


2026 年 10 月 5 日,Rust 1.99.0 正式发布。本次更新覆盖语言能力、编译器、平台支持、标准库、Cargo、Rustdoc、兼容性行为以及内部工具链升级等多个方向。
从开发者最容易感知的变化来看,Rust 1.99.0 带来了 C 可变参数函数定义稳定化、裸函数定义 C 可变参数函数能力稳定化、多个内存与原始指针相关 API、Box<[T; N]> 的迭代支持、Vec 原始部分拆装能力、文件时间设置接口,以及 Cargo 工作区依赖默认特性覆盖行为的改进。
同时,本版本也包含不少需要关注的兼容性变化,例如旧式整数模块被完全弃用、泛型项使用 no_mangle 升级为硬错误、CI 环境中 Cargo 默认禁用增量编译,以及文档注释、宏、联合体模式匹配等方面的行为调整。
下面按照语言、编译器、平台、库、Cargo、Rustdoc、兼容性和内部变更逐项展开。
一、语言层面的更新
Rust 1.99.0 在语言能力和诊断能力方面新增了多项变化,其中既包括新的 lint,也包括 C 互操作性、属性宏模块声明、内联汇编和 UnsafeCell 语义保证等内容。
1. 新增默认允许的 raw_borrows_via_references lint
本版本新增了一个默认允许的 raw_borrows_via_references lint。
该 lint 用于检查一种特定情况:某个引用在创建后立刻衰减为原始借用。也就是说,代码中先产生引用,随后又立即将其转换为原始借用时,编译器可以针对这种模式进行检查。
由于该 lint 默认处于允许状态,因此它不会直接改变现有代码的编译结果。开发者可以根据项目需要主动启用,以便识别这类引用快速转化为原始借用的写法。
2. unconditional_panic lint 扩展到 chunks 和 windows 的零大小调用
unconditional_panic lint 的检测范围得到了扩展。
现在,当调用会因 chunks 或 windows 的大小参数为零而发生 panic 的函数时,编译器也能够进行检测。这意味着,原本仅在部分显而易见的无条件 panic 场景中发挥作用的 lint,如今也能覆盖切片分块和滑动窗口相关的零尺寸调用。
对于依赖运行时参数传入大小值的代码来说,这项变化能够更早暴露明显错误的调用方式。
3. C 可变参数函数定义正式稳定
Rust 1.99.0 稳定了 C 可变参数函数定义能力。
这意味着,Rust 现在可以在稳定版本中定义符合 C 可变参数形式的函数,用于处理类似 C 语言中可变数量参数的函数签名。该能力对于与 C 接口进行更深入互操作的场景具有重要意义。
同时,标准库中也稳定了 core::ffi::VaList,为处理 C 可变参数相关逻辑提供了对应的类型支持。
4. 裸函数定义 C 可变参数函数能力稳定
除了 C 可变参数函数定义本身,Rust 1.99.0 还稳定了使用 unsafe(naked) 裸函数来定义 C 可变参数函数的能力。
此前,这项能力需要通过 c_variadic_naked_functions 特性使用。现在,该能力进入稳定范围。
裸函数通常具有更严格的使用要求和更少的编译器自动生成行为。将它与 C 可变参数函数定义结合,进一步完善了 Rust 在底层接口、特殊调用约定和 C 兼容场景中的表达能力。
5. never 类型经过调整后参与 trait 方法解析
Rust 1.99.0 中,trait 方法现在会在经过调整的 never 类型上进行解析,并且会产生 FCW。
这属于类型系统与方法解析机制的调整。对于涉及 never 类型、类型调整和 trait 方法调用的代码,编译器的解析行为将按照新的规则执行。
6. 推断变量可在特定子类型关系下强制转换为 trait 对象
本版本改进了从推断变量到 trait 对象的强制转换规则。
当一个推断变量通过子类型关系关联到一个已知为 Sized 的类型时,该推断变量可以被强制转换为 trait 对象。
这一变化属于类型推断与 trait 对象转换的改进,使某些原本受限于推断信息的场景获得更明确的处理能力。
7. 属性宏和派生宏中可在任意位置使用外部模块声明
Rust 1.99.0 稳定了在自定义属性宏或派生宏主体中的任意位置使用外部模块声明的能力。
换句话说,类似 mod foo; 这样的外部模块声明,不再局限于某些特定位置,而是可以出现在自定义属性宏或派生宏的主体中。
这项稳定化使宏相关代码中对于模块拆分和组织方式的表达更加灵活。
8. overflowing_literals 对重复负号的处理得到修复
overflowing_literals lint 修复了对重复取负场景的处理。
例如,--128_i8 这样的表达式此前可能触发 overflowing_literals lint。现在,它不再由该 lint 报告,因为这种情况已经可以由 arithmetic_overflow lint 检测。
这项调整使不同 lint 的职责更加明确:重复取负导致的问题由算术溢出相关 lint 负责,而不再由字面量溢出 lint 重复报告。
9. 两个运行时符号定义 lint 新增 POSIX 符号检查
invalid_runtime_symbol_definitions 和 suspicious_runtime_symbol_definitions 两个 lint 现在加入了 POSIX 符号。
这意味着,涉及运行时符号定义的检查范围进一步扩大,POSIX 相关符号也将被纳入无效或可疑定义的检测范围。
10. 内联模块中未使用的 path 属性将触发 lint
Rust 1.99.0 会对内联模块中未使用的 path 属性进行 lint 检查。
如果一个内联模块上使用了 path 属性,但该属性实际上没有发挥作用,编译器将能够提示这一问题。
这有助于发现模块组织代码中遗留、无效或与预期不一致的路径属性配置。
11. unreachable_cfg_select_predicates 被纳入 unused lint 组
unreachable_cfg_select_predicates lint 现在作为 unused lint 组的一部分启用。
这意味着,无法到达的条件编译选择谓词将被归入未使用相关检查中。项目如果对 unused lint 组进行了统一配置,也将同时覆盖这一项检查。
12. x86 平台 asm 支持通过向量寄存器传递 128 位整数
Rust 1.99.0 稳定了在 x86 平台上,通过 asm! 的向量寄存器传递 128 位整数的能力。
这一变化与内联汇编相关。对于需要在 x86 平台上通过内联汇编操作或传递 128 位整数的低层代码,现在可以使用向量寄存器完成相应传递。
13. 明确部分分配允许原地扩容,但不允许原地缩容
本版本明确记录了一项分配行为规则:某些分配允许原地增长,但没有任何分配被允许原地缩小。
这是一项文档层面的明确化。它说明了内存分配在尺寸变化时的保证边界:增长可能在原始位置完成,而缩小则不具有原地完成的许可。
14. UnsafeCell 内容可在不经过 get 的情况下访问
Rust 1.99.0 现在保证,UnsafeCell 中的内容可以不通过 get 来访问。
与此同时,invalid_reference_casting lint 也根据这一保证进行了调整。
这两项变化共同影响与 UnsafeCell、引用转换和底层内存访问相关的代码。此前某些依赖于特定访问路径的理解,现在有了新的明确保证;相关 lint 的判断也随之适配。
15. global_asm 会考虑全局启用的目标特性
global_asm! 现在会考虑全局启用的 target feature。
这意味着,在全局汇编场景下,编译器会将全局启用的目标特性纳入处理范围。对于依赖特定目标特性的全局汇编代码,这是一项行为上的完善。
16. 宏调用使用无效文档属性时会出现警告
当宏调用上使用了无效的文档属性时,Rust 1.99.0 会发出警告。
这项改进加强了文档属性使用的检查。若某个文档属性不适用于宏调用,编译器将不再静默接受,而是给出相应提示。
二、编译器更新
Rust 1.99.0 的编译器变化主要集中在目标 CPU 参数、位置无关可执行文件,以及方法缺失建议质量三个方面。
1. AVR、AMDGCN 与 NVPTX 中的 target-cpu 处理变化
对于 AVR、AMDGCN 和 NVPTX,-Ctarget-cpu 现在会被转换为 target modifier。
这项调整影响这些目标平台上的编译参数处理方式。原本以目标 CPU 参数形式提供的信息,将以目标修饰符的形式参与目标配置。
2. 所有 GNU 目标启用静态位置无关可执行文件
Rust 1.99.0 在所有 GNU target 上启用了 static_position_independent_executables。
这一变化统一了 GNU 目标上的相关可执行文件配置行为。
3. 缺失方法建议优先采用完全匹配的 doc alias
当编译器针对缺失方法给出建议时,Rust 1.99.0 会优先选择来自文档别名且名称完全匹配的方法,而不是仅通过其他方法名的相似度搜索给出建议。
如果库作者发现新用户常常以另一个名称寻找某个方法,可以为该方法添加文档别名。这样做不仅有助于 Rustdoc 搜索,也有助于编译器在缺失方法诊断中给出更准确的建议。
这项更新的重点在于:完全匹配的文档别名优先级高于普通的相似名称匹配。
三、平台支持更新
Rust 1.99.0 将 riscv64-unknown-linux-musl 提升为 Tier 2,并提供 host tools。
这意味着,该目标的平台支持等级得到提升。有关 Rust 分层平台支持的更多信息,可参考 Rust 平台支持页面。
四、标准库与核心库更新
本版本的库更新包括 RangeInclusive 迭代优化、transmute_copy 调整、字符串转义行为变化、格式化缓冲区再导出,以及一批稳定 API。
1. RangeInclusive 迭代性能优化及耗尽后行为调整
RangeInclusive,即 a..=b 形式的闭区间范围,在某些情况下获得了更好的迭代优化。
这一优化带来了一个附带变化:已经作为迭代器耗尽的 RangeInclusive 值,其行为发生了调整。
例如,对于已经耗尽的范围:
start()的返回值可能与此前不同。end()的返回值可能与此前不同。- 将这种范围作为切片索引时,行为也可能不同。
这些行为此前并没有稳定性保证,因此这次调整不被视为破坏性变更。
需要注意的是,变化只涉及已经耗尽后仍被继续观察或使用的 RangeInclusive 值。
2. transmute_copy 放宽为接受 ?Sized 类型
transmute_copy 现在放宽限制,可以接受 ?Sized 类型。
这意味着,相关接口不再仅局限于 Sized 类型,而是能够覆盖更广泛的类型参数形式。
3. transmute_copy 改用不展开的 panic
transmute_copy 的 panic 行为也进行了更新:现在使用不会展开的 panic。
这项调整影响 transmute_copy 在发生 panic 时的处理方式。
4. escape_debug_ext 不再转义两个特定字符
escape_debug_ext 不再转义 U+FF9E 和 U+FF9F。
这两个字符的调试转义行为在 Rust 1.99.0 中发生改变,不再被转换为转义表示。
5. alloc 重新导出 core::fmt::NumBuffer
core::fmt::NumBuffer 现在被重新导出到 alloc 中。
因此,相关格式化数字缓冲区类型可以通过 alloc 获得。
五、本次稳定的 API 汇总
Rust 1.99.0 稳定了一批新的 API,涵盖数组装箱迭代、双端队列保留、可变参数列表、非空指针与 Box 转换、Vec 原始部分拆装、原始值布局查询、字符串 UTF-8 容错处理,以及文件时间设置等能力。
1. Box 数组迭代相关
以下能力稳定:
IntoIterator for Box<[T; N]>IntoIterator for &Box<[T; N]>IntoIterator for &mut Box<[T; N]>
这意味着,装箱数组本身、装箱数组的共享引用,以及装箱数组的可变引用,都支持相应的迭代器转换。
2. VecDeque 新增 retain_back
稳定 API:
VecDeque::retain_back
该接口用于从双端队列尾部方向执行保留相关操作。
3. C 可变参数列表支持
稳定 API:
core::ffi::VaList
该类型与 C 可变参数函数处理相关。
4. Box 与 NonNull 的转换接口
稳定 API:
Box::into_non_nullBox::from_non_null
这两个接口用于 Box 与非空指针之间的转换。
5. Vec 原始组成部分的拆分与重建
稳定 API:
Vec::into_partsVec::from_parts
这组接口用于获取 Vec 的组成部分,以及从对应部分重新构造 Vec。
6. 原始值布局查询接口
稳定 API:
core::mem::size_of_val_rawcore::mem::align_of_val_rawcore::alloc::Layout::for_value_raw
这些接口与原始值的大小、对齐要求和布局计算有关。
7. 字符串 UTF-8 容错处理接口
稳定 API:
String::from_utf8_lossy_ownedstring::FromUtf8Error::into_utf8_lossy
这组接口用于 UTF-8 容错转换相关场景。
8. StepBy 实现 FusedIterator
稳定项:
FusedIterator for StepBy<I>
StepBy<I> 现在实现了 FusedIterator。
9. 文件时间设置接口
稳定 API:
std::fs::set_timesstd::fs::set_times_nofollow
这两个接口用于设置文件时间,其中后者具有不跟随符号链接的语义。
六、Cargo 更新
Rust 1.99.0 中的 Cargo 更新主要涉及新的内置 profile、工作区依赖默认特性覆盖,以及 CI 环境下的增量编译默认行为。
1. 新增内置 debug profile
Cargo 新增了一个内置的 debug profile。
这一变化是为后续将 dev profile 从调试用途逐步过渡出来做准备,目标是为更快的开发迭代提供更合理的默认设置。
需要注意的是,在当前版本中,dev 和 debug profile 之间没有差异。
该更新对应文档编号 17214。
2. 2024 及之后版本工作区成员可覆盖依赖 default-features
当工作区成员使用 2024 或更高版本时,现在可以覆盖继承自工作区依赖的 default-features 字段。
例如,工作区中某个依赖启用了默认特性,而成员 crate 使用类似下面的配置:
toml
serde = { workspace = true, default-features = false }
那么该成员 crate 可以关闭默认特性。
对于更早版本的 edition,default-features = false 会被忽略,同时 Cargo 会给出警告。
这一变化对应 RFC 3945,并关联编号 17126。
3. CI 环境默认禁用增量编译
Cargo 现在会在 CI 环境中默认禁用增量编译。
CI 环境通过 CI 环境变量进行检测。
这意味着,当 CI 环境变量存在时,Cargo 默认不会启用增量编译。该更新关联编号 17220。
七、Rustdoc 更新
Rustdoc 在本版本中新增了 lint,同时对 trait 实现过滤进行了性能优化。
1. 新增 unused_footnote_definition lint
Rustdoc 新增了 unused_footnote_definition lint。
该 lint 用于检查未被使用的脚注定义,帮助发现文档中存在但没有被引用的脚注内容。
2. trait 实现过滤性能提升
Rustdoc 改进了 trait 实现的过滤方式。
根据更新说明,这项优化平均可以带来约 20 的性能提升,在部分真实世界 crate 中,性能提升最高可达到约 40。
这项优化主要体现在 Rustdoc 对 trait 实现信息进行筛选时的处理效率。
八、兼容性注意事项
Rust 1.99.0 包含一系列兼容性调整。其中有些是错误修复,有些是 lint 范围变化,有些则会直接影响已有代码的编译结果或行为。
升级时需要重点关注以下内容。
1. 旧式整数模块被完全弃用
旧式整数模块现在被完全弃用。
例如,原先的:
rust
std::i32::MAX
应改为:
rust
i32::MAX
也就是说,整数类型关联常量应通过类型本身访问,而不再使用旧式标准库整数模块路径。
2. 泛型项使用 no_mangle 升级为硬错误
对泛型项使用 no_mangle,现在从原有状态升级为硬错误。
这意味着,相关代码不再只是得到提示或警告,而会直接导致编译失败。
3. Pin::new_unchecked 的安全不变量略有变化
Pin::new_unchecked 的安全不变量发生了轻微调整。
使用该接口的代码需要注意其安全前提已经发生变化,并根据新的不变量要求审查相关实现。
4. 不再提升对 extern static 的引用
Rust 1.99.0 不再提升对 extern static 的引用。
这项变化影响外部静态变量引用相关的提升行为。
5. 确保 let 模式的推断类型通过类型检查
现在,let 模式中推断出的类型会被确保通过类型检查。
该调整涉及 let 模式、类型推断和类型检查之间的处理一致性。
6. hermit/fs 返回 unsupported
在 hermit 的文件系统实现中,现在返回 unsupported(),而不再返回 from_raw_os_error(22)。
这是平台相关文件系统行为的一项调整。
7. 修复稳定 Rust 中宏调用意外允许 repr(simd) 的问题
此前,稳定 Rust 中宏调用上意外允许使用 repr(simd)。
Rust 1.99.0 修复了这一问题,稳定 Rust 不再错误地允许这种情况。
8. 常量求值在产出值类型中存在泛型时中止
当正在产生的值的类型中包含泛型时,常量求值会中止。
这一变化影响涉及泛型类型和常量求值的代码。
9. 文档注释代码块中未应用到任何对象的属性现在是错误
在文档注释的代码块中,如果某个属性没有应用到任何内容,现在会成为错误。
此前这类情况的处理方式不同;升级后,文档示例代码中的无效属性需要被修正。
10. Box::leak 文档提示避免反向恢复
Box::leak 的相关说明现在会提示开发者避免将泄漏后的值反向恢复。
这是对该接口使用方式的文档提示调整。
11. PowerPC 内联汇编修复小端标量浮点所在向量通道
PowerPC 内联汇编修复了一个问题:在小端模式下,标量浮点数此前位于错误的向量通道中。
Rust 1.99.0 对这一行为进行了修正。
12. doctest 过滤不再考虑 doc(cfg())
在过滤 doctest 时,不再考虑 doc(cfg())。
这意味着,文档条件配置不再参与 doctest 过滤时的判断。
13. 关联常量类型中的匿名生命周期推断为 static
关联常量类型中的匿名生命周期现在会被推断为 static。
这是一项生命周期推断规则调整。
14. 非本地宏产生分号的表达式警告范围扩大
如果宏展开为一个分号,现在即使该宏来自其他 crate,也会触发 semicolon_in_expressions_from_non_local_macros 警告。
此前,为了避免显示本地无法修复的警告,这类提示通常只会针对来自同一 crate 的宏出现。但这种处理掩盖了问题,因为提供宏的 crate 的集成测试会作为独立 crate 编译,测试中往往无法暴露这个问题。
如果遇到此类 lint,应向提供该宏的 crate 报告问题,让其修复,而不是仅在自身项目中静默处理。
15. semicolon_in_expressions_from_macros 相关 lint 拆分
本版本中:
semicolon_in_expressions_from_macros现在也会检查非本地宏。- 针对非本地宏的分号表达式检查被拆分为独立 lint。
这使本地宏与非本地宏在分号表达式问题上的诊断范围更加明确。
16. 联合体模式匹配建议发生调整
Rust Reference 不再建议使用单一模式将 union 与另一个值一起进行匹配,例如手动编写的带标签 union。
原因是,某些情况下,这种代码会导致编译器在检查模式其余部分是否匹配之前,先读取 union 的内容。
对于类似此前建议的代码,这可能导致未定义行为。
因此,相关模式匹配写法不再被推荐。
九、内部变更
Rust 1.99.0 还包含不影响公开接口的内部改进。
这些变化不会直接改变 Rust、rustc 或相关工具对外提供的公共接口,但代表了编译器性能和内部实现方面的重要改进。
本版本最显著的内部工具链更新是:
- 更新到 LLVM 23
LLVM 更新通常会影响编译器后端和相关内部能力,但本次说明明确指出,这部分变更不影响公开接口。
十、总结
代码地址:github.com/rust-lang/rust
Rust 1.99.0 是一个覆盖面很广的版本。
语言层面,C 可变参数函数定义和裸函数中的 C 可变参数能力进入稳定状态;原始借用、UnsafeCell、目标特性、内联汇编、宏属性和多项 lint 得到完善。
标准库层面,Box、Vec、VecDeque、字符串、文件时间、原始值布局查询和可变参数列表等 API 完成稳定化;RangeInclusive 获得优化,但已耗尽范围的观察行为需要重新注意。
Cargo 层面,新 debug profile 为未来 profile 调整铺路,工作区依赖特性覆盖能力更灵活,CI 环境则默认关闭增量编译。
兼容性方面,旧式整数模块、泛型项 no_mangle、宏展开分号、文档代码块属性、联合体模式匹配以及常量求值等变化,都值得在升级时逐项检查。
对于计划升级到 Rust 1.99.0 的项目,建议重点审查以下内容:
- 是否仍在使用旧式整数模块路径。
- 是否存在泛型项使用
no_mangle。 - 是否依赖已耗尽
RangeInclusive的start()、end()或切片索引行为。 - 是否在 CI 中依赖增量编译。
- 是否存在文档代码块中未应用到任何对象的属性。
- 是否使用了可能展开为分号的外部宏。
- 是否涉及
UnsafeCell、Pin::new_unchecked、C 可变参数、裸函数、内联汇编和 union 模式匹配等底层代码。