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 测试,确认没有未定义符号被静默放过。

相关推荐
asdzx671 小时前
告别手动校对:使用 Python 对比两个 PDF 文档的差异
开发语言·python·pdf
Rust研习社1 小时前
Rust 操作 Redis 从入门到生产级应用
开发语言·redis·后端·rust
deviant-ART1 小时前
HttpServletResponse 中 Header 与 OutputStream 的正确使用顺序(避坑指南)
java·后端·servlet
编码者卢布1 小时前
【App Service】查看Application Insights自身SDK日志的方法示例
后端·python·flask
xyq20241 小时前
Memcached stats items 命令详解
开发语言
Evand J1 小时前
【MATLAB例程】多传感器协同DOA目标跟踪与EKF滤波,输出动态目标轨迹、轨迹误差对比分析
开发语言·matlab·目标跟踪·滤波·定位·导航
csbysj20201 小时前
《jEasyUI 自定义分页》
开发语言
初心未改HD1 小时前
Go语言Context深度解析与工程实践
开发语言·golang
土豆12501 小时前
Rust 生命周期开发实战:从"编译不过"到"一次过编"的实用指南
前端·rust