附录 C:术语表

编译器中使用了大量...怪异的缩写和词汇。本术语表旨在列出它们并提供一些解释和指引, 以便您更好地理解它们。

中文术语含义
ASTASTsyntax crate 产生的抽象语法树(Abstract Syntax Tree),它非常严格地反映了用户使用的语法。
约束位binder「约束位」是变量和类型声明的位置。例如,<T> 是泛型形参 Tfn foo<T>(..) 中的约束位,而 |a| ... 是形参 a 的约束位。详见背景材料
约束变量bound variable「约束变量」是在表达式/项中声明的变量。例如,变量 a 就是闭包表达式 |a| a * 2 中的约束变量。详见背景材料
codegencodegen将 MIR 翻译成 LLVM IR 的代码。
codegen 单元codegen unit在产生 LLVM IR 时,我们会将 Rust 代码分成几组 codegen 单元。这些单元中的每一个都由 LLVM 独立处理以实现并行性。它们也是增量重用的单位。
完备性completeness完备性是类型论中的技术术语。完备性表示每个类型安全的程序都能通过类型检查。兼顾可靠性(Soundness)和完备性是非常困难的,通常可靠性更加重要(见「可靠性」)。
控制流图control-flow graph程序控制流的一种表示方法。详见背景材料
CTFECTFE即编译期函数求值(Compile-Time Function Evaluation)。这是编译器在编译期求值 const fn 的能力。它是编译器常量求值系统的一部分(详情)。
cxcx我们倾向于用「cx」作为上下文(context)的简写。另见 tcxinfcx 等。
DAGDAG即有向无环图(directed acyclic graph),在编译时用于跟踪查询之间的依赖关系(详情)。
数据流分析data-flow analysis静态分析可用来确定程序控制流中每个节点的属性是否正确。详见背景材料
DefIdDefId一个标识定义的索引(见 librustc/hir/def_id.rs)。用于唯一地标识一个 DefPath
双指针Double pointer带有附加元数据的指针。详见「胖指针」。
drop glue1drop glue(内部)编译器生成的指令,用于操纵对数据类型调用析构器(Drop)。
DSTDST动态大小的类型(Dynamically-Sized Type)。编译器无法静态地获知该类型在内存中的大小(例如 str[u8])。这种类型并未实现 Sized 且无法在栈上分配。它们只能作为结构体中的最后一个字段,且只能通过指针来使用(如 &str&[u8])。
先界定的生命周期early-bound lifetime生存域在定义的位置被代换的生命周期。在元项的 Generics 中界定并通过 Substs 来代换。与后界定生命周期相对(详情)。
空类型empty type见「不可居留类型」
胖指针Fat pointer一种两个字宽的指针,它保存了某个值的地址,以及使用该值所需的额外的信息。Rust 包含两种「胖指针」,分别是切片的引用和特质对象。切片的引用保存了切片的起始地址和长度。特质对象保存了一个值的地址和一个与该值对应的,指向该特质的实现的指针。「胖指针」也被称为「宽指针」或「双指针」。
自由变量free variable「自由变量」即不在表达式或项中约束的变量。详见背景材料
'gcx'gcx即全域生命周期(详情)。
泛型(复数)generics即一组在类型或元项上定义的泛型形参。
HIRHIR上层 IR,将 AST 降级并脱糖(desugar)后产生(详情)。
HirIdHirId由一个 def-id 与一个「定义内偏移(intra-definition offset)」结合产生,用于在 HIR 中标识一个特定的节点。
HIR 映射HIR MapHIR 映射,通过 tcx.hir 访问,能够让你在 HIR 中快速导航,并在多种标识符之间互相转换。
ICEICE内部编译器错误(internal compiler error),在编译器崩溃时产生。
ICHICH增量编译散列值(incremental compilation hash)。ICH 作为 HIR 或 crate 元数据之类的指纹,用于检查它们是否被修改。它在增量编译时可用于检测 crate 的某部分是否被修改,确定是否应重新编译。
推导变量inference variable「推导变量」是一种特殊的类型/生存域,在进行类型或生存域推导时,它用来表示尝试推导的东西。类比于代数中的 x。例如,如果我们尝试推导程序中某个变量的类型,那么就要创建一个推导变量来表示该未知的类型。
infcxinfcx推导上下文(见 librustc/infer
存留intern「存留」指先将确定且常用的常量数据(如字符串)存储下来,然后用标识符(例如一个 Symbol)来引用它,而非直接使用数据本身,以此节省内存。
IRIR中间表示(Intermediate Representation)。编译器中一种通用的形式。在编译过程中,代码会从原始源码(ASCII 文本)转换为多种 IR。在 Rust 中,它们主要是 HIR、MIR 和 LLVM IR。每种 IR 都适用于某种计算集合。例如,MIR 适用于借用检查器,而 LLVM IR 则适用于 codegen,因为 LLVM 可以接受它。
IRLOIRLOIRLOirlo 有时用作 internals.rust-lang.org 的缩写。
元项item语言中的一种「定义」,例如 static、const、use 语句、模块、结构体等等。具体来说,它对应与 Item 类型。
语言元项lang item表示语言本身固有概念的元项,其中包括:特殊的内建特质如 SyncSend;表示操作的特质如 Add,由编译器调用的函数(详情)。
后界定的生命周期late-bound lifetime生存域在调用的位置被代换的生命周期。在 HRTB 中界定并通过编译器中特定的函数来代换,例如 liberate_late_bound_regions。与先界定生命周期相对(详情)。
局部 cratelocal crate当前正在编译的 crate。
LTOLTO链接期优化(Link-Time Optimizations)。一组由 LLVM 提供的优化,它只在最后链接二进制文件时执行。其中包括移除最终程序中不会被使用的函数等多种优化。ThinLTO 是 LTO 的一种变体,旨在提高可扩展性和效率,但可能会牺牲一些优化。您也可以阅读 Rust 源码库中关于「FatLTO」的 Issue。「FatLTO」是为非 Thin LTO 的别称。LLVM 文档:ltothinlto
LLVMLLVM(其实不算缩写 :-P)一个开源的编译器后端。它接受 LLVM IR 并输出原生二进制程序。很多编程语言(如 Rust)都可以实现一个输出 LLVM IR 的编译器前端,并用 LLVM 将该语言编译到所有 LLVM 支持的平台上。
记忆化memoize记忆化是一种将计算结果(如纯函数调用的计算结果)存储起来以避免重复计算的方法。这是一种典型的执行速度和内存使用间的权衡。
MIRMIR中层 IR,在通过 borrowck 和 codegen 进行类型检查后产生(详情)。
mirimiri一个 MIR 解释器,用于常量求值(详情
正规化normalize常用术语,表示转换为更典范的形式,不过在 rustc 中一般指关联类型的正规化
新类型newtype「新类型」是对其它类型的包装(例如,struct Foo(T) 就是 T 的「新类型」)。在 Rust 中它通常用于为索引提供一种更强的类型。
NLLNLL非词法生命周期(non-lexical lifetimes),Rust 借用系统的一个扩展,使其基于控制流图。
node-id 或 NodeIdnode-id or NodeId用于在 AST 或 HIR 中标识特定节点的索引,之后会被逐步淘汰并以 HirId 代之。
(证明)义务obligation必须被特质系统证明的东西(详情)。
投影projection常用术语,表示「相对路径」,例如 x.f 是一种「字段投影」,而 T::Item 是一种「关联类型投影」。
被提升常量promoted constants从函数中提取并提升到静态作用域的常量。更多详情见此节
提供者provider用于执行查询的函数(详情)。
量化quantified在数学和逻辑学中,存在量化和全称量化用于提出像「是否存在类型 T 使其为真?」或「对于所有的类型 T 它是否都为真?」这样的问题。详见背景材料
查询query在编译器可能存在的子计算过程(详情)。
生存区region生命周期的另一个术语,通常在书面用于或借用检查器中出现。
rib2rib名字求解器中的一种数据结构,用于跟踪多个名字所处的同一作用域(详情)。
sesssess编译器会话(session),用于存储整个编译期间使用的全局数据。
副表side tables由于 AST 和 HIR 一旦创建即不可变,因此我们通常以散列表的形式保存关于它们的额外的信息,并以特定节点的 id 来索引。
符文sigil类似于关键字,但完全由非字母或数字的标记组成。例如,& 是一个表示引用的符文。
占位符placeholder注意:skolemization 已被 placeholder 取代。 一种处理「for-all」类型(例如 for<'a> fn(&'a u32))的子定型(subtyping)以及解决高阶特质界定(HRTB,higher-ranked trait bounds,例如 for<'a> T: Trait<'a>)的方式。详见占位符与全域一节。
可靠性soundness可靠性是类型论中的技术术语。大致来说,如果一个类型系统是可靠的,且一个程序可通过类型检查,那么它就是类型安全的。例如,在 Safe Rust 中,我们无法将一个值强制赋予一个类型不匹配的变量(见「完备性」)。
(代码)区段span用户源码中的位置,主要用于错误报告。它是个形如「文件名/行/列」的元组,保存了起点/终点,也用于跟踪宏展开和编译脱糖(desugar)。所有这些都被打包成几个字节(实际上,它只是个表的索引)。更多信息见 Span 数据类型。
substssubsts对给定泛型类型或元项的代换(例如 HashMap<i32, u32> 中的 i32u32)。
tcxtcx即类型上下文(typing context),编译器的主要数据结构(详情)。
'tcx'tcx当前正在活动的推导上下文的生命周期(详情)。
特质引用trait reference带有合适的输入类型/生命周期集合的特质的名字(详情)。
(词法)标记token语法解析的最小单元。词法标记是分词后的产物(详情)。
TLSTLS线程局部的存储(Thread-Local Storage)。定义的变量在每个线程中都有各自的一份副本(而非所有线程共享一份副本)。它会与 LLVM 有一些交互。不是所有平台都支持 TLS。
transtrans将 MIR 翻译为 LLVM IR 的代码。重命名为 codegen。
特质引用trait reference特质及其类型形参的值(详情)。
tyty类型(type)的内部表示(详情)。
UFCSUFCS全域函数调用(Universal Function Call Syntax)。一种无歧义的调用方法的语法(详情)。
不可居留类型uninhabited type一种 无值 的类型。它与 ZST 不同,ZST 有刚好一个值。不可居留类型的一个例子是 enum Foo {},它没有任何变体,因此无法被创建。编译器会将不可居留类型的的代码视作死代码,因此没有这样的值可被处理。!(即 never 类型)是一个不可居留类型。不可居留类型也叫做「空类型」。
upvarupvar由闭包外部的闭包捕获的变量。
型变variance形变决定了泛型形参/生命周期形参的改变如何影响其子定型;例如,若 TU 的子类型,则 Vec<T>Vec<U> 的子类型,因为 Vec 对其泛型形参是 协变(covariant) 的。更一般的解释见背景材料型变一章阐述了类型检查是如何处理型变的。
宽指针Wide pointer带有附加数据的指针。详见「胖指针」。
ZSTZST零大小类型(Zero-Sized Type)。值的大小为 0 字节的类型。由于 2^0 = 1,因此这种类型只能有刚好一个值。例如,()(单元类型)就是一个 ZST。struct Foo; 也是一个 ZST。编程器可对 ZST 做出良好的优化。

译注:

1

这里用了个双关。Drop 即 Rust 中的析构器 trait,用 drop() 方法来清理掉脱离作用域的值; glue 即胶水代码,用来粘合或填平不同的操作。drop glue 本意是滴胶,而 drop 又有删除,去掉的意思。 到这里则引申出了,它是编译器生成的,用来做清理(drop)的胶水(glue)指令的意思。

2

rib 本意是胸腔的肋骨,形状是从上往下逐渐增大,很像作用域由内向外层层扩大。 然而不同于环状的是,它还有一个高度。作用域有个特点,就是即便一个作用域在另一个作用域之内, 那么内部作用域里的变量也并不总是能访问外部作用的变量,有可能内部有个同名的变量把外部的屏蔽了。 解决方案是,引入一个高度,让它变成个自上而下逐级变大的「栈」,并规定同级的内层可访问外层。 如果内部能直接访问外部变量,那么它们在同一级上,作用域只分内外层; 否则,就把内部的变量升高一级。在中文语境中,把它比作等高线或者汉诺塔似乎更加贴切。