Rust 1.95 稳定版解读与生态新动向

Rust 1.95 稳定版解读与生态新动向

一、Rust 1.95.0:三个值得关注的新特性

Rust 1.95.0 已于 2026 年 4 月 16 日正式发布。这个版本带来了几项对日常编码体验影响较大的改进。

1. cfg_select! ------ 编译时条件选择的官方方案

过去,如果你想在编译时根据不同的目标平台(如 unixwindows32 位64 位)执行不同的代码分支,最常用的方式是引入第三方 crate cfg-if。写法大概是这样的:

rust 复制代码
cfg_if::cfg_if! {
    if #[cfg(unix)] {
        fn foo() { /* unix 特定实现 */ }
    } else if #[cfg(target_pointer_width = "32")] {
        fn foo() { /* 32 位实现 */ }
    } else {
        fn foo() { /* 兜底实现 */ }
    }
}

Rust 1.95 把它变成了语言内置特性,不需要再引入任何依赖:

rust 复制代码
cfg_select! {
    unix => {
        fn foo() { /* unix 特定实现 */ }
    }
    target_pointer_width = "32" => {
        fn foo() { /* 32 位实现 */ }
    }
    _ => {
        fn foo() { /* 兜底实现 */ }
    }
}

为什么这很重要?

  • 减少了一个几乎每个跨平台项目都会引入的依赖
  • 编译器对内置宏的理解更充分,IDE 支持和错误提示更好
  • 语法更简洁:条件 => { 代码块 },一目了然

你甚至可以直接用它在表达式中做选择:

rust 复制代码
let platform = cfg_select! {
    windows => "windows",
    target_os = "macos" => "macos",
    _ => "unix-like",
};

2. if-let 守卫进入 match 表达式

Rust 1.88 引入了 let chainsif let 链式条件),现在这种能力扩展到了 match 表达式中。

看一个实际场景 :假设你有一个 Option<i32> 类型的值,需要先解包,再对一个可能失败的操作做判断:

rust 复制代码
// Rust 1.95 之前:需要嵌套 if let
match value {
    Some(x) => {
        if let Ok(y) = compute(x) {
            println!("{}, {}", x, y);
        }
    }
    None => {}
}

// Rust 1.95:直接在 match arm 上加 if-let 守卫
match value {
    Some(x) if let Ok(y) = compute(x) => {
        // x 和 y 在这里都可用
        println!("{}, {}", x, y);
    }
    _ => {}
}

实际意义 :这让你在 match 中可以同时做模式匹配和条件判断,减少嵌套层级,代码更加扁平。这在处理嵌套 Result<Option<T>> 等复杂类型时尤其有用。

注意if-let 守卫中的模式不会 参与 match 的穷尽性检查,这一点和普通 if 守卫一致。也就是说,编译器不会因为它而认为你覆盖了更多情况。

3. 一批标准库 API 稳定化

这个版本稳定了大量实用 API,挑几个值得关注的:

MaybeUninitCell 的数组转换

rust 复制代码
// 现在可以直接在 [MaybeUninit<T>; N] 和 MaybeUninit<[T; N]> 之间转换
let arr: [MaybeUninit<u8>; 4] = /* ... */;
let unified: MaybeUninit<[u8; 4]> = arr.into();

这在做底层系统编程、FFI 交互时非常常见,以前需要 unsafe 手写转换,现在安全地完成。

集合类型的 _mut 方法

VecVecDequeLinkedList 都新增了 push_mutinsert_mut 等方法。这些方法返回可变引用而非 Copy 值,适用于元素类型不实现 Copy 的场景:

rust 复制代码
let mut v = vec![String::from("hello")];
let s: &mut String = v.push_mut(String::from("world"));
// 拿到刚插入元素的 &mut 引用,而不是一个被 Move 出去的值

Atomic*::updatetry_update

所有原子类型新增了基于闭包的原子更新方法:

rust 复制代码
use std::sync::atomic::AtomicI32;

let counter = AtomicI32::new(0);
// 原子地执行:读取 -> 修改 -> CAS 重试
counter.update(|old| old + 1);

这替代了手写 compare_exchange 循环的样板代码,简洁且不易出错。


二、docs.rs 构建策略变化:从 5 个目标减少到 1 个

变化时间:2026 年 5 月 1 日生效

docs.rs 是 Rust 生态的在线文档服务,几乎所有 crate 的文档都托管在上面。目前的行为是:如果一个 crate 没有显式声明构建目标,docs.rs 会为默认 5 个目标平台各构建一份文档。

从 5 月 1 日起 ,默认行为将改为只构建一个目标 (通常是 x86_64-unknown-linux-gnu)。

对你的影响

你的情况 是否受影响
纯 Rust 代码,不区分平台 不受影响
crate 使用了 #[cfg(target_os = "...")] 等平台特定代码 需要在 Cargo.toml 中声明目标
FFI crate,绑定多个平台 必须声明

如何适配 :在 Cargo.toml 中显式声明:

toml 复制代码
[package.metadata.docs.rs]
targets = [
    "x86_64-unknown-linux-gnu",
    "x86_64-apple-darwin",
    "x86_64-pc-windows-msvc",
]

为什么这么做? 大多数 crate 在不同平台上的代码完全一样,多构建几份文档浪费的是 docs.rs 的服务器资源和你的构建时间。这个改变从 2020 年开始酝酿,如今终于落地。


三、WebAssembly 工具链:移除 --allow-undefined 历史遗留

这个变化对 Rust + WebAssembly 开发者来说是一个潜在破坏性更新

背景

从 Rust 最早支持 WebAssembly 开始,链接器 wasm-ld 就一直带着 --allow-undefined 标志。这个标志的含义是:允许链接后的二进制中存在未定义的符号

问题

这意味着如果你写错了函数名、忘了链接外部 C 库,编译器不会报错 ,而是默默把那个符号标记为从 "env" 导入。直到运行时你才会发现------而且错误信息很难追溯到源码。

举个例子:

rust 复制代码
unsafe extern "C" {
    fn mylibrary_init();  // 正确
}

// 如果你拼写错误:
unsafe extern "C" {
    fn mylibraryinit();   // 编译不报错!运行时才崩
}

变化

Rust 正在移除这个标志,让 WebAssembly 目标和其他原生平台行为一致:未定义符号 = 编译错误

你需要做什么

  • 如果你的 WebAssembly 项目正确声明并链接了所有外部符号 → 不受影响
  • 如果你依赖了 "env" 隐式导入 → 需要修复代码,显式声明符号来源
  • 如果你用了 wasm-bindgen 等工具 → 一般不受影响,它们处理的是正确的符号导入

四、生态观察

结合 4 月的这些更新,我们可以看到 Rust 发展的几个趋势:

1. 语言本身在"补全"而非"颠覆"

cfg_select!if-let 守卫都不是全新概念,而是把社区已经验证过好用、但需要第三方库或 workaround 的能力收归标准库。这说明 Rust 的演进策略越来越成熟------先让生态试水,再纳入语言。

2. 工具链在减少历史包袱

移除 WebAssembly 的 --allow-undefineddocs.rs 减少默认构建目标,都是在清理早期为了"能用就行"而留下的技术债。这些变化虽然可能短期带来适配成本,但长期来看让工具链行为更一致、更可预测。

3. 标准库持续"填坑"

Atomic*::updateMaybeUninit 数组转换这些 API 的稳定化,针对的都是实际开发中频繁出现的场景。Rust 团队明显在系统性地减少那些"明明很常用,却还要自己写 unsafe"的痛点。


五、升级建议

bash 复制代码
# 升级到 1.95.0
rustup update stable

# 验证版本
rustc --version  # 应显示 1.95.0

如果你维护 WebAssembly 项目,建议在升级后做一次完整的 cargo build --target wasm32-unknown-unknown 测试,确认没有未定义符号被静默放过。

相关推荐
为何创造硅基生物13 小时前
C语言 结构体内存对齐规则(通俗易懂版)
c语言·开发语言
吃好睡好便好13 小时前
在Matlab中绘制横直方图
开发语言·学习·算法·matlab
星寂樱易李13 小时前
iperf3 + Python-- 网络带宽、网速、网络稳定性
开发语言·网络·python
仰泳之鹅14 小时前
【C语言】自定义数据类型2——联合体与枚举
c语言·开发语言·算法
之歆14 小时前
DAY_12JavaScript DOM 完全指南(二):实战与性能篇
开发语言·前端·javascript·ecmascript
candyTong15 小时前
Claude Code 的 Edit 工具是怎么工作的
javascript·后端·架构
cen__y15 小时前
Linux12(Git01)
linux·运维·服务器·c语言·开发语言·git
AI人工智能+电脑小能手15 小时前
【大白话说Java面试题 第65题】【JVM篇】第25题:谈谈对 OOM 的认识
java·开发语言·jvm
GetcharZp16 小时前
GitHub 2.4 万 Star!D2 正在重新定义程序员画图方式
后端
社交怪人16 小时前
【算平均分】信息学奥赛一本通C语言解法(题号2071)
c语言·开发语言