Never 与 panic
panic(message: String) -> Never 中止当前计算,并以 message 生成诊断。其他独立内容仍可继续呈现。
Never:没有正常返回值
Never 是不含任何值的数据类型,既不是 Unit,也不是 Result。没有对应的字面量或运行期 Value 变体。函数可以声明返回 Never,但其实现不能正常返回任意值:
fn stop(message: String) -> Never { panic(message) }
不返回的表达式可以占据正常值位置;分支合并时 Never + T 得到 T,两个不返回分支则仍为 Never。因此 Result 的“错误变诊断”可以用普通 Code 写出:
// 使用 match 和 panic 定义 expect。
fn expect<T: Type>(value: Result<T, String>) -> T {
match value {
ok(v) => v,
err(message) => panic(message),
}
}
容器类型按完整类型区分。例如 Result<Never, String> 与 Result<Int, String> 不同型,前者只能构造 err。
Never 可用作编译期 Type 表达式和类型默认值。
Option<Never>可有 none,Array<Never>可为空,Result<Never, E>可有 err;None、空数组与 err 本身都不是 Never 值。Never subject 的 match 没有可到达的臂,允许空 match:
fn absurd(value: Never) -> String { match value {} }。不返回的实参不能为泛型提供正常值的推断证据;其他实参或显式
<T>仍须确定类型参数。
求值时机
普通检查只验证 panic 的签名与消息类型,不运行它。运行期只有选中的分支会执行:
fn label(valid: Bool) -> String {
if valid { "valid" } else { panic("invalid input") }
}
数据计算执行到 panic 就停止。逻辑运算保持短路:false && panic("unused") 和 true || panic("unused") 不触发 panic。
已经构造但尚未挂载的内容仍保持惰性:
fn unused() -> InlineContent {
let hidden = [#panic("not mounted")];
[kept]
}
内容函数的实参在挂载时求值。直接写 let stopped = panic("stop") 则立即中止当前 Code 计算。不可到达的后续源码仍接受语法与类型检查。
诊断与边界
失败在最近的内容错误边界生成诊断。
消息允许是运行期生成的 String;诊断指向实际 panic 调用,运行期错误节点保留 Code 包装函数与文档挂载的展开链。
预览可以保留其他独立内容;严格发布仍因错误失败,不发布错误的部分构建结果。
Code 内容字面量支持
#panic("message")插值;独立 Markup 中需调用一个返回 Content 的 Code 包装函数。
compile_error 是检查期操作,要求已知消息,检查器访问到它就报告错误;panic 是求值期操作。显式 comptime 或必须计算的编译期实参执行到 panic 时,报告发生在该阶段,位置仍指向内部 panic 调用。
Result 的 err 是普通可处理值,不会自动触发 panic。反过来,Result 的 match 也不能捕获 panic 或预算耗尽。输入未准备使用宿主 NeedResources 协议,不伪装成用户错误值。