
Rust 1.100.0 正式发布,never type 终于稳定
来源标题:Announcing Rust 1.100.0
Rust 团队发布 Rust 1.100.0,其中 never type(代码中写作 !)在历经 10 年、5 次失败后终于稳定。该版本还稳定了 Allocator API、DropGuard API,并在 Cargo 中加入未使用依赖报告、减少缓存冲突和 min-publish-age 等改进。用户可通过 rustup update stable 升级。
以下正文由 AI 翻译自 Rust Blog(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
Rust 团队很高兴地宣布 Rust 的新版本 1.100.0。Rust 是一门让每个人都能构建可靠且高效软件的编程语言。 如果你之前通过 rustup 安装过 Rust,可以用以下命令获取 1.100.0:
$ rustup update stable
如果你还没有安装,可以从我们网站上的相应页面获取 rustup,并查看 1.100.0 的详细发布说明。 如果你想通过测试未来版本来帮助我们,可以考虑在本地更新到 beta 通道(rustup default beta)或 nightly 通道(rustup default nightly)。请报告你遇到的任何 bug!
1.100.0 稳定版包含哪些内容
- never 类型
- Allocator API
- DropGuard API
- 召唤零大小类型
- 在 Cargo 中报告未使用的依赖
- 减少 Cargo 缓存冲突
- Cargo 最小发布时间
- 稳定的 API
never 类型 历经 10 年和 5 次失败的稳定化尝试,never 类型终于稳定了!这也完成了这项工作对应的项目目标。 never 类型,在代码中写作 !,是规范的空类型(uninhabited type)。它表示发散计算(divering computation)的类型——这类计算永远不会得到任何值——其后的任何代码都不可达。终止控制流的表达式,如 return、break 和 std::process::exit,其类型也是 !。 由于不可能拥有 never 类型的值,Rust 允许 never-to-any 强制转换,即可以把 ! 转换成任何其他类型(这正是它与其他空类型的区别)。例如,可以用它来在 match 或 if 的某个分支中不返回值:
fn mrrrow(option: Optionu32>) {
let value = match option {
// `x` 的类型是 `u32`
Some(x) => x,
// `return` 的类型是 `!`,随后被强制转换为 `u32`,
// 使 `match` 通过类型检查。
None => return,
};
// ...
虽然此前已经可以这样使用和观察 never 类型,甚至可以在函数返回类型中命名它(-> !),但本次发布允许在任何地方命名 never 类型:
fn infallible_unwrapT>(res: ResultT, !>) -> T {
// ^^ 以前不允许在这里写 `Result`
let Ok(v) = res;
v
此外,本次发布将 Infallible 改为 never 类型的别名。这使得所有使用 Infallible 的旧 API 都与使用 ! 兼容。这是自 Infallible 引入以来就有的计划,也是 never 类型稳定化如此困难的原因之一(waffle 曾做过一个演讲,谈到稳定化过程中的一些麻烦)。 遗憾的是,为了允许修改 Infallible,我们不得不引入一个破坏性变更。本次发布将 2024 之前的版本(即 2015、2018 和 2021)中的「never 类型回退」从 () 改为 !,与 edition 2024 中已经完成的做法类似。这在很大程度上应该不会被注意到,但在极少数情况下可能影响代码(例如忽略一个返回泛型参数的函数的结果时)。请注意,这一变更也可能使编译器将更多代码检测为不可达。 我们尽可能减少了这一破坏性变更的影响,提前提供了未来兼容性警告,并为因此被破坏的公开 crate 发布了修复。如果某个依赖因 never 类型的问题而失败,请考虑更新它,因为可能已经为其发布了修复。
Allocator API 本次发布稳定了 allocator_api 的核心部分,使库作者能够定义自定义分配器,并与某些标准库类型一起使用——目前是 Vec 和 Box。这些通过新稳定的 Allocator trait 启用。 这是 Allocators 1.0 项目目标的基础。还有很多工作要做,包括扩展可与自定义分配器一起使用的 API 范围,以及在更多集合和指针类型上稳定其使用;不过核心 trait 和设计已经就位,预计很快会有更多内容稳定下来!
DropGuard:在每条退出路径上运行闭包 Rust 中的 Drop trait 使得在变量离开作用域时运行代码成为可能,无论我们是 return、? 还是 panic。Drop 是类型的一部分,这意味着在 Rust 中你永远不必手动关闭 socket。 然而,当你只想在函数退出时无条件运行一些代码时,实现 Drop 可能会觉得有点不方便。这就是我们引入 core::mem::DropGuard 的原因:一个新的辅助类型,在被 drop 时运行一个闭包。 DropGuard 接受两个参数:一个变量和一个闭包。它实现了 Deref 和 DerefMut,因此你可以像平常一样继续使用该变量。但当它被 drop 时,会运行闭包并消耗该变量。 DropGuard 还实现了 dismiss 方法,它从守卫中返回变量而不运行析构函数。这使得快速实现带回滚的全有或全无事务式 API 成为可能。下面是一个实现解析器的例子,它使用守卫在失败时回滚修改:
use std::mem::DropGuard;
use std::num::ParseIntError;
/// 尝试解析所有 `strings` 并将它们推入 `nums`。
/// 如果任何一个解析失败,`nums` 保持不变。
fn parse_all(nums: &mut Vecu32>, strings: &[&str]) -> Result(), ParseIntError> {
let len = nums.len();
let mut nums = DropGuard::new(nums, move |nums| {
nums.truncate(len); // ← 1. 失败时重置 vec
});
for s in strings {
nums.push(s.parse()?); // ← 2. 如果 `?` 返回错误,则回滚
DropGuard::dismiss(nums); // ← 3. 解析成功,解除守卫
Ok(())
召唤零大小类型 由于 Rust 的 unsafe 代码指南仍在确定中,很明显,明确以 unsafe 方式创建零大小类型到底意味着什么,以及我们应该推荐人们怎么做,将非常有用。
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。