返回资讯中心
外部精选
软件工程
#社区热议

Rust 1.100 发布,never 类型历经十年终于稳定

来源标题:Rust 1.100

Rust 团队发布 Rust 1.100.0,never 类型(写作 !)在历经 10 年和 5 次失败的稳定化尝试后正式稳定,并完成了该工作的项目目标。never 类型表示发散计算的类型,即永远不会返回值的计算,其后的代码不可达。return、break 和 std::process::exit 等终止控制流的表达式也具有该类型。

Hacker NewsmbStavola2026/11/12 · 今天16 分钟阅读

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

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!

历经 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 的类型是 u32 Some(x) => x, // return 的类型是 !,随后被强制转换为 u32, // 使得 match 能通过类型检查。 None => return, }; // ... 尽管 never 类型此前已经可以这样使用和观察,甚至可以在函数返回类型中命名(-> !),但这个版本允许在任何地方命名 never 类型: fn infallible_unwrap<T>(res: Result<T, !>) -> T { // ^^ 以前不允许写 Result<_, !> let Ok(v) = res; v 此外,这个版本把 Infallible 改为 never 类型的别名。这使得所有使用 Infallible 的旧 API 都能与 ! 兼容。这是自 Infallible 引入以来就有的计划,也是 never 类型稳定化如此困难的原因之一(waffle 曾做过一次演讲,谈及稳定化过程中的一些困难)。 遗憾的是,为了能够修改 Infallible,我们不得不引入一项破坏性变更。这个版本把 2024 之前各版本(即 2015、2018 和 2021)的“never 类型回退”(never type fallback)从 () 改为 !,与 edition 2024 中已经完成的改动类似。这在很大程度上应该不会被察觉,但在某些罕见情况下可能影响代码(例如忽略一个返回泛型参数的函数的结果时)。请注意,这一变更也可能让编译器把更多代码判定为不可达。 我们尽可能减小了这项破坏性变更的影响:提前提供了 future compatibility 警告,并为因此受损的公开 crate 发布了修复。如果某个依赖因 never 类型的问题而失败,请考虑更新它,因为可能已经为它发布了修复。

这个版本稳定了 allocator_api 的核心部分,使库作者能够定义可与某些标准库类型一起使用的自定义分配器——目前是 Vec 和 Box。它们通过新稳定化的 Allocator trait 启用。 这是 Allocators 1.0 项目目标的基础。仍有很多工作要做,包括扩展可与自定义分配器配合使用的 API 范围,以及在更多集合和指针类型上稳定使用它们;不过核心 trait 和设计已经就位,预计很快会有更多内容稳定下来!

Rust 中的 Drop trait 使得在变量离开作用域时运行代码成为可能,无论我们是返回、使用 ? 还是 panic。Drop 成为类型的一部分,意味着在 Rust 中你永远不必手动关闭 socket。 然而,当你只是想在函数退出时无条件运行一些代码时,实现 Drop 可能会让人觉得有点不方便。这就是我们引入 core::mem::DropGuard 的原因:这是一个新的辅助类型,在 drop 时运行一个闭包。 DropGuard 接受两个参数:一个变量和一个闭包。它实现了 Deref 和 DerefMut,因此你可以照常继续使用该变量。但当它被 drop 时,它会运行闭包并消费该变量。 DropGuard 还实现了 dismiss 方法,可以在不运行析构函数的情况下从 guard 中返回变量。这使得快速实现带回滚的全有或全无的事务式 API 成为可能。下面是一个示例,实现了一个 parser,使用 guard 在失败时回滚修改: use std::mem::DropGuard; use std::num::ParseIntError; /// 尝试解析所有 strings 并将它们推入 nums。 /// 如果其中任何一个解析失败,nums 保持不变。 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. 失败时重置 vec }); for s in strings { nums.push(s.parse()?); // ← 2. 如果 ? 返回错误,则回滚 DropGuard::dismiss(nums); // ← 3. 解析成功,解除 guard Ok(())

召唤零大小类型 由于 Rust 的 unsafe 代码指南仍在确定中,人们清楚地意识到,明确以 unsafe 方式创建零大小类型的确切含义,以及我们应该推荐人们如何做这件事,将非常有用。 这个问题在 Rust 1.100 中由一个函数回答:std::mem::conjure_zst。 与其对 () 做 transmute、使用 MaybeUninit::uninit().assume_init(),或各种其他咒语,这是在你知道这样做是安全的情况下创建零大小类型值的专用方式。如果一个可居住类型没有大小,我们就确切知道它必须是哪个值:什么都没有。

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

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

打开原文
去社区讨论 →