- 文档
【免费下载链接】rfcs
RFCs for changes to Rust
本指南围绕已合并进 RFC 仓库的 RFC 2834(对应实现追踪于 rust-lang/rust#71249)展开,系统讲解 Cargo 如何在构建结束阶段向开发者汇报上游依赖中触发"未来不兼容(future-incompatibility)"警告的 crate,即使这些警告已被--cap-lints=allow或#[allow(..)]抑制。读完本文,你将掌握该机制要解决的问题、rustc与 Cargo 的职责边界、构建结束报告的完整形态与cargo describe-future-incompatibilities的用法,以及.cargo/config中报告频率控制配置的设计思路,并理解其与仓库内相关 RFC 的演进关系。
背景:cap-lints机制及其副作用
要理解 RFC 2834,必须先理解它要对抗的机制——--cap-lints。仓库中的 RFC 1193 "cap-lints" 定义了该标志:
--cap-lints LEVEL设置本次编译的最高 lint 等级,不能被其他标志或属性覆盖。
其可接受值为allow、warn、deny、forbid。当传入--cap-lints allow时,源码中所有#[warn]、#[deny]、#[forbid]都会被忽略;传入--cap-lints warn时,只有deny和forbid指令被忽略。
RFC 1193 同时规定 Cargo 在编译所有上游依赖(非 path 依赖)时一律传入--cap-lints allow。这样做的理由很充分:如果上游 crate 使用了#![deny(warnings)],而新版本 Rust 引入了新的警告,上游依赖就可能编译失败,形成隐式破坏性变更。将上游依赖的 lint 封顶,可以让编译器在向后兼容的前提下自由演进 lint 集合。
然而副作用也随之而来:未来不兼容(future-incompatibility)lints 同样被cap-lints抑制了。这类 lint 标记的是一段"计划在未来的某个 Rust 版本中被移除/变成硬错误"的代码模式,通常涉及可能产生未定义行为(unsound)或语义未明确定义的构造。它们恰恰是开发者最需要提前知道的信号——因为一旦对应版本发布,整个项目将直接编译失败。
核心问题:下游维护者被蒙在鼓里
RFC 2834 引用了 rust-lang/rust#34596 中的一段经典描述:
如果你编写了一个被广泛使用的库,但当下并未积极使用它,你可能注意不到它将来会坏掉——而且,你的用户也不会注意到,因为 Cargo 在把你的库作为依赖编译时会封顶 lints。
运行示例:unwary与brash
RFC 用一对虚构 crate 说明问题:unwary依赖上游 cratebrash,而brash的源码触发了未来不兼容 lint——对 packed 字段的借用&x.data.0(即"safe packed borrows"问题,见 rust-lang/rust#46043)。
今天的实际行为如下:由于brash是unwary的非 path 依赖,构建unwary时 Cargo 会给rustc传入--cap-lints=allow,从而在诊断输出中完全抑制brash的警告:
crates % cd unwary unwary % cargo build # no warning issued about problem in the `brash` dependency. Compiling brash v0.1.0 Compiling unwary v0.1.0 (/tmp/unwary) Finished dev [unoptimized + debuginfo] target(s) in 0.30s unwary % cd ../brash brash % cargo build # (but a `brash` developer will see it when they build.) Compiling brash v0.1.0 (/tmp/brash) warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) --> src/lib.rs:13:9 | 13 | let y = &x.data.0; | ^^^^^^^^^ | = note: `#[warn(safe_packed_borrows)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043> = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior Finished dev [unoptimized + debuginfo] target(s) in 0.30s brash %也就是说:brash的维护者自己构建时能看到警告,但unwary的维护者构建项目时看不到任何提示——直到某个未来的 Rust 版本发布,unwary直接编译失败。
反馈不能只是原始诊断输出
RFC 特别强调:反馈不应仅仅是brash的原始诊断输出。unwary的维护者在短期内通常无法对上游 crate 的警告做任何事(可以向brash提 issue 甚至贡献修复代码,但在brash发布新版本之前,这并不能解决眼前的问题)。因此,如果 Cargo 直接把上游的诊断一股脑铺在终端里,对unwary的维护者而言只是噪音。
正确做法是:继续对上游依赖传递--cap-lints=allow,同时让rustc通过某种渠道告诉 Cargo"哪些 crate 触发了未来不兼容 lint",再由 Cargo 在构建结束时给出简洁的汇总报告。
提案总览:保留 cap-lints,增加汇总报告
RFC 2834 的设计目标可以概括为三条:
- 继续传递
--cap-lints=allow:非 path 上游依赖的正常 lint 仍被封顶,不改变既有行为。 rustc上报触发信号:即使警告被抑制,rustc也要通过某种通道告知 Cargo 未来不兼容 lint 被触发了。cargo汇总反馈:在构建结束时输出一份精炼报告,列出哪些 crate 包含未来会被拒绝的代码,并(可选)给出解决建议。
RFC 还设想 Cargo 可以额外提供解决策略的反馈,例如:
- 查询本地 index:看上游 crate 是否有更新版本可用,若有则建议用户通过
cargo update升级(这只是一种启发式手段,并不会预先验证新版本是否真的解决了问题;若 Cargo 未运行在 offline 模式,也可进一步查询 crates.io 本身,但查询 index 在实践中通常已足够); - 建议提交 bug:提示
unwary维护者到上游 crate 的源码仓库提交或搜索已归档的 issue(brash作者可能自己都不知道这个问题——例如他在该 lint 随编译器发布之前就停止了维护); - 标注截止时间:
rustc为每个未来不兼容 lint 内嵌"距离变成硬错误还有多久"的信息,让维护者知道还有多少时间窗口去推动上游修复或更换 fork。
这些建议的具体形式不在 RFC 的强制范围内,详见后文"未来可能性"一节。
用户视角:构建结束时的报告形态
什么是"未来不兼容"
RFC 给出的定义:未来不兼容(future incompatibility)是指计划在未来某个 Rust 版本中从语言中移除的代码模式。这类模式通常是无未定义行为但语义未完全定义、或确实 unsound 的构造,但因为被广泛使用,需要一段宽限期再移除。
构建结束报告
在 Cargo 完成一个 crate 及其上游依赖的编译后,如果任何 crate(或其上游依赖)触发了未来不兼容警告、且整体编译没有错误,Cargo 会在编译结束阶段列出所有触发该警告的 crate;可能时,报告还会包含预计 Rust 停止编译该代码的未来日期或版本号:
crates % cd unwary unwary % cargo build Compiling brash v0.1.0 Compiling bold v0.1.0 Compiling rash v0.1.0 Compiling unwary v0.1.0 Finished dev [unoptimized + debuginfo] target(s) in 0.30s warning: the crates brash, bold, and rash contain code that will be rejected by a future version of Rust. note: the crate rash will stop compiling in Rust 1.50 (scheduled for February 2021). note: to see what the problems were, invoke `cargo describe-future-incompatibilities` unwary %注意这里报告的是crate 名级别的汇总,而非逐个表达式的诊断,这正是 RFC 刻意设计的"简洁"形态。
依赖图中的多重版本
如果当前 crate 的依赖图中存在同一 crate 的多个版本被列入了结束报告,那么结束报告应明确指出是哪个(或哪些)版本触发了 lint。这对cargo tree里常见的传递依赖版本分叉场景至关重要——维护者需要知道该去升级哪一条依赖链。
cargo describe-future-incompatibilities:查看详细诊断
报告末尾的 note 提示用户调用cargo describe-future-incompatibilities。该命令会让 Cargo 查询上一次构建缓存的信息,打印出更有信息量的诊断:
unary % cargo describe-future-incompatibilities The `brash` crate currently triggers a future incompatibility warning with Rust, with the following diagnostic: > warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) > --> src/lib.rs:12:9 > | > 12 | let y = &x.data.0; // UB, also future-compatibility warning > | ^^^^^^^^^ > | > = note: `#[warn(safe_packed_borrows)]` on by default > = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! > = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043> > = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior The `bold` crate currently triggers a future incompatibility warning with Rust, with the following diagnostic: > warning: private type `foo::m::S` in public interface (error E0446) > --> src/lib.rs:5:5 > | > 5 | pub fn f() -> S { S } > | ^^^^^^^^^^^^^^^^^^^^^ > | > = note: `#[warn(private_in_public)]` on by default > = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! > = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> The `rash` crate currently triggers a future incompatibility warning with Rust, with the following diagnostic: > error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. > --> src/lib.rs:4:8 > | > 4 | fn bar<T=i32>(x: T) { } > | ^ > | > = note: `#[deny(invalid_type_param_default)]` on by default > = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! > = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>这个"汇总报告 + 按需查看明细"的两级设计,让想搞清楚问题的开发者有路可循,又不会用他们本地开发用不上的信息淹没所有人的诊断输出。
重编译时报告仍会保留
即使上游依赖没有重新编译,重建unwary时结束报告依然会输出——因为 Cargo 会把未来不兼容状态缓存在target/目录中:
unwary % touch src/main.rs unwary % cargo build Compiling unwary v0.1.0 Finished dev [unoptimized + debuginfo] target(s) in 0.30s warning: the crates brash, bold, and rash contain code that will be rejected by a future version of Rust. note: the crate rash will stop compiling in Rust 1.50 (scheduled for February 2021). unwary % note: to see what the problems were, invoke `cargo describe-future-incompatibilities`根 crate 自身触发时的一致性
为了用户体验一致,即使根 crate 自己是触发未来不兼容 lint 的唯一来源,Cargo 也应在结束阶段发出同样的警告(此时构建过程中的原始警告依然照常显示):
crates % cd brash brash % cargo build Compiling brash v0.1.0 (/tmp/brash) warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) --> src/lib.rs:13:9 | 13 | let y = &x.data.0; | ^^^^^^^^^ | = note: `#[warn(safe_packed_borrows)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043> = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior Finished dev [unoptimized + debuginfo] target(s) in 0.30s warning: the crate brash contains code that will be rejected by a future version of Rust. brash % cargo build Finished dev [unoptimized + debuginfo] target(s) in 0.00s warning: the crate brash contains code that will be rejected by a future version of Rust. note: to see what the problems were, invoke `cargo describe-future-incompatibilities` brash %注意第二次构建(增量、无编译发生)依然输出了警告,印证了"报告依赖缓存、不依赖重建"的设计。
无警告时输出不变
如果没有任何未来不兼容警告,Cargo 的输出与今天完全一致。例如unwary升级了brash的版本、切换到bold2(bold的 fork)、并用本地代码替换了对rash的使用,从而消除了所有触发点:
crates % cd unwary unwary % cargo build Compiling brash v0.2.0 Compiling bold2 v0.1.0 Compiling unwary v0.2.0 Finished dev [unoptimized + debuginfo] target(s) in 0.30s unwary %参考级设计:rustc与 Cargo 的职责划分
RFC 2834 的核心约束是最小化对现有 Rust 用户的干扰:正常 lint 检查继续被抑制,因此 Cargo 继续对非 path 上游依赖传递--cap-lints=allow。
-Dwarnings语义保持不变
与 lint 直接交互的标志(如-Dwarnings)行为不变。以unwary为例:
- 无论是
cargo rustc -- -Dwarnings还是RUSTFLAGS=-Dwarnings cargo build,每次rustc调用的方式都相同,产出的诊断集合也与今天一致; - 下游
brash这个非 path 依赖中的警告 lint 依旧被 cap,其未来不兼容警告仍被隐藏; - Cargo 在构建结束时输出的"
brash包含未来将被拒绝的代码"报告不是 lint,不与-Dwarnings交互; - 结论:即使你向
rustc传了-Dwarnings,收到未来不兼容报告也不会导致构建失败。
rustc的职责
编译器侧的行为会有轻微变化:即使在--cap-lints=allow开启的情况下,rustc也需要让 Cargo 知道未来不兼容 lint 何时被触发。具体而言:
rustc必须把未来不兼容 lints(参见 PR #59658 "Minimum Lint Levels")与那些"永远只是警告"的普通 lints 区分开来;rustc需要一种新的操作模式,RFC 称之为future-incompatibility checking mode(未来不兼容检查模式):- 在该模式下,无论是否设置了
--cap-lints=allow,都要检查未来不兼容 lints 的触发; - 在该模式下,无论代码是否出现在
#[allow(..)]属性作用域内,也要检查这类 lint; - 在该模式下,诊断本身的输出仍可按
--cap-lints=allow或#[allow(..)]被静默——这些标志/注解的语义是"静默诊断报告",但不是"静默关于源码中存在 lint 触发实例的反馈"; - 该模式旨在解决 rust-lang/rust#34596 的主体问题。
- 在该模式下,无论是否设置了
Cargo 的职责
- 以启用未来不兼容检查模式的方式调用
rustc——无论是否同时传递--cap-lints=allow; - 捕获检查模式产出的任何输出,并在整个构建结束时汇总;
- 将每个 crate 的未来不兼容记录存储在
target/目录某处,从而在后续重建根 crate 时无需重编译即可输出同样报告(RFC 指出这在今天是容易满足的约束:nightly 渠道的 Cargo 已经在本地缓存构建上游 path 依赖时产生的警告); - 向用户建议解决问题的途径,具体策略不由本 RFC 强制规定。
实现策略:借助 JSON 错误格式
RFC 认为最干净的实现方式是:让rustc把--error-format=json视作"应当为当前 crate 输出未来不兼容汇总报告"的信号——扩展rustc的 JSON 输出,加入一条记录本次编译触发过的未来不兼容 lint 的新记录。
选用 JSON 的好处在于:JSON 记录更易于扩展,可以稳健地承载"该 lint 何时变为硬错误"这类元数据。不过 RFC 并不强制这一选择,其他选项包括使用环境变量 opt-in 改变rustc输出,或让rustc把未来不兼容元数据写入文件系统。
不是所有未来不兼容 lint 都有明确的"变为硬错误"时间表。RFC 假设会通过某种方式为它们建立排期,并要求每个未来不兼容 lint 的元数据都应包含(若已知)其变为硬错误的预期 Rust 版本——这也是采用 JSON 诊断的另一层动机。
相关政策考量
RFC 指出:不应盲目地把所有 lint 都纳入这套机制——当前被归类为C-future-incompatibility的 lint 并非都适合此机制,这是相关团队的政策决策,具体形态不在 RFC 范围内。
无论政策形式如何,有一点值得注意:遇到上游未来不兼容问题的用户,可能既没有空闲时间也没有外部开发资源。rustc开发者需要谨慎决定何时让某个 lint 开始通过该机制上报:
- 如果首要目标是最大程度减少用户对工具和生态的挫败感,那么某个 lint 的未来不兼容上报应等到生态中大部分 crate 都已发布修复版本之后再开启;
- 换句话说,应当追求一种稳态:典型用户面对未来不兼容报告时的反应,是运行
cargo update,或请求合并一个(已存在的)PR。
频率控制:.cargo/config的future_incompatibility_report配置
"每次构建都提醒"对某些用户可能过于打扰——短期无法解决被标记的问题是很常见的。因此 RFC 提议扩展.cargo/config文件,让用户微调 Cargo 打印报告的频率。完整的提议配置如下:
[future_incompatibility_report] # This setting can be used to reduce the frequency with which Cargo will report # future incompatibility issues. # # The possible values are: # * "always" (default): always emit the report if any future incompatibility # lint fires, # * "never": never emit the report, # * "post-cargo-update": emit the report the first time we encounter a given # future incompatibility lint after the most recent # `cargo update` run for a crate, # * "daily": emit the report the first time any particular lint fires each day, # * "weekly": emit the report the first time any particular lint fires # each week (starting from Monday, following ISO 8601), # * "lunar": emit the report the first time any particular lint fires every # four weeks. (We recommend using this value in tandem with # an IDE that presents the current phase of the moon in its UI.) frequency = "always" # This allows a further fine-tuning for lints that have been given an # explicit schedule for when they will be turned into hard errors. # # If false, such scheduled lints are treated the same as unscheduled ones. # # If true, such scheduled lints issue their report more frequently # as time marches towards the release date when the warning becomes an error. # # Specifically, # * 6 weeks before that release, the report is emitted at least once per week, # * 2 weeks before that release, the report is emitted on every build. # # (Note that a consequence of the above definition, this value of this setting # has no effect if the `future_incompat_report_frequency` is "always".) telescoping_schedule = true逐项解读:
frequency:可选值为"always"(默认,只要有未来不兼容 lint 触发就报告)、"never"(永不报告)、"post-cargo-update"(自最近一次对该 crate 执行cargo update之后,首次遇到某个未来不兼容 lint 时报告一次)、"daily"(每个 lint 每天首次触发时报告)、"weekly"(每周首次触发时报告,从周一开始,遵循 ISO 8601)、"lunar"(每四周首次触发时报告,RFC 调侃建议配合一个能显示月相的 IDE 使用);telescoping_schedule:针对有明确"变为硬错误"排期的 lints 进一步微调。为false时,有排期的 lint 与无排期的同等对待;为true时,随着发布日临近报告越发频繁——发布前 6 周起至少每周报告一次,发布前 2 周起每次构建都报告。注意:当frequency = "always"时该设置不产生额外效果。
RFC 明确表示:它并不真正规定上述键值集合,而是信任 Cargo 团队来确定向用户暴露哪些合适的旋钮。这种"设计授权"也让最终实现可能与 RFC 文字略有出入。
缺陷与权衡(Drawbacks)
- 该变更同时要求修改
rustc和cargo,两者协调可能比较棘手; - RFC 建议的松耦合方式是"使用
--error-format=json即启用未来不兼容检查模式",这避免了给rustc增加新的稳定命令行标志;但任何使用--error-format=json的非 Cargo 客户端,可能觉得这是编译器语义上令人困惑的变化。
备选方案辨析(Rationale and alternatives)
"不做改变"可行吗?
有人认为"现有做法一直在工作,无需改变"。RFC 的反驳是:之所以至今没爆发,恰恰是因为编译器和语言团队在把现有未来不兼容 lint 转为硬错误时被迫非常保守——这种转变成本极高,而这在很大程度上正是本 RFC 要解决的那个问题。在少数已经转为硬错误的案例中,团队花费了大量时间用 crater 评估破坏面并逐一修复。本 RFC 的变更希望能鼓励编译器/语言团队之外的更多 Rust 用户主动处理未来不兼容的破坏。
能否仅靠 Cargo 实现?
一种思路是不改rustc、把实现完全隔离在 Cargo 内:停止传--cap-lints=allow,让 Cargo 捕获编译器的全部诊断输出并事后处理、判断哪些 lint 是未来不兼容警告。但这有三大问题:
- 脆弱:依赖 Cargo 事后处理编译器的诊断输出;
- 低效:编译器现在必须为 crate 的所有依赖运行全部 lint 检查,而我们只关心其中一小部分;
- 不足:它只能处理
--cap-lints的场景,无法捕捉上游依赖在源码中用#[allow(..)]属性规避警告的情况——而如果为了弥补这点去无条件改变rustc、让它无论--cap-lints=allow还是#[allow(..)]都输出未来不兼容反馈,又会惹恼那些期望这些标志/注解让诊断输出保持安静的人(也就是"编译器不听我的!")。这正是 RFC 坚持"--cap-lints=allow与#[allow(..)]继续静默诊断报告、仅把反馈限定为一句'crate brash 包含未来会被拒绝的代码'"的原因。
能否仅靠 rustc 实现?
PR #59658 "Minimum Lint Levels" 曾尝试在编译器内单独解决,做法是把未来不兼容 lint 标记为特殊情形、使其不受--cap-lints和#[allow(..)]静默。该 PR 的讨论列举了诸多问题,本质上是担心下游开发者被自己无能为力的 lints 刷屏。讨论的结论是:可以重做以降低刷屏——对每个依赖只报告 lint 的一次实例(而非该依赖中每个触发该 lint 的表达式各一条诊断)。这确实是改进,但仍不是理想体验。本 RFC 刻意把未来不兼容 lint 触发视为独立于普通诊断的严肃事件,值得 Cargo 特殊对待(甚至可能在线查询该 crate 是否有新版本)。注意:最低 lint 等级机制与本 RFC 不冲突,可以并行推进,只是它不足以单独解决眼前的问题。
扩展cap-lints层级是否更好?
另一个低影响方案是扩展--cap-lints的层级,使其变成:
allow warn-future-incompat warn deny-future-incompat deny这样--cap-lints=warn-future-incompat表示"允许(不警告)所有非未来不兼容 lint,仅对未来不兼容 lint 警告";--cap-lints=deny-future-incompat表示"对非未来不兼容 lint 警告、对未来不兼容 lint 报错"。并且(关键一步)把cargo build的默认值改为cap-lints=warn-future-incompat,让开发者默认就能直接得知依赖中的未来不兼容。
RFC 作者选择不采用该方案,因为怀疑它会遭遇与"minimum lint levels"相同的困境:抛出一堆开发者无法立即在本地解决的诊断。(不过它仍可能是值得加入rustc和cargo的合理功能。)
未解决的问题
- Cargo 自身发出的未来不兼容警告(如 rust-lang/cargo#6313 评论中所讨论的)应当被纳入支持,作者设想这不需要太多额外工作,但未明确处理也未深入调研;
- 实现层面的问题:用
--error-format=json作为把rustc切换进未来不兼容检查模式的方式是否合理?一个变体是改用--json CONFIG选项让 Cargo opt-in 该功能——这样已经使用--error-format=json的客户端就无需感知这一变化。
未来可能性:Cargo 给出的修复建议
RFC 设想的主要后续工作是 Cargo 围绕问题给出的反馈建议,列举了两种形态。
查询 crate 的新版/替代版本
当 crate 触发未来不兼容警告时,Cargo 可以到 crates.io 上查找该依赖的更新版本:
crates % cd unwary unwary % cargo build Compiling brash v0.1.0 Compiling bold v0.1.0 Compiling rash v0.1.0 Compiling unwary v0.1.0 Finished dev [unoptimized + debuginfo] target(s) in 0.30s warning: the crates brash, bold, and rash contain code that will be rejected by a future version of Rust. note: the crate rash will stop compiling in Rust 1.50 (scheduled for February 2021). note: newer versions of bold and rash are available; upgrading to them via `cargo update` may resolve their problems. unwary %该建议目前只覆盖"升级到新版本"。若得到 crates.io 的更多帮助,还可以走得更远:建议用户切换到的上游 crate 的潜在 fork——这对处理 abandoned(无人维护)的 crate 很有用。
建议提交 bug report
如果没有更新版本可用,Cargo 可以输出一份用户可提交给上游 crate 的 bug report 模板:
crates % cd unwary unwary % cargo build Compiling brash v0.1.0 Compiling unwary v0.1.0 Finished dev [unoptimized + debuginfo] target(s) in 0.30s warning: the crate brash contains code that will be rejected by a future version of Rust. note: the following gist contains a bug report you might consider filing with the maintainer of brash. https://gist.github.com/pnkfelix/ae03d3ea95160fb71a797b15e05f8d49 unwary %示例中模板被发布到 gist(使用作者自己的 GitHub 账号;RFC 坦言不确定能否让 Cargo 以匿名方式创建 gist,但应该能找到某种 pastebin 服务)。该模板的正文大致是:
这个 crate 目前触发了 Rust 的未来不兼容警告。 在 src/lib.rs:13:9 处有以下代码:
let y = &x.data.0;这导致rustc发出如下诊断(来自 https://github.com/rust-lang/rust/issues/46043):warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) ...由于该构造未来会变成硬错误,我们应该消除它的出现。
进一步细化:如果开始建议 bug report 模板,Cargo 或许还能在上游 crate 仓库中搜索与该模板描述匹配的既有 issue,并建议用户去查看其当前状态,而不是新开一个 issue——这样可以避免给上游维护者添麻烦。
与仓库其他 RFC 的关联
- RFC 1193 cap-lints:本 RFC 的基石。
--cap-lints标志与"Cargo 对上游依赖传--cap-lints allow"的约定,正是导致上游未来不兼容警告被隐藏的根源,也是 RFC 2834 选择继续保留的机制; - RFC 1589 rustc-bug-fix-procedure:展示了
rustc侧如何注册未来不兼容 lint——通过store.register_future_incompatible(sess, vec![FutureIncompatibleInfo { id: LintId::of(..), reference: "issue #...." }])把 lint 标记为FutureIncompatibleInfo。这正对应本 RFC 中"rustc必须区分未来不兼容 lints 与其他 lints"的职责要求; - RFC 3389 manifest lint:其 Drawbacks 一节明确指出
[lints]只影响关联包本身、不作用于依赖,因此无法与"针对依赖的未来不兼容 lints"协同工作,可能造成用户困惑——这从侧面印证了 RFC 2834 这类依赖级报告机制的必要性; - RFC 3874 与 RFC 3875:均提及
cargo report(RFC 2834 所述机制落地后的命令形态)不会包含标准库 crate 及其依赖的报告,说明这套报告机制在现代 Cargo 中已与 build-std 场景做了明确隔离。
小结
RFC 2834 为 Rust 生态解决了一个隐蔽而危险的"定时炸弹"问题:上游依赖中的未来不兼容代码因cap-lints而被无声容忍,直到某个 Rust 版本发布时项目猝然编译失败。它给出的答案是职责分离——rustc以 JSON 错误格式承载未来不兼容检查模式的信号,Cargo 负责汇总、缓存(target/目录)与频率控制(.cargo/config),并把详细的逐 crate 诊断留给按需调用的cargo describe-future-incompatibilities。对于下游维护者,这套设计把"知道问题存在"与"不被原始诊断刷屏"两件事同时做到了。
- 文档
【免费下载链接】rfcs
RFCs for changes to Rust
相关推荐
Cargo 的 future-incompat 报告机制:`cargo report future-incompatibilities` 命令全解析
Cargo 的 future incompat 报告机制: cargo report future incompatibilities 命令全解析 导读 car
开发工具包管理器CLI构建工具Rust RFCs 深度解析:cargo install 与 cargo uninstall 的命令设计与实践(RFC 1200)
Rust RFCs 深度解析:cargo install 与 cargo uninstall 的命令设计与实践(RFC 1200) 本文以 Rust RFC 仓
文档Rust RFC 2091 深度解读:用 `[track_caller]` 让 `unwrap()`/`expect()` 报告真实调用位置
Rust RFC 2091 深度解读:用 track_caller 让 unwrap / expect 报告真实调用位置 本文以 Rust RFC 仓库中的 t
文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考