derive

std.derive

fun check

pub fun check[T]();

拒绝此处派生(derive)不遍历的每一种字段形态

这是集中在一处的分类契约。每个派生在自身遍历前都会调用它,因此被拒绝的记录会使构建失败并输出针对该字段形态的错误信息,而不是通过叶子动作刚好先触及的某个内禀(intrinsic)报错。它是 pub 的,以便手写的派生也能遵循相同的规则。

其函数体完全在编译期(comptime):每个分支要么为空,要么是一个 $error,因此被接受的 T 会被编译为一个空函数。发布流水线会消除该调用;在 -O0 下,派生只需付出一次函数调用的开销。

[T]:要分类的记录类型

fun eq

pub fun eq[T](a: *T, b: *T) bool;

对记录的字段进行结构化相等性比较

按字段逐个比较 ab,深入嵌套记录,并在首次不匹配时返回 false。没有任何字段的记录比较结果为相等。 每个字段都必须可以通过分类(参见 check);联合类型(union)、引用、数组或 ^ 秘密字段在编译期都会触发 $error

[T]:要比较的记录类型 a:第一个记录 b:第二个记录 v:返回值,当每个字段在每一层深度上都比较相等时为 true

fun hash

pub fun hash[T](v: *T) u64;

对记录的字段进行 FNV-1a 哈希计算

按照声明顺序将每个字段的值折叠到 64 位累加器中,并深入嵌套记录,因此嵌套字段的贡献与扁平化字段完全相同。 比较为 eq 的两个记录会产生相同的哈希值,因为它们以相同的顺序遍历相同的字段。其适用性与 eq 相同。

[T]:要哈希的记录类型 v:要哈希的记录 返回值:64 位哈希值

fun clone

pub fun clone[T](dst: *T, src: *T);

按字段将 src 复制到 dst

此操作对于 dst = src 的价值在于“拒绝”而非“复制”:每个字段都能分类的记录,其成员逐个复制不会出错,因此 clone[T] 的成功编译即证明结构化复制是完全复制。 如果某个字段仅会被浅层复制(例如指向所有权存储的引用)——则无法分类,构建会失败,而不会返回一个与第一个记录内存别名的第二个记录。

带有所有权的克隆会追踪引用、因此会分配内存且可能失败,这是一个单独的成员。briar-systems/mach#2693(mach 4.15.0)提供了它所需的遍历能力,因此它目前还在等待的是一个携带分配器和错误的签名,而不是编译器功能。

[T]:要复制的记录类型 dst:目标记录,按字段覆盖 src:源记录

fun fmt

pub fun fmt[T](w: *writer.Writer, v: *T) Result[usize, str];

将记录以 Type{field=value, ...} 的形式写入写入器

按声明顺序将每个字段渲染为 name=value,以 , 分隔,并将值格式化委托给 format。嵌套记录渲染为 name=Type{...},因此 Player{pos=Vec3{x=1, y=2, z=3}, id=7} 只需一次调用。 类型拼写来自 $type_name(语义分析器自身的诊断权威),因此打印出来的名称和错误中的名称不会产生偏差。

此格式化程序将 `^` 秘密字段打印为普通值,无法做到其他处理。 目前挽救它的是秘密字段无法通过分类,因此 check[T] 会使构建失败,而不会让秘密字段蒙混过关——请参阅关于秘密字段的模块说明。请不要将其误解为敏感信息消减(redemption/redaction):这里没有任何代码识别秘密字段,支持敏感信息感知的 fmt 正在等待 briar-systems/mach#2694

其适用性与 eqhash 相同。

[T]:要渲染的记录类型 w:目标写入器 v:要渲染的记录 返回值:总写入字节数,或错误消息