读取错误
典型的错误如下所示:
error[NAM003]: Unknown identifier
unknown identifier 'message'
examples/hello.0:2:27
2 | check world.out.write(message)
| ^^^^^^^
rule: Names must be declared before use in the current lexical scope.
expected: local binding, parameter, function, builtin value
actual: no visible symbol named 'message'
fix: Introduce a local binding before this use (local-edit)
explain: zero explain NAM003从上到下阅读:
- 第一行给出稳定的错误代码和简短标题。
- 消息说明出了什么问题。
- 位置信息指向文件、行号和列号。
- 源码摘录标记了确切的词元。
rule、expected和actual解释了不匹配的原因。fix给出最安全的修复方案。explain指向更深入的帮助信息。
在这个例子中,程序尝试写入 message 但未声明它。添加一个局部绑定即可修复:
pub fn main Void world World ! let message "hello from zero\n" check world.out.write message默认纯文本输出
默认的诊断信息应该简短且在终端日志中有用。
默认情况下不应包含 ANSI 颜色、粗体样式、超链接、OSC 转义序列或终端控制序列。这些字节会膨胀代理上下文,使日志更难比较。
使用:
zero check examples/hello.0面向工具的 JSON 输出
JSON 是显式的。在代理、CI、编辑器、深度分析和需要稳定结构化数据的工具中使用 --json。
zero check --json examples/hello.0原生 JSON 格式是版本化的:
{
"schemaVersion": 1,
"ok": false,
"diagnostics": [
{
"severity": "error",
"code": "NAM003",
"message": "unknown identifier 'message'",
"path": "examples/hello.0",
"line": 2,
"column": 27,
"length": 7,
"expected": "visible local, parameter, function, or builtin",
"actual": "no visible symbol named 'message'",
"help": "declare the name before using it",
"fixSafety": "behavior-preserving",
"repair": {
"id": "manual-review",
"summary": "Inspect the diagnostic fields and choose a repair manually."
},
"related": []
}
]
}修复安全性
修复带有安全性标签,以便代理知道何时可以自动执行:
format-only:仅更改格式behavior-preserving:保持程序行为不变local-edit:局限于当前局部作用域或文件api-changing:更改函数签名、导出名称、包 API 或调用点requires-human-review:有风险或模糊;展示计划但不要自动应用
当前原生诊断
原生编译器为已实现的控制流和类型规则维护稳定的错误代码:
PAR100:解析器语法错误,例如缺少大括号、逗号或格式错误的类型参数列表NAM003:未知标识符NAM004:重复名称、错误调用参数数量或泛型类型名称遮蔽IMP001:未知的包本地导入,修复 id 为fix-import-pathIMP002:包本地导入循环IMP003:跨导入模块的重复公共导出PKG001:本地包依赖路径不包含zero.jsonPKG002:包依赖形成循环PKG003:一个包名解析到冲突的版本PKG004:包依赖不支持所选目标平台BLD002:错误的项目清单或不支持的清单目标格式ERR002:调用方的显式错误集缺少被调用方抛出的错误ERR003:可失败调用未使用check或rescueABI001:不支持的 C ABI 导出或外部布局接口CIMP003:外部目标的 C 依赖会使用宿主的 include 路径、宿主库路径或隐式宿主pkg-config发现BOR001:词法借用冲突,JSON 中borrowTrace.activeBorrows条目命名每个报告的借用根、路径、类型、活跃绑定、 已知时的声明范围和修复方案。如果报告达到上限,borrowTrace.truncated为 true。BOR002:引用来源逃逸,包括从调用返回的引用或通过可变参数存储写入的引用OWN001:移动后使用拥有值,或会拥有不受约束的泛型载荷的泛型容器TYP010:条件必须为BoolTYP002:赋值、字面量、返回或类型默认值中的类型不匹配TYP011:null需要Maybe<T>上下文TYP012:break需要封闭的循环TYP013:continue需要封闭的循环TYP014:范围循环边界必须与整数兼容TYP015:整数字面量必须使用有效的数字、分隔符、基数前缀和整数后缀TYP016:整数字面量必须适合预期的原始整数宽度TYP017:as转换仅限于原始数值和字节char源类型与目标类型TYP018:字符字面量必须恰好包含一个字节或支持的字节转义序列TYP019:浮点字面量必须使用digits "." digits格式,可带可选指数TYP020:浮点字面量必须适合预期的原始浮点宽度TYP021:索引、切片和索引赋值需要支持该操作的目标TYP022:索引表达式和存在的切片边界必须为整数TYP023:泛型调用类型参数数量不匹配,或在非泛型函数上使用类型参数TYP024:泛型推断为某个类型参数发现了冲突的具体类型TYP025:无法从局部调用参数推断泛型类型参数TYP026:类型别名重复、格式错误或循环TYP027:递归泛型调用更改了类型参数PUB001:公共声明缺少必需的显式 API 类型元数据MET001:解析的meta表达式请求了当前编译器版本尚无法求值的编译时行为IFC001:接口约束未知,或具体类型参数没有静态类型体IFC002:受约束的具体类型缺少必需的静态接口方法IFC003:具体静态方法的参数数量与接口不匹配IFC004:具体静态方法的返回类型与接口不匹配IFC005:具体静态方法的参数类型与接口不匹配STC001:静态值参数使用了不支持的非整数类型STC002:静态值参数不是整数字面量或确定性的顶层常量STC003:显式静态值参数与带注解类型所携带的值冲突SHM001:泛型类型方法调用无法推断继承的类型/静态参数SHM002:泛型类型方法的参数隐含了冲突的Self实例化RCV001:接收者风格调用了未知方法或没有self的静态方法RCV002:接收者风格调用需要可寻址的接收者,或mutref<Self>需要可变接收者FLD001:类型字面量包含未知字段FLD002:类型字面量省略了没有默认值的必需字段TAR001:请求的目标名称不在zero targets中TAR002:所选目标平台未提供程序所需的能力- 边界检查失败:原生可执行文件在索引、索引赋值或切片范围超出基础
长度时打印
zero bounds check failed并 中止。 MAT004:match 分支只能为携带载荷的选择分支绑定载荷
标准库诊断
标准库模块使用与编译器诊断相同的结构化诊断约定。
MEM001报告格式错误的内存类型形式,例如Maybe缺少其必需的类型参数。std.parse、std.json和std.env诊断在适用的地方携带源码位置信息。std.time诊断可以对单词元输入使用仅偏移量的位置信息。- 标准库错误代码保持稳定且包本地化,
zero explain <code>提供人工指导,--json暴露结构化修复元数据。
常见修复方案
托管的文件系统辅助工具在当前编译器中仅限宿主平台。在非宿主目标上会明确失败:
bin/zero check --json --target linux-musl-x64 conformance/native/fail/std-fs-target-unsupported.0该诊断使用 TAR002、fixSafety: "requires-human-review" 和修复
id choose-target-with-required-capability。
规范的修复方式是为具有所需能力的目标构建,或将该代码移至特定目标的入口点之后。
可写字节辅助工具需要可变存储:
let dst [4]u8 [0, 0, 0, 0]let src [4]u8 [122, 101, 114, 111]let _copied std.mem.copy dst src这会报告 TYP009,修复 id 为 make-binding-mutable。规范修复为:
mut dst [4]u8 [0, 0, 0, 0]let src [4]u8 [122, 101, 114, 111]let _copied std.mem.copy dst src命名错误的 std.fs 调用需要显式错误流:
let file std.fs.createOrRaise fs ".zero/out.txt"这会报告 ERR003,修复 id 为 check-or-rescue-fallible-call。
使用 check 并在调用方的 ![NotFound TooLarge Io] 集合中包含 NotFound、TooLarge 和 Io。当调用需要就地恢复时,局部使用 rescue。
泛型调用仅使用局部推断。以下代码会失败,因为 T 需要同时为 i32 和 u8:
fn first<T: Type> T left T right T ret left let value i32 first 1 2_u8修复方式是使参数一致,或传入具有兼容值的显式类型参数:
let value i32 first<i32> 1 2公共常量需要显式 API 形状:
pub const answer 42这会报告 PUB001。保持行为的修复为:
pub const answer i32 42C 互操作将宿主和目标发现分开。以下代码在跨目标时失败,因为清单请求了宿主 include/库发现:
bin/zero build --json --target linux-musl-x64 conformance/c/host-leak-package --out .zero/out/host-leak-package这会报告 CIMP003,修复 id 为 configure-target-c-dependency。
规范的修复方式是使用包相对的供应商头文件/库,或配置目标 sysroot。不要依赖宿主 include 路径、宿主库路径或宿主 pkg-config 发现进行跨目标构建。
包依赖诊断是图级别的修复:
| 代码 | 含义 |
|---|---|
PKG001 | 本地依赖路径错误或缺失。 |
PKG002 | 两个包清单相互循环依赖。 |
PKG003 | 图将一个包名解析为多个版本。 |
PKG004 | 所选目标平台不在依赖的目标列表中。 |
这些都使用 requires-human-review,因为正确的修复可能更改
包拓扑或目标支持。
类型别名是编译时的拼写,不能循环:
alias A B alias B A这会报告 TYP026。将别名指向具体类型(如 Span<u8>)或移除循环。
不支持的编译时执行报告 MET001,例如
const os String meta target.os,直到目标事实在原生编译器中实现。
泛型类型方法必须从具体的 Self 值或显式类型参数进行特化:
type FixedVec<T: Type, static N: usize> fn cap usize ret N let cap FixedVec.cap()这会报告 SHM001。
通过以下两种方式之一修复:
- 传入显式类型参数,例如
FixedVec.cap<u8, 4>() - 调用接收具体
Self值的方法,例如FixedVec.push(&mut vec, value)或vec.push(value)
SHM002 表示显式方法参数与接收者的注解类型不一致。
接收者调用需要第一个参数为 self: ref<Self> 或 self: mutref<Self> 的已声明方法:
let vec FixedVec<u8,4> FixedVec . len 0 items [0, 0, 0, 0]check vec.push 1这会报告 RCV002,因为 push 需要 mutref<Self> 而 vec 是
不可变的。
未知的接收者方法报告 RCV001。没有 self 的静态方法应
通过类型命名空间调用。
类型字段默认值允许省略字段,但仅当声明提供了兼容的默认值时:
type NeedsItem count usize 0 item u8 let value NeedsItem NeedsItem .这会报告 FLD002,修复 id 为 initialize-missing-field,因为 item
没有默认值。类型错误的默认值会在默认值表达式处报告 TYP002。
静态接口在泛型特化时检查。以下代码失败,因为 Counter 未提供所需的静态方法:
interface Readable<T: Type> fn read i32 self ref<T> type Counter value i32 fn readValue<T: Readable<T>> i32 value ref<T> ret T.read value这会报告 IFC002。添加具有匹配签名的具体静态方法:
fn read i32 self ref<Self> ret self.value静态值参数在发射前检查,以便固定大小的布局保持具体:
type FixedVec<T: Type, static N: usize> len usize items [N]T fn first<T: Type, static N: usize> T vec ref<FixedVec<T,N>> ret vec.items[0] let vec FixedVec<u8,4> FixedVec . len 4 items [1, 2, 3, 4]let bad first<u8, 8> (&vec)这会报告 STC003,因为显式的 8 与注解的
FixedVec<u8,4> 冲突。
相关的静态值诊断:
STC001:不支持的静态参数类型STC002:在需要编译时整数的地方使用了运行时值
命令
zero check <input>:默认以人类优先的纯文本输出zero check --json <input>:完整的诊断 JSONzero explain <code>:诊断代码的人类可读解释zero explain <code> --json:机器可读的解释zero fix --plan --json <input>:提议的类型化修复,不编辑文件
实用示例:
zero explain TAR002
zero explain --json TYP009
zero fix --plan --json conformance/native/fail/mem-copy-immutable-dst.0
zero fix --plan --json --target linux-musl-x64 conformance/native/fail/std-fs-target-unsupported.0