附录 B:背景话题
本节涵盖了本指南中出现的常见编译器术语。我们会在某些特定于 Rust 的上下文中给出这些术语的一般定义。
什么是控制流图?
控制流图(control-flow graph)是编译器中常见的术语。如果你曾使用过流程图, 那么控制流图的概念对你来说会很熟悉。它是程序的一种表示方式, 能够以非常清晰的方式展现底层控制流。
控制流图由以边相连的一组基本块(basic block)构成。基本块的主要概念是 一组「一起」执行的语句,也就是说,只要你的分支跳到了基本块, 它就会从头到尾依次执行所有的语句。只有到基本块的最后才有可能分支到更多地方 (在 MIR 中,我们将最后一条语句称作终止句(terminator)):
bb0: {
statement0;
statement1;
statement2;
...
terminator;
}
你在 Rust 中使用的很多表达式都会编译成多个基本块。例如,考虑以下 if 语句:
a = 1;
if some_variable {
b = 1;
} else {
c = 1;
}
d = 1;
它会被编译成四个基本块
BB0: {
a = 1;
if some_variable { goto BB1 } else { goto BB2 }
}
BB1: {
b = 1;
goto BB3;
}
BB2: {
c = 1;
goto BB3;
}
BB3: {
d = 1;
...;
}
在使用控制流图时,循环会简单地作为一个图中的环路出现,而 break
关键字则会被翻译成跳出此环路的一条路径。
什么是数据流分析?
静态程序分析(Static Program Analysis), 作者 Anders Møller 和 Michael I. Schwartzbach,它是一个绝佳的资源。
to be written
什么是「全称量化」?「存在量化」呢?
to be written
什么是协变和逆变?
详见 Rust 秘典 中的子定型(Subtyping)一章。
关于类型检查器如何处理型变的更多信息见本指南的 型变(variance)一章。
什么是「自由生存域」和「自由变量」?「约束生存域」呢?
我们来描述一下程序变量的自由和约束的概念,因为它们是我们最熟悉的概念。
-
考虑此表达式,它创建了一个闭包:
|a, b| a + b
。在这里,a + b
中的a
和b
指代该闭包被调用会时传入的参数。我们称a
和b
在该闭包中是 被约束(bound)的,而闭包签名|a, b|
是名字a
和b
的约束位(binder) (因为对a
或b
的任何引用都是指代它引入的变量)。 -
考虑此表达式
a + b
。在该表达式中,a
和b
均指代定义在该表达式之外 的局部变量。我们称这些变量在该表达式中自由出现(appear free) (即它们是**自由(free)的,而非被约束(bound)**的(被束缚的))。
所以现在你理解了:在某些「表达式、语句、还是别的什么」中的变量, 如果指代的是定义在该「表达式、语句、还是别的什么」之外的东西,那么它们就是 「自由出现」的。我们可以等价地称之为表达式中的「自由变量」, 毕竟它们就是一组「自由出现」的变量而已。
那么,它们与生存域(region)有什么关系呢?我们可以将类似的概念应用到类型和生存域上来。
例如,在类型 &'a u32
中,'a
是自由出现的。但在类型 for<'a> fn(&'a u32)
中则不是。