常量求值
常量求值是在编译期间计算 表达式 结果的过程。 其条件是所有表达式的子集能够在编译时进行求值。
常量表达式
常量表达式可以在编译时求值。在 常量上下文 中,唯一允许的表达式,并且始终在编译时求值。 在其他位置,如 let 语句 中,常量表达式可能会被求值,但不能保证在编译时求值。 如果必须在编译时求值 (即在常量上下文中) ,则越界的 数组索引 或 溢出 等行为会导致编译器错误。 否则,这些行为会导致警告,但可能会在运行时崩溃。
以下表达式是常量表达式,只要任何操作数也是常量表达式。并且不会导致 Drop::drop
调用。
- 字面值。
- 常量参数。
- 函数 和 常量 的 路径 。不允许递归定义常量。
- 静态变量 的路径。这些只允许在静态变量的初始化器中使用。
- 元组表达式 。
- 数组表达式 。
- 结构体 表达式。
- 块表达式 ,包括
unsafe
块。 - 字段 表达式。
- 索引表达式,使用
usize
的 数组索引 或 切片 。 - 区间表达式 。
- 不捕获环境变量的 闭包表达式 。
- 在整数和浮点数类型、
bool
和char
上使用的内置 否定 、 算术 、 逻辑 、 比较 或 惰性布尔 运算符。 - 共享 借用 ,除非应用于具有 内部可变性 的类型。
- 解引用运算符 ,除了原始指针。
- 分组 表达式。
- 转换 表达式,除了
- 指针到地址转换和
- 函数指针到地址转换。
- const函数 和 const 方法的调用。
- loop 、 while 和
while let
表达式。 - if 、
if let
和 match 表达式。
常量上下文
常量上下文 是以下情况之一:
常量函数
常量函数是指允许在常量上下文中调用的函数。
将函数声明为 const
不会影响函数现有的用途,只限制了参数和返回类型可以使用的类型和表达式。
可以像普通函数一样自由地使用常量函数进行相同的操作。
在常量上下文中调用函数时,编译器会在编译时解释该函数。解释环境为编译目标,而不是主机环境。
因此,如果你正在针对 32 位系统进行编译,则无论是在 64 位系统还是 32 位系统上构建, usize
都是 32 位。
常量函数有一些限制,以确保可以在编译时求值。例如,不可能将随机数生成器编写为常量函数。 在编译时调用常量函数将始终产生与在运行时调用它相同的结果,即使调用多次也是如此。 有一个例外:如果在极端情况下进行复杂的浮点数运算,则可能会得到(极微小的)不同结果。 建议不要使数组长度和枚举判别值依赖于浮点数计算。
允许在常量上下文中使用但不允许在常量函数中使用的显著特性包括:
- 浮点运算
- 浮点值与除了
Copy
之外的 trait 约束的泛型参数一样处理。因此,你无法对它们进行任何操作,只能复制/移动它们。
- 浮点值与除了
在常量函数中可以使用以下内容,但在常量上下文中不行:
- 使用泛型类型和生命周期参数。
- 常量上下文允许有所限制的使用 常量泛型参数 。