2026 年 11 月 12 日,Rust 1.100.0 稳定版正式发布。从 2015 年 1.0 算起,这门系统级语言按每六周一版的节奏走完第 100 个次要版本,一次性端出了拖延 10 年、历经 5 次稳定化失败的 Never 类型(!),以及 std::alloc::Allocator 自定义内存分配器、core::mem::DropGuard 和 Cargo 依赖冷却机制(min-publish-age)。
比起三位数版本号的纪念意义,这版更新最反常的地方在于妥协与铁腕并存。官方把自定义分配器劈成两半,只放行 Box 和 Vec;为了焊死 ! 类型,向来死守兼容性的编译器团队罕见打破旧版次承诺,强推破坏性回退规则;而备受期待的 Cargo 防供应链投毒冷却期,虽然通过了微虚拟机 Firecracker 等 16 个场景实测,却比前端生态的 pnpm 留出了更多豁免后门。
- 语言与标准库落地.稳定
!类型并将Infallible降级为类型别名;稳定Allocator核心子集(限Box/Vec);新增core::mem::DropGuard状态回滚守卫与std::mem::conjure_zst零大小类型构造函数;wasm32-wasip3晋升至 Tier 2 支持,WASI SDK 升至 34,标准库更新至 Unicode 18.0.0。 - Cargo 工具链更新.上线
global-min-publish-age依赖冷却期;上线自有 lint 系统[lints.cargo]及unused_dependencies僵尸依赖检查;cargo install默认读取内置Cargo.lock;重构build-dir中间产物哈希目录布局。 - 直接受影响团队.Linux 内核(Rust for Linux)、嵌入式与数据库研发可脱离 Nightly 工具链编写自定义内存池;企业 DevSecOps 与 CI 基建团队面临旧代码类型推导中断、
target/硬编码路径失效及二进制安装防线漏网三项改造压力。
十年五败一朝破局,拆包上市的底层控制权
在代码里写作 ! 的 Never 类型,代表 return、break 或 std::process::exit 这类永不返回正常值的计算。过去开发者能写 -> !,却无法在泛型参数里直接写出 Result<T, !>,只能拿标准库枚举 std::convert::Infallible 当替身。
把 Infallible 改成 type Infallible = !,在 GitHub 追踪议题 #35121(对应 RFC 1216)里卡了整整十年。期间五次冲击稳定版全部回滚,死结集中在议题 #161925 梳理的四大兼容性雷区,包括 never 强制转换后的方法查找歧义、! 与 Infallible 的冲突 trait 实现、保留的 From<!> 实现,以及复杂的子类型推导。
最要命的雷区是类型推导回退机制(fallback)。当编译器无法推导发散代码的具体类型时,Rust 2024 版次已默认回退为 !,但 2015、2018 和 2021 三个旧版次仍默认回退为单元类型 ()。议题 #155924 与 #148922 的测试表明,只要不统一回退规则,把 Infallible 变成 ! 的别名就会直接导致大批存量代码推导中断。
官方这次没有再等。编译器团队直接在 2015、2018 和 2021 旧版次中引入破坏性变更,把全 Edition 的回退规则统一强推为 !,提前数个版本上线警告并主动给受影响的公共 crate 提补丁。
同样的切香肠思路也用在了自定义内存分配器(追踪议题 #32838)上。1.100.0 稳定了 std::alloc::Allocator trait 以及 Global、System 分配器,开放了 Box::new_in、Vec::new_in 和 Vec::with_capacity_in。但核对 PR #156882 就会发现,尽管发布列表中出现了 Rc<T, A> 和 Arc<T, A> 的部分委托签名,真正落地的只有原 allocator_api 的核心子集,其余复杂容器接口被剥离并改名为 allocator_ext 留待日后演进。
即便只迈出这半步,PR #161946 已经暴露出代价。为 Box 泛化任意分配器支持后,部分既有代码会直接触发新的类型推导错误。
顺带补齐底层控制短板的还有两项实用 API。core::mem::DropGuard 接收一个变量和闭包,通过 Deref 与 DerefMut 保持正常读写,异常退出作用域时自动消费变量并执行回滚闭包,正常走完流程则调 DropGuard::dismiss(guard) 取出原值,省去了手写结构体实现 Drop 的繁琐。std::mem::conjure_zst 则取代了 MaybeUninit::uninit().assume_init() 这类晦涩写法,专门用于凭空构造零大小类型(ZST);它依然标为 unsafe,因为像 PyO3 里的 Python<'py> 这类零大小令牌代表着持有 Python 全局解释器锁(GIL),随意构造会直接击穿并发安全边界。
迎战 AI 供应链投毒,Cargo 冷却期的三道后门与构建排雷
在 Cargo 追踪议题 #17009 中,贡献者 Giles Cope 曾于 2026 年 5 月 25 日发出预警,指出 AI 辅助供应链攻击正在加速,亟需落地基于 RFC 3923 的依赖最小发布时间。随后的稳定化 PR #17335 在 Amazon Linux(含 x86_64 与 arm64 架构)上,针对微虚拟机 Firecracker 等 16 个场景跑通了 1 天冷却期验证。
企业安全团队现在只需在 .cargo/config.toml 的 [registry] 下配置 global-min-publish-age = "3 days"(默认值为 0 即关闭,针对 crates.io 的专属配置项 registry.min-publish-age 本次推迟发布),cargo update 解析依赖时就会自动跳过未满阈值的新版本。
把 Cargo 的实现与 pnpm、npm 横向拉通对比,能看清不同包管理器在工程可用性上的防线水位:
| 机制维度 | Cargo 1.100.0 | pnpm | npm | 实际工程影响 |
|---|---|---|---|---|
| 配置项与格式 | .cargo/config.toml 设语义化字符串(如 "3 days") | pnpm-workspace.yaml 设分钟数(三日为 4320) | .npmrc 设天数(三日为 3) | 语义字符串更易读,跨工具语法不通用 |
| 默认策略 | 默认 0(关闭),需手动配全局项 | 文档内置默认 1440 分钟,可回退较新版本 | 默认关闭 | 需 DevSecOps 主动改配置才生效 |
| 已有 Lockfile | 优先信任并保留 Cargo.lock 内版本 | 默认重新校验 lockfile 年龄 | 遵循已有锁文件 | 只要进过锁文件,年轻版本也不拦截 |
| 单包与紧急豁免 | 传环境变量配合 --precise 单次放行入锁 | 配 minimumReleaseAgeExclude 白名单 | 11.17.0 起支持 min-release-age-exclude | 零日漏洞抢修需提前改造 CI 脚本 |
| 二进制安装命令 | cargo install 完全忽略冷却期 | — | — | 命令行直接装工具有供应链漏网风险 |
当线上爆发零日漏洞、必须立刻拉取几小时前刚发布的修复补丁时,冷却机制会把救命补丁一起拦在门外。运维团队必须在流水线里显式传入环境变量 CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow,再配合 cargo update -p some-crate --precise 1.2.3 强行穿透冷却期,把新版本写入 Cargo.lock。
比紧急豁免更需要盯紧的,是这套防线留下的三处明确盲区。已记录在 Cargo.lock 中的版本不受影响;包索引中缺失 pubtime 发布时间戳的源永远不会被拦截;而直接运行 cargo install 安装二进制工具时,解析器会完全无视 min-publish-age。
雪上加霜的是,cargo install 在 1.100.0 中默认启用了 .crate 压缩包内自带的 Cargo.lock(解决陈年 Issue #7169),原先的 --locked 参数直接变成无操作。这项改动本是为了防止用户编译工具时因依赖漂移而报错,但与 cargo install 豁免冷却期叠加后,只要包作者在发版前把刚出炉的恶意依赖锁进 .crate,终端用户执行安装时就会照单全收。
准备在本周升级 1.100.0 的基建团队,还需要在 CI 流水线里排查三颗构建雷。Cargo 上线了自有 lint 系统 [lints.cargo],其中 cargo::unused_dependencies 能在构建全部相关 target 时揪出 Cargo.toml 里的僵尸依赖(不检查 dev-dependencies);但为了减少多 git worktree 下的缓存冲突(议题 #17287),Cargo 重构了 build-dir 中间产物哈希目录布局,任何在 Bazel、Buck2 或扫描脚本中硬编码解析 target/ 内部路径的工具都会当场失效,必须迁移至 Cargo JSON 消息接口。此外,闭包对 if let 变量的精确捕获(PR #154210)会改变部分代码的析构顺序(drop order),配合全 Edition ! 回退变更及 ARMv7-A 硬件浮点基线修正,无人维护的陈旧第三方依赖极易直接断编。
破兼容之戒偿旧债,百版之后的工程算盘
看懂了上面的技术细节,才能看清 Rust 1.100.0 真正的分水岭意义。
很多人把百版更新当成庆功宴,但我更在意官方在 ! 类型和 Allocator 上的出手方式。《韩非子》里讲“法与时转则治”,一门工业级语言最怕的不是特性慢,而是被早年的兼容性承诺捆死手脚,变成谁也不敢动祖宗之法的泥潭。
过去十年,C++ 标准委员会为了绝对的向后兼容与 ABI 稳定,多次在 std::pmr(多态内存资源)和异常规范上叠床架屋,旧包袱不肯扔,新特性就只能做成补丁套补丁。Rust 这次情况不完全一样,它有 Edition 机制做缓冲,但在跨版次混编的底层类型系统上,一样撞上了兼容性的铁板。
Rust 团队这次难得做对了一件事,就是承认“既要绝对不破兼容,又要彻底修好类型底座”是个伪命题。
为了把 Infallible 彻底焊进 !,官方宁可背上破坏 2015 至 2021 旧版次兼容性的骂名,也要用先发警告、替社区修公共包的方式把历史欠账一刀平掉。分配器也是同理,与其为了 Rc、Arc 和冷门容器的边角泛化再吵五年,不如先把 80% 系统级项目最急需的 Box 和 Vec 拆出来上市。这种“可控破坏”加“拆包交货”的务实算计,比发十个花哨的语法糖更有工程含金量。
反过来,我对 Cargo 这次的依赖冷却期就不太买账。
安全机制最忌讳给用户制造虚假的安全感。RFC 3923 讨论期间,社区曾争论过“公地悲剧”——如果所有人都设冷却期,新版本就没人试毒,普通 Bug 只会更晚暴露。为了向构建稳定性妥协,Cargo 最终端出了一个默认关闭、放行已有 Cargo.lock、豁免无时间戳源,且对 cargo install 完全不设防的折中方案。
前端的 pnpm 敢默认开启冷却阈值并校验锁文件,Cargo 却为了不弄挂现有的 CI 流水线和命令行安装体验,把最容易被黑客利用的 cargo install 留在了防线外面,还顺手把 .crate 内置的锁文件变成了默认放行凭证。企业安全团队如果以为配一行 global-min-publish-age 就能高枕无忧,迟早会在研发人员随手敲下的不带版本号的 cargo install 上栽跟头。
站在第 100 个版本的节点上,Rust 已经过了靠宏大叙事吸引信徒的阶段,全面进入了跟陈年技术债和现实供应链攻防死磕的深水区。接下来半年,真正检验这次拆包豪赌成败的变量有两个:一是社区在消化 Box 泛化带来的类型推导报错后,被切进 allocator_ext 的剩余半截分配器接口还能不能顺利合拢;二是各大企业在开启冷却期后,会不会倒逼 Cargo 团队把 cargo install 那道敞开的后门彻底焊上。
