返回资讯中心
外部精选
软件工程
#开发者实时流

Rust 1.100.0 发布,never 类型历经十年正式稳定

来源标题:Announcing Rust 1.100.0

Rust 团队发布 1.100.0 版本,never 类型(代码中写作 !)在经历 10 年和 5 次失败的稳定化尝试后终于稳定,同时完成了该项目的既定目标。never 类型表示发散计算,即永不返回值的计算,其后代码不可达。已安装 rustup 的用户可通过 rustup update stable 升级。

Hacker News 最新mbStavola2026/11/12 · 今天16 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

Rust 团队很高兴地宣布 Rust 新版本 1.100.0。Rust 是一门 empowering everyone to build reliable and efficient software 的编程语言。

如果你之前通过 rustup 安装过 Rust,可以用以下命令获取 1.100.0:

$ rustup update stable

如果你还没有安装,可以从我们网站相应页面获取 rustup,并查看 1.100.0 的详细发布说明。

如果你想通过测试未来版本来帮助我们,可以考虑在本地更新到 beta 通道(rustup default beta)或 nightly 通道(rustup default nightly)。请报告你遇到的任何 bug!

历经 10 年和 5 次失败的稳定化尝试,never 类型终于稳定了!这也完成了这项工作对应的项目目标。

never 类型在代码中写作 !,是规范的空类型(uninhabited type)。它表示发散计算(diverging computation)的类型——这类计算永远不会产生任何值——其后的任何代码都不可达。终止控制流的表达式,例如 return、break 和 std::process::exit,其类型也是 !。

由于 never 类型的值不可能存在,Rust 允许 never-to-any 强制转换,即把 ! 转换为任意其他类型(这正是它区别于其他空类型的地方)。例如,可以用它让 match 或 if 的某个分支不返回值:

fn mrrrow(option: Option<u32>) { let value = match option { // x has type u32 Some(x) => x, // return has type !, which is then coerced to u32, // allowing the match to pass type checking. None => return, }; // ...

虽然 never 类型此前已经可以这样使用和观察到,甚至可以在函数返回类型中命名(-> !),但本次发布允许在任何位置命名 never 类型:

fn infallible_unwrap<T>(res: Result<T, !>) -> T { // ^^ writing Result<_, !> was not allowed before let Ok(v) = res; v

此外,本次发布将 Infallible 改为 never 类型的别名。这使得所有使用 Infallible 的旧 API 都能与 ! 兼容。这是自 Infallible 引入以来就有的计划,也是 never 类型稳定化如此困难的原因之一(waffle 曾就此稳定化过程中的一些困难做过演讲)。

遗憾的是,为了允许修改 Infallible,我们不得不引入一个破坏性变更。本次发布将 2024 之前版本(即 2015、2018 和 2021)中的“never 类型回退”(never type fallback)从 () 改为 !,与 2024 edition 中已经完成的改动类似。这在很大程度上不会被察觉,但在极少数情况下可能影响代码(例如忽略一个返回泛型参数的函数的结果时)。注意,这一变更也可能让编译器把更多代码判定为不可达。

我们尽量将这一破坏性变更的影响降到最低:提前提供了未来兼容性警告,并为因此损坏的公开 crate 发布了修复。如果某个依赖因 never 类型相关问题而失败,请考虑更新它,因为可能已经发布了针对它的修复。

本次发布稳定了 allocator_api 的核心部分,使库作者能够定义可与某些标准库类型(目前是 Vec 和 Box)配合使用的自定义分配器。这些功能通过新稳定化的 Allocator trait 启用。

这是 Allocators 1.0 项目目标的基础。还有很多工作要做,包括扩展可与自定义分配器配合使用的 API 面,以及让它们稳定地用于更多集合和指针类型;不过,既然核心 trait 和设计已经就绪,预计很快会有更多内容稳定下来!

Rust 中的 Drop trait 使得在变量离开作用域时运行代码成为可能,无论我们是 return、? 还是 panic。Drop 是类型的一部分,这意味着在 Rust 中你永远不必关闭 socket。

然而,当你只想在函数退出时无条件运行一些代码时,实现 Drop 可能会觉得有些不便。这就是我们引入 core::mem::DropGuard 的原因:一个新的辅助类型,在被 drop 时运行一个闭包。

DropGuard 接受两个参数:一个变量和一个闭包。它实现了 Deref 和 DerefMut,因此你可以照常继续操作该变量。但当它被 drop 时,会运行闭包并消费该变量。

DropGuard 还实现了一个 dismiss 方法,可以从 guard 中取回变量而不运行析构函数。这使得快速实现带回滚的全有或全无事务式 API 成为可能。下面是一个示例,实现一个解析器,使用 guard 在失败时回滚修改:

use std::mem::DropGuard; use std::num::ParseIntError; /// Attempt to parse all strings and push them into nums. /// If parsing any of them fails, nums remains unchanged. fn parse_all(nums: &mut Vec<u32>, strings: &[&str]) -> Result<(), ParseIntError> { let len = nums.len(); let mut nums = DropGuard::new(nums, move |nums| { nums.truncate(len); // ← 1. Reset the vec on failure }); for s in strings { nums.push(s.parse()?); // ← 2. If ? returns an error, roll back DropGuard::dismiss(nums); // ← 3. Parsing successful, dismiss the guard Ok(())

召唤零大小类型

由于 Rust 的不安全代码指南仍在制定中,有一点变得很清楚:明确以不安全方式创建零大小类型(zero-sized type)究竟意味着什么,以及我们应该推荐人们如何去做,会非常有用。

这个问题在 Rust 1.100 中由一个函数回答:std::mem::conjure_zst。

不必再使用 transmute ()、MaybeUninit::uninit().assume_init() 或各种其他咒语,这是当你确知这样做安全时,创建零大小类型值的专用方式。如果一个有值类型(inhabited type)没有大小,我们确切知道它必须是哪个值:什么都没有。

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →