老铁们,Rust 又更新了

2025年12月11日,Rust 官方正式发布了 1.92.0 版本

你可能会问:“又更新了?上个月不是刚更新过吗?”

没错,Rust 每六周发一个新版本,比你交房租还准时。这次 1.92 带来了几个挺有意思的改动,尤其是关于 never 类型的那些事儿,咱们今天来唠唠。

先说怎么升级,老规矩:

rustup update stable

一行命令搞定,比点外卖还简单。

Rust 1.92 重点:never 类型的 lint 要"翻脸"了

这次最重要的变化,就是两个关于 never 类型的 lint 从"警告"升级成了"默认拒绝"。

什么意思呢?打个比方。以前编译器看到你写的可疑代码,就像你妈看到你屋里乱七八糟,会唠叨两句:“儿子,这样不太好啊。“但你可以假装没听见,代码照样能编译通过。

现在不一样了。编译器直接变成你丈母娘:“不行,这样不能过门!“代码编译不过去了。

具体是这两个 lint:

  • never_type_fallback_flowing_into_unsafe
  • dependency_on_unit_never_type_fallback

别被这俩名字吓到,说人话就是:Rust 团队在为 never 类型正式稳定做准备,这些 lint 是用来检测那些可能会被未来改动影响的代码。

什么是 never 类型?

never 类型概念图 - 永远不会返回的函数类型

如果你还不知道 never 类型是啥,我来解释一下。

在 Rust 里,! 表示"这个函数永远不会正常返回”。什么情况会用到?比如:

  • panic!() —— 程序直接炸了,还返回个屁
  • loop {} —— 死循环,永远出不来
  • std::process::exit() —— 程序退出了

就像你问一个杠精"你什么时候能认错”,答案就是 never,永远不可能。

影响大吗?

Lint 升级对比:从 warn 到 deny-by-default

Rust 团队估算,大概有 500 个 crate 会受到影响。听起来不少,但相对于整个生态来说其实还好。

而且,这毕竟是 lint,不是硬性的破坏性改动。如果你实在改不了代码,可以用 #[allow] 暂时压下去:

#[allow(never_type_fallback_flowing_into_unsafe)]
fn my_questionable_function() {
    // 你那些可疑的代码
}

但是,强烈建议还是修一下。就像体检报告说你某个指标偏高,虽然现在没事,但不管它迟早要出问题。

unused_must_use 优化:Result 变聪明了,不再瞎报警

这个改动我个人觉得特别贴心。

以前 unused_must_use 这个 lint 有点"一刀切”。只要你忽略了一个 Result 的返回值,它就会警告你:“喂,你这个 Result 没处理!”

但问题是,有些 Result 根本不可能出错。

比如你写了个函数返回 Result<(), Infallible>Infallible 这个类型的意思是"不可能的事”,就像你问"太阳从西边出来怎么办"一样,压根不需要考虑。

以前编译器不管这些,照样警告你。就像你妈非要你带伞,但外面是大晴天而且你就下楼倒个垃圾。

现在编译器懂事了:

use core::convert::Infallible;

fn can_never_fail() -> Result<(), Infallible> {
    // 这个函数绝对不会失败
    Ok(())
}

fn main() {
    can_never_fail();  // 现在不会警告了
}

这在实际开发中特别有用。比如你定义了一个 trait,里面有个关联类型 Error

trait UsesAssocErrorType {
    type Error;
    fn method(&self) -> Result<(), Self::Error>;
}

// 这个实现不可能失败
struct CannotFail;
impl UsesAssocErrorType for CannotFail {
    type Error = Infallible;  // 错误类型是"不可能"
    fn method(&self) -> Result<(), Self::Error> {
        Ok(())
    }
}

// 这个实现可能失败
struct CanFail;
impl UsesAssocErrorType for CanFail {
    type Error = std::io::Error;
    fn method(&self) -> Result<(), Self::Error> {
        Err(std::io::Error::other("出事了"))
    }
}

fn main() {
    CannotFail.method();  // 不警告,因为错误不可能发生
    CanFail.method();     // 警告!你应该处理这个错误
}

这就像快递小哥学会了看收件地址。以前是"有快递就喊你下来",现在知道"这个是你主动上门取的,不用通知了"。

Linux 栈回溯修复:-Cpanic=abort 也能看 backtrace 了

这个改动说起来有点历史渊源。

在 Rust 1.22 的时候,即使你用了 -Cpanic=abort(让程序 panic 时直接退出而不是展开栈),栈回溯(backtrace)还是能正常工作的。

然后 Rust 1.23 把这功能给整没了。原因是为了性能优化,不再生成 unwind tables(展开表)。

从那以后,如果你想要栈回溯,得自己加个编译选项:-Cforce-unwind-tables=yes

现在 1.92 版本默认就会生成这些表了。你的程序崩了,能看到完整的调用栈,方便定位问题。

如果你真的不想要这些表(比如嵌入式场景,要极致压缩体积),可以显式关掉:

rustc -Cforce-unwind-tables=no your_code.rs

这就像手机的定位功能,以前关了就完全没了,现在默认开着但你可以手动关。

macro_export 更严格了

#[macro_export] 这个属性现在会更严格地检查你传给它的参数。

以前你可能传了些乱七八糟的东西进去,编译器睁一只眼闭一只眼。现在它会直接报错。

这是 Rust 团队在逐步统一所有内置属性的错误处理方式。以后你会发现,各种属性的错误提示会越来越一致,越来越友好。

Rust 1.92 新稳定 API 一览

Rust 1.92 新稳定 API 概览

这次稳定了一批实用的 API,挑几个有意思的说说:

Box/Rc/Arc 的 new_zeroed 系列

let boxed: Box<[u8; 1024]> = Box::new_zeroed();

这个 API 让你可以分配一块全是零的内存。在需要大量初始化为零的场景下,比手动 Box::new([0u8; 1024]) 更高效。

就像买新房,以前得自己一个房间一个房间打扫,现在开发商直接给你弄得干干净净交付。

RwLockWriteGuard::downgrade

let lock = RwLock::new(5);
let write_guard = lock.write().unwrap();
let read_guard = write_guard.downgrade();  // 写锁降级为读锁

这个功能等了好久了。以前你想从写锁切换到读锁,得先释放写锁,再获取读锁,中间可能有其他线程插队。现在可以直接降级,原子操作,不给别人插队的机会。

就像你在银行办业务,以前想从柜台换到自助机,得先取号重新排队。现在可以直接转过去。

btree_map::Entry::insert_entry

use std::collections::BTreeMap;

let mut map = BTreeMap::new();
let entry = map.entry("key").insert_entry("value");
// entry 现在是 OccupiedEntry,可以继续操作

Entry API 又多了个实用方法。

slice 的 rotate_left/right 现在是 const 了

const ROTATED: [i32; 5] = {
    let mut arr = [1, 2, 3, 4, 5];
    arr.rotate_left(2);
    arr
};
// ROTATED = [3, 4, 5, 1, 2]

编译期就能旋转数组了,又省了一点运行时开销。

Rust 1.92 升级指南

这个版本没有什么破坏性改动,可以放心升级。

唯一需要注意的就是那两个 never 类型的 lint。如果你的代码或者依赖里有相关警告,建议趁早修。Rust 团队在为 never 类型的最终稳定做铺垫,迟早要面对的事情,不如现在就解决。

运行这个命令看看你的项目有没有问题:

cargo clippy --all-features 2>&1 | grep -E "never_type|dependency_on_unit"

如果啥都没输出,恭喜你,安全过关。

写在最后

Rust 1.92 是个"稳扎稳打"的版本,没有特别惊艳的大功能,但每个改动都很实在。

never 类型的推进让人看到了 Rust 语言设计的长远规划。一个类型从提出到稳定,可能要经过好几年的讨论、实验、调整。这种谨慎的态度,是 Rust 能够保持向后兼容性的重要原因。

好了,今天就聊到这。升级完记得跑一遍测试,有问题评论区见。

相关阅读

如果你对 Rust 感兴趣,这几篇文章你可能也会喜欢:


觉得这篇文章有用? 点个赞让更多人看到,收藏起来下次升级的时候翻出来看看。如果你身边也有写 Rust 的朋友,转发给他们,说不定能帮他们避开几个坑。有什么问题或者想聊的,评论区等你。