术语表
抽象语法树
“抽象语法树“或“AST“是编译器编译程序时程序结构的中间表示。
对齐
值的对齐指定值首选从哪些地址开始。始终是 2 的幂。对值的引用必须是对齐的。更多信息。
应用程序二进制接口 (ABI)
应用程序二进制接口 (ABI) 定义了编译后的代码如何与其他编译后的代码交互。使用 [extern 块]和 extern fn 时,ABI 字符串影响:
- 调用约定:如何传递函数参数、返回值(例如在寄存器中还是在栈上),以及谁负责清理栈。
- 展开:是否允许栈展开。例如,
"C-unwind"ABI 允许跨 FFI 边界展开,而"C"ABI 不允许。
元数
元数指的是函数或运算符接受的参数数量。例如,f(2, 3) 和 g(4, 6) 的元数为 2,而 h(8, 2, 6) 的元数为 3。! 运算符的元数为 1。
数组
数组,有时也称为固定大小数组或内联数组,是描述元素集合的值,每个元素由程序在运行时可计算的索引选择。它占据连续的内存区域。
关联项
关联项是与另一个项关联的项。关联项在实现中定义,在 trait 中声明。只有函数、常量和类型别名可以被关联。与自由项对比。
全面实现
任何类型出现未覆盖的实现。impl<T> Foo for T、impl<T> Bar<T> for T、impl<T> Bar<Vec<T>> for T 和 impl<T> Bar<T> for Vec<T> 被视为全面实现。然而,impl<T> Bar<Vec<T>> for Vec<T> 不是全面实现,因为此 impl 中出现的所有 T 实例都被 Vec 覆盖。
约束
约束是对类型或 trait 的限制。例如,如果对函数接受的参数设置了约束,则传递给该函数的类型必须遵守该约束。
组合子
组合子是高阶函数,只应用函数和先前定义的组合子来从其参数提供结果。它们可用于以模块化方式管理控制流。
Crate
Crate 是编译和链接的单元。有不同类型的 crate,例如库或可执行文件。crate 可以链接和引用其他库 crate,称为外部 crate。crate 具有自包含的模块树,从称为 crate 根的未命名根模块开始。通过在 crate 根中将项标记为公开,可以使它们对其他 crate 可见,包括通过公开模块的路径。更多信息。
分派
分派是当涉及多态性时确定实际运行哪个特定版本代码的机制。两种主要的分派形式是静态分派和动态分派。Rust 通过使用 trait 对象支持动态分派。
动态大小类型
动态大小类型 (DST) 是没有静态已知大小或对齐的类型。
实体
实体是一种语言构造,可以在源程序中以某种方式引用,通常通过路径。实体包括类型、项、泛型参数、变量绑定、循环标签、生命周期、字段、属性 和 lints。
表达式
表达式是值、常量、变量、运算符和函数的组合,求值为单个值,有或没有副作用。
例如,2 + (3 * 4) 是一个返回值 14 的表达式。
自由项
基础 trait
基础 trait 是为其添加现有类型的实现是破坏性更改的 trait。Fn trait 和 Sized 是基础的。
基础类型构造器
基础类型构造器是在其上实现全面实现是破坏性更改的类型。&、&mut、Box 和 Pin 是基础的。
每当类型 T 被视为本地时,&T、&mut T、Box<T> 和 Pin<T> 也被视为本地。基础类型构造器不能覆盖其他类型。每当使用术语“覆盖类型“时,&T、&mut T、Box<T> 和 Pin<T> 中的 T 不被视为覆盖。
已居住
如果类型有构造函数,因此可以被实例化,则该类型是已居住的。已居住类型不是“空的“,因为可以有该类型的值。与未居住相反。
固有实现
固有方法
已初始化
如果变量已被赋值且之后未被移出,则该变量是已初始化的。所有其他内存位置都被假定为未初始化的。只有 unsafe Rust 可以在不初始化的情况下创建内存位置。
本地 trait
在当前 crate 中定义的 trait。trait 定义是否本地与应用的类型参数无关。给定 trait Foo<T, U>,Foo 始终是本地的,无论 T 和 U 替换为什么类型。
本地类型
在当前 crate 中定义的 struct、enum 或 union。这不受应用的类型参数影响。struct Foo 被视为本地,但 Vec<Foo> 不是。LocalType<ForeignType> 是本地的。类型别名不影响本地性。
模块
模块是零个或多个项的容器。模块组织成树状结构,从根处称为 crate 根或根模块的未命名模块开始。路径可用于引用其他模块中的项,这可能受到可见性规则的限制。更多信息
名称
名称是引用实体的标识符或生命周期或循环标签。名称绑定是实体声明引入与该实体关联的标识符或标签时发生的情况。路径、标识符和标签用于引用实体。
名称解析
命名空间
命名空间是根据名称引用的实体类型对声明的名称进行的逻辑分组。命名空间允许一个命名空间中的名称出现与另一个命名空间中的同名名称不冲突。
在命名空间内,名称按层次结构组织,其中层次结构的每一级都有自己的命名实体集合。
具名类型
可以直接通过路径引用的类型。具体来说是枚举、结构体、联合体和 trait 对象类型。
Dyn 兼容 trait
可以在 trait 对象类型(dyn Trait)中使用的 Trait。只有遵循特定规则的 trait 才是dyn 兼容的。
这些以前称为对象安全 trait。
路径
路径是一个或多个路径段的序列,用于引用当前作用域或命名空间层次结构其他级别的实体。
Prelude
Prelude 或 Rust Prelude 是一小部分项(主要是 trait)的集合,被导入到每个 crate 的每个模块中。prelude 中的 trait 是普遍存在的。
作用域
审查者
审查者是在 match 表达式和类似模式匹配构造中匹配的表达式。例如,在 match x { A => 1, B => 2 } 中,表达式 x 是审查者。
大小
值的大小有两个定义。
第一个是存储该值必须分配多少内存。
第二个是具有该项类型的数组中连续元素之间的字节偏移量。
它是对齐的倍数,包括零。大小可能因编译器版本(随着新优化的进行)和目标平台(类似于 usize 如何因平台而异)而变化。
更多信息。
切片
切片是连续序列的动态大小视图,写为 [T]。
它通常以其借用形式出现,可变或共享。共享切片类型是 &[T],而可变切片类型是 &mut [T],其中 T 表示元素类型。
语句
语句是编程语言中命令计算机执行操作的最小独立元素。
字符串字面量
字符串字面量是直接存储在最终二进制文件中的字符串,因此对 'static 持续时间有效。
其类型是 'static 持续时间借用的字符串切片,&'static str。
字符串切片
字符串切片是 Rust 中最基本的字符串类型,写为 str。它通常以其借用形式出现,可变或共享。共享字符串切片类型是 &str,而可变字符串切片类型是 &mut str。
字符串切片始终是有效的 UTF-8。
Trait
Trait 是用于描述类型必须提供的功能的语言项。它允许类型对其行为做出某些承诺。
泛型函数和泛型结构体可以使用 trait 来约束或限制它们接受的类型。
Turbofish
表达式中带有泛型参数的路径必须在开头的括号前加上 ::。与泛型的尖括号结合,这看起来像一条鱼 ::<>。因此,这种语法在口语中被称为 turbofish 语法。
示例:
#![allow(unused)]
fn main() {
let ok_num = Ok::<_, ()>(5);
let vec = [1, 2, 3].iter().map(|n| n * 2).collect::<Vec<_>>();
}
需要此 :: 前缀来消除逗号分隔列表中多次比较的泛型路径的歧义。有关没有前缀会产生歧义的示例,请参阅 turbofish 的堡垒。
未覆盖类型
不作为另一个类型参数出现的类型。例如,T 是未覆盖的,但 Vec<T> 中的 T 是覆盖的。这仅与类型参数相关。
未定义行为
未指定的编译时或运行时行为。这可能导致但不限于:进程终止或损坏;不正确、错误或意外的计算;或特定于平台的结果。更多信息。
未居住
如果类型没有构造函数,因此永远无法被实例化,则该类型是未居住的。未居住类型是“空的“,因为没有该类型的值。未居住类型的典型示例是永不类型 !,或没有变体的枚举 enum Never { }。与已居住相反。
零大小类型 (ZST)
如果类型的大小为 0,则该类型是零大小的 (ZST)。此类类型最多有一个可能的值。示例包括:
- 单元类型(参见 layout.tuple.unit)。
- 函数项(参见 type.fn-item.intro)。
- 类元组结构体的构造函数(参见 type.fn-item.intro)。
- 类元组枚举变体的构造函数(参见 type.fn-item.intro)。
- 没有字段或所有字段都是零大小的
repr(C)结构体(参见 layout.repr.c.struct.size-field-offset)。 - 没有字段或所有字段都是零大小的
repr(transparent)结构体(参见 layout.repr.transparent.layout-abi)。 - 零大小类型的数组(参见 layout.array)。
- 长度为零的数组(参见 layout.array)。
- 零大小类型的联合体(参见 items.union.common-storage)。
#![allow(unused)]
fn main() {
use core::mem::{size_of, size_of_val};
fn f() {}
struct S(u8);
enum E { V(u8) }
#[repr(C)]
struct C1 {}
#[repr(C)]
struct C2 {
f1: (),
f2: [(); 10],
f3: [u8; 0],
f4: C1,
}
#[repr(transparent)]
struct T1 {}
#[repr(transparent)]
struct T2 {
f1: (),
f2: [(); 10],
f3: [u8; 0],
}
union U {
f1: (),
f2: [(); 10],
f3: [u8; 0],
}
assert_eq!(0, size_of::<()>());
assert_eq!(0, size_of_val(&f));
assert_eq!(0, size_of_val(&S));
assert_eq!(0, size_of_val(&E::V));
assert_eq!(0, size_of::<C1>());
assert_eq!(0, size_of::<C2>());
assert_eq!(0, size_of::<T1>());
assert_eq!(0, size_of::<T2>());
assert_eq!(0, size_of::<[(); 10]>());
assert_eq!(0, size_of::<[u8; 0]>());
assert_eq!(0, size_of::<U>());
}