Notist
On this page
  1. Never 与 panic
  2. Never:没有正常返回值
  3. 求值时机
  4. 诊断与边界

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 协议,不伪装成用户错误值。