Rust 新版解读 | 1.89 | TODO
Rust 1.89 官方 release doc: Announcing Rust 1.89.0 | Rust Blog
通过 rustup 安装的同学可以使用以下命令升级到 1.89 版本:
$ rustup update stable
常量泛型的显式推断参数
Rust现在支持在常量泛型参数中使用 _,从上下文推断其值:
#![allow(unused)] fn main() { pub fn all_false<const LEN: usize>() -> [bool; LEN] { [false; _] } }
与类型中使用 _ 的规则类似,在函数签名中不允许将 _ 作为常量泛型参数:
#![allow(unused)] fn main() { // 不允许这样做 pub const fn all_false<const LEN: usize>() -> [bool; _] { [false; LEN] } // 这个也不允许 pub const ALL_FALSE: [bool; _] = all_false::<10>(); }
生命周期语法不匹配的警告
函数签名中的生命周期省略是 Rust 语言的一个便利特性,但也可能成为新手和专家的绊脚石。特别是当类型中隐含生命周期但语法上不明显时:
#![allow(unused)] fn main() { // 返回类型 `std::slice::Iter` 有一个生命周期, // 但是看起来没有任何提示。 // // 生命周期省略推断返回类型的生命周期 // 与 `scores` 相同。 fn items(scores: &[u8]) -> std::slice::Iter<u8> { scores.iter() } }
类似这样的代码现在会默认产生警告:
warning: hiding a lifetime that's elided elsewhere is confusing
--> src/lib.rs:1:18
|
1 | fn items(scores: &[u8]) -> std::slice::Iter<u8> {
| ^^^^^ -------------------- the same lifetime is hidden here
| |
| the lifetime is elided here
|
= help: the same lifetime is referred to in inconsistent ways, making the signature confusing
= note: `#[warn(mismatched_lifetime_syntaxes)]` on by default
help: use `'_` for type paths
|
1 | fn items(scores: &[u8]) -> std::slice::Iter<'_, u8> {
| +++
我们最初在2018年尝试改进这种情况,作为 rust_2018_idioms 警告组的一部分,但关于 elided_lifetimes_in_paths 警告的强烈反馈表明它过于生硬,因为它会警告那些对理解函数无关紧要的生命周期:
#![allow(unused)] fn main() { use std::fmt; struct Greeting; impl fmt::Display for Greeting { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // -----^^^^^^^^^ expected lifetime parameter // 知道`Formatter`有生命周期并不会帮助程序员 "howdy".fmt(f) } } }
我们随后意识到,我们想要消除的混淆发生在以下情况:
- 生命周期省略推断规则将输入生命周期与输出生命周期连接起来
- 语法上不明显存在生命周期
Rust中有两种语法表明生命周期的存在:& 和 ',其中 ' 又分为推断生命周期 '_ 和命名生命周期 'a。当类型使用命名生命周期时,生命周期省略不会为该类型推断生命周期。根据这些标准,我们可以构建三组:
| 明显有生命周期 | 允许生命周期省略推断生命周期 | 示例 |
|---|---|---|
| 否 | 是 | ContainsLifetime |
| 是 | 是 | &T, &'_ T, ContainsLifetime<'_> |
| 是 | 否 | &'a T, ContainsLifetime<'a> |
mismatched_lifetime_syntaxes 警告检查函数的输入和输出是否属于同一组。对于上面的初始示例,&[u8] 属于第二组,而std::slice::Iter<u8> 属于第一组。我们说第一组中的生命周期是隐藏的。
由于输入和输出生命周期属于不同组,警告会提示这个函数,减少对不明显但重要的生命周期的混淆。
mismatched_lifetime_syntaxes 警告取代了 elided_named_lifetimes 警告,后者专门针对命名生命周期做了类似的事情。
未来对 elided_lifetimes_in_paths 警告的工作计划将其拆分为更集中的子警告,并考虑最终警告其中的一部分。
更多 x86 目标特性
target_feature 属性现在支持 x86 上的 sha512、sm3、sm4、kl 和 widekl 目标特性。此外,x86 上也支持许多 avx512 内部函数和目标特性:
#![allow(unused)] fn main() { #[target_feature(enable = "avx512bw")] pub fn cool_simd_code(/* .. */) -> /* ... */ { /* ... */ } }
跨平台文档测试
现在运行 cargo test --doc --target other_target 时会测试文档测试,这可能会导致一些文档测试因失败而被测试出来。
可以通过用 ignore-<target> 注解文档测试来禁用失败的测试(文档):
#![allow(unused)] fn main() { /// ```ignore-x86_64 /// panic!("something") /// ``` pub fn my_function() { } }
extern "C" 函数中的 i128 和 u128
i128 和 u128 不再触发 improper_ctypes_definitions 警告,意味着这些类型可以在 extern "C" 函数中使用而不产生警告。这有一些注意事项:
- 当类型可用时,Rust 类型与 C 中的(无符号)
__int128在 ABI 和布局上是兼容的。 - 在
__int128不可用的平台上,i128和u128不一定与任何 C 类型对齐。 i128不一定与任何平台上的_BitInt(128)兼容,因为_BitInt(128)和__int128可能有不同的 ABI(如在 x86-64 上)。
这是去年布局变更的最后一点后续工作:https://blog.rust-lang.org/2024/03/30/i128-layout-update。
将 x86_64-apple-darwin 降级为 Tier 2 并保留工具链
GitHub 将很快停止为公共仓库提供免费的 macOS x86_64 运行器。苹果也宣布了计划停止支持 x86_64 架构。
根据这些变化,Rust 项目正在将 x86_64-apple-darwin 目标从带工具链的 Tier 1降级为带工具链的 Tier 2。这意味着该目标(包括 rustc 和 cargo 等工具)将保证构建,但不保证通过我们的自动化测试套件。
我们预计在 Rust 1.89 和 1.90 发布之间会接受降级为带工具链的 Tier 2 的 RFC,这意味着 Rust 1.89 将是 x86_64-apple-darwin 作为 Tier 1 目标的最后一个 Rust 版本。
对于用户来说,这一变化不会立即产生影响。只要目标保持在 Tier 2,Rust 项目仍将通过 rustup 或其他安装方法分发标准库和编译器的构建。不过随着时间的推移,测试覆盖率的降低可能会导致问题或兼容性下降。
wasm32-unknown-unknown 目标上的标准兼容C ABI
wasm32-unknown-unknown 目标上的 extern "C" 函数现在具有标准兼容的 ABI。更多信息请参阅这篇博客文章:https://blog.rust-lang.org/2025/04/04/c-abi-changes-for-wasm32-unknown-unknown。
平台支持
x86_64-apple-darwin正在被降级为带工具链的Tier 2- 添加新的Tier-3目标
loongarch32-unknown-none和loongarch32-unknown-none-softfloat
有关 Rust 的分层平台支持的更多信息,请参阅 Rust 的平台支持页面。
Others
其它更新细节,和稳定的 API 列表,参考原Blog