Rust 版本
rust-version
字段是一个可选键,用于告诉 cargo 你的包支持哪个版本的 Rust 工具链。
[package]
# ...
rust-version = "1.56"
Rust 版本必须是至少包含一个组件的裸版本号;它不能包含 semver 运算符或预发布标识符。检查 Rust 版本时,编译器预发布标识符(如 -nightly)将被忽略。
MSRV: 自 1.56 版本起生效
用途
诊断
当你的包在不受支持的工具链上编译时,Cargo 会向用户报告错误。这使得支持预期清晰明了,并避免报告不太直接的诊断信息,例如标准库中的无效语法或缺失功能。这会影响包中的所有 Cargo 目标,包括二进制文件、示例、测试套件、基准测试等。用户可以使用 --ignore-rust-version
标志选择启用不受支持的包构建。
开发辅助
cargo add
会自动选择依赖项的版本要求,使其成为与你的 rust-version
兼容的最新版本。如果这不是最新版本,cargo add
会通知用户,以便他们可以选择是保留它还是更新你的 rust-version
。
解析器在选择依赖项时可能会考虑 Rust 版本。
其他工具也可以利用它,例如 cargo clippy
的 incompatible_msrv
lint。
注意:可以使用
--ignore-rust-version
选项忽略rust-version
。
支持预期
这些是一般预期;某些包可能会在其文档中说明何时不遵循这些预期。
完整性
在每个 feature 下,所有功能(包括二进制文件和 API)都可在受支持的 Rust 版本上使用。
已验证
包的功能已在其受支持的 Rust 版本上经过验证,包括自动化测试。另请参阅我们的Rust 版本 CI 指南。
可补丁性
当许可证允许时,用户可以使用你的包的分支来覆盖其本地依赖项。在这种情况下,Cargo 可能会为打补丁的依赖项加载整个工作区,该工作区应在受支持的 Rust 版本上工作,即使工作区中的其他包支持不同的 Rust 版本。
依赖项支持
为了支持上述内容,预期每个依赖项的版本要求至少支持一个与你的 rust-version
兼容的版本。然而,不预期依赖项规范会排除与你的 rust-version
不兼容的版本。实际上,同时支持两者可以让你在支持旧版本 Rust 的用户和不支持旧版本 Rust 的用户之间取得平衡。
设置和更新 Rust 版本
支持哪些 Rust 版本需要在以下几点之间进行权衡
- 维护者因不使用 Rust 工具链或其依赖项的新功能而付出的成本
- 用户因包使用工具链的新功能而产生的成本(他们本可以从中受益),例如通过将 polyfill 迁移到标准库中的功能来减少构建时间
- 对于支持旧版本 Rust 的用户而言,包的可用性
注意:更改
rust-version
被视为次要不兼容性。
建议:选择一个关于支持哪些 Rust 版本以及何时更改此版本的策略,以便用户可以将其与自己的策略进行比较,如果策略不兼容,则决定是否可以接受放弃一般改进或无法修复的阻塞性错误的风险。
最简单的支持策略是始终使用最新的 Rust 版本。
根据你的风险状况,下一个最简单的方法是继续支持你的包中支持旧版本 Rust 的旧主版本或次版本。
选择受支持的 Rust 版本
你的包的用户最有可能依据以下方面追踪他们受支持的 Rust 版本
- 他们的 Rust 工具链供应商的支持策略,例如 Rust 项目或 Linux 发行版
- 注意:Rust 项目仅为最新版本提供错误修复和安全更新。
- 用户使用新工具链重新验证其包的固定计划,例如,每年的第一个版本,每 5 个版本。
此外,用户不太可能立即使用新的 Rust 版本,他们需要时间来注意并重新验证,或者他们的计划可能不完全一致。
版本策略示例
- “N-2”,表示“最新版本,提供 2 个版本的更新宽限期”
- 每个偶数版本,提供 2 个版本的更新宽限期
- 本日历年中的每个版本,提供一年的更新宽限期
注意:要查找与你的项目当前状态兼容的最低
rust-version
,可以使用第三方工具,如cargo-msrv
。
更新时间线
当你的策略指定你不再需要支持某个 Rust 版本时,你可以立即或在需要时更新 rust-version
。
通过允许 rust-version
偏离你的策略,你为用户提供了更多的升级宽限期。然而,这太不可预测了,无法依赖它来与用户所追踪的 Rust 版本保持一致。
rust-version
偏离你指定的策略越远,用户越有可能推断出你未曾打算的策略,从而因期望未得到满足而感到沮丧。
当允许偏离时,就会出现什么程度的“合理性足够”来放弃受支持版本的问题。每个人都可以得出合理不同的理由;进行这样的讨论对于相关方来说可能会令人沮丧。这将削弱那些想要避免此类冲突的人,特别是对于新入职或临时贡献者而言,他们要么觉得自己没有资格提出这个问题,要么觉得冲突可能会影响其更改被合并的机会。
工作区中的多策略
Cargo 允许在一个工作区内支持多个策略。
在特定的 Rust 版本下验证特定的包可能会变得复杂。cargo-hack
等工具可以提供帮助。
对于跨策略共享的任何依赖项,必须使用最低的共同版本,因为 Cargo 统一了 SemVer 兼容的版本,这可能会限制具有较高 rust-version
的工作区成员访问共享依赖项的功能。
为了允许用户修补你工作区成员之一上的依赖项,工作区中的每个包都需要能够在工作区支持的最旧的 Rust 版本中加载。
使用 incompatible-rust-versions = "fallback"
时,一个包的 Rust 版本可能会影响为另一个具有不同 Rust 版本的包选择的依赖项版本。有关更多详细信息,请参阅解析器章节。
一种或多种策略
缓解支持旧版本 Rust 带来的缺点的一种方法是将你的策略应用于你继续支持的包的旧主要或次要版本。与这些主要或次要版本的发布分支相比,你可能仍然需要一个关于开发分支支持哪些 Rust 版本的策略。
仅在“需要”时更新开发分支可以帮助减少受支持的发布分支的数量。
问题在于可以将哪些内容回移植到这些发布分支中。通过在次版本之间回移植新功能,下一个可用版本将缺少它,这可能被视为一个破坏性变更,违反了 SemVer。回移植更改也伴随着引入错误的风险。
支持旧版本需要付出代价。这个代价取决于包中错误的风险和影响以及回移植的可接受程度。按需创建发布分支并将回移植的负担放在社区身上是平衡此代价的方法。
依赖管理工具目前还没有办法报告非最新版本仍然受支持,这将注意到这一点的责任转移到了用户身上,他们需要在文档中查看。
例如,Rust 版本支持策略可能如下所示
- 开发分支追踪 Rust 项目的最新稳定版本,并在需要时更新
- 更改
rust-version
时,次版本将升高
- 更改
- 项目支持本历年的每个版本,并提供额外一年的宽限期
- 支持受支持 Rust 版本的最后一个次要版本将收到社区提供的错误修复
- 修复必须回移植到开发分支和所需受支持 Rust 版本之间的所有受支持次要版本