Rust 1.83.0 于 2024 年 11 月 28 日发布,带来了对常量上下文(const contexts)功能的大幅扩展。本文将基于官方博客内容,解析此次更新的核心变化,分析每个更改的原因、优化前后的区别,并通过示例代码帮助读者理解这些改进的实际意义。
一、Rust 1.83.0 版本概览
Rust 1.83.0 的主要亮点是增强了常量上下文的功能,允许在编译期执行更复杂的代码。此外,还稳定了一些新的 API,支持在常量上下文中使用。本次更新包括:
- 新的常量上下文能力 :
- 支持引用静态变量(statics)。
- 支持在常量上下文中使用可变引用和指针。
- 扩展了内部可变性和原始指针的支持。
- 稳定 API:一些函数和 API 现在可以在常量上下文中使用。
- 其他变更:包括 Rust、Cargo 和 Clippy 的改进。
二、核心更改解析
1. 新的常量上下文能力
常量上下文指的是编译期需要评估的所有代码,包括 const
和 static
项的初始值、数组长度、枚举判别值、常量泛型参数,以及在这些上下文中调用的 const fn
函数。Rust 1.83.0 扩展了常量上下文的能力,解锁了更多编译期计算的可能性。
1.1 支持引用静态变量(References to Statics)
更改原因
在 Rust 1.82.0 及之前,static
项(静态变量)无法在常量上下文中引用(除了 static
项自身的初始化表达式外)。这限制了开发者在编译期使用全局静态数据的场景。此次更新移除了这一限制,允许常量上下文引用不可变的 static
项。
优化前后对比
- 优化前 :常量上下文无法引用
static
变量,必须通过其他方式(如硬编码值)绕过限制。 - 优化后 :允许引用不可变的
static
变量,简化了代码。
示例代码
以下是本次更新后合法的引用 static
的例子,改例子之前会报错。
rust
static S: i32 = 25;
const C: &i32 = &S;
fn main() {
println!("{}", *C); // 输出: 25
}
但对于可变或内部可变的 static
变量,仍有一些限制:
rust
static mut S: i32 = 0;
// 错误:常量上下文不能访问可变全局内存
const C1: i32 = unsafe { S }; // 编译错误
// 错误:常量最终值不能包含对可变内存的引用
const C2: &i32 = unsafe { &S }; // 编译错误
然而,允许将指向可变 static
的原始指针作为常量值:
rust
static mut S: i32 = 64;
const C: *mut i32 = &raw mut S;
fn main() {
unsafe {
*C = 128; // 修改 S 的值
println!("{}", S); // 输出: 128
}
}
影响
这一变化允许开发者在编译期更方便地使用全局静态数据,但通过限制可变内存的访问,确保了常量的语义不会因运行时变化而改变。
1.2 支持可变引用和指针(Mutable References and Pointers)
更改原因
在之前的 Rust 版本中,常量上下文中不允许使用可变引用和指针,因为这可能导致常量值的不可预测性。Rust 1.83.0 放宽了这一限制,允许在常量计算过程中使用可变引用和指针,但禁止它们成为常量最终值的一部分。
优化前后对比
- 优化前:常量上下文中不能使用可变引用,必须通过不可变引用或复制值来完成计算。
- 优化后:可以在常量计算中使用可变引用和指针,提升了灵活性。
示例代码
以下是一个在常量上下文中使用可变引用的例子:
rust
const fn inc(x: &mut i32) {
*x += 1;
}
const C: i32 = {
let mut c = 41;
inc(&mut c);
c
};
fn main() {
println!("{}", C); // 输出: 42
}
支持内部可变性和原始指针的例子:
rust
use std::cell::UnsafeCell;
const C: i32 = {
let c = UnsafeCell::new(41);
unsafe { *c.get() += 1 };
c.into_inner()
};
fn main() {
println!("{}", C); // 输出: 42
}
但可变引用不能成为常量最终值:
rust
const C: &mut i32 = &mut 4; // 错误:常量最终值不能包含可变引用
影响
这一变化允许在编译期执行更复杂的计算逻辑,例如修改临时变量,但通过禁止可变引用进入最终值,确保了常量的确定性。
1.3 其他常量上下文能力的扩展
Rust 1.83.0 还稳定了许多可以在常量上下文中使用的函数(详见"Stabilized APIs"部分)。这些新功能解锁了更多编译期计算的可能性,例如在数组长度计算或常量泛型中执行更复杂的逻辑。
2. 稳定 API(Stabilized APIs)
更改原因
Rust 团队不断扩展可以在常量上下文中使用的标准库 API,以支持更广泛的编译期计算场景。Rust 1.83.0 稳定了一些新的 API,具体列表可在官方发布笔记中查看。
优化前后对比
- 优化前:这些 API 只能在 nightly 版本中以不稳定的形式使用。
- 优化后:现在可以在稳定版中使用,降低了开发者的使用成本。
示例代码
由于博客未具体列出所有稳定 API,我们假设一个常见的函数(如 std::mem::size_of
)已稳定为 const fn:
rust
const SIZE: usize = std::mem::size_of::<i32>();
fn main() {
println!("Size of i32: {}", SIZE); // 输出: 4
}
影响
这些稳定的 API 为开发者提供了更多编译期计算工具,特别是在嵌入式系统或性能敏感场景中。
3. 其他变更
Rust 1.83.0 还包括对 Rust 核心语言、Cargo 和 Clippy 的其他改进。详细信息可在官方发布笔记中查看。这些变更通常是小幅优化或错误修复,提升了整体开发体验。from Pomelo_刘金 转载请注明出处,感谢!