Rust 1.52.1 发布

Rust团队准备了一个新版本 1.52.1,以解决增量编译中的一个错误,该错误在 1.52.0 中变成了编译器错误。我们建议所有 Rust 用户,包括当前使用 1.52.0 之前的稳定版本的用户,升级到 1.52.1 或禁用增量编译。下面提供了有关操作方法的指南。

如果您通过 rustup 安装的 Rust 旧版本,则获取 Rust 1.52.1 就像下等操作一样简单:

rustup update stable

如果还没有,可以从我们 Rust 官网上的相应页面获取 rustup

概括

此版本适用于 1.52.0 损坏的版本,这些版本是由新添加的验证引起的。该验证检测到的错误在所有 Rust 版本1 中都存在,并且可能在增量版本中触发错误编译,因此降级到先前的稳定版本不是一个解决方案。

鼓励用户升级到 1.52.1 或在其本地环境中禁用增量版本(如果使用的是早期版本):请参阅“您应该做什么”部分以获取有关如何执行此操作的详细信息。

默认情况下,对于发行版本,增量编译是关闭的,因此,几乎不影响生产版本(仅适用于已选择加入的用户)。

由增量编译中的错误引起的错误编译会在最终工件中生成不正确的代码,从而本质上生成格式错误的二进制文件,这意味着从理论上讲,任何行为都是可能的。实际上,我们目前只知道一种已知的错误编译,但是众所周知,由于增量引起的错误很难跟踪:如果用户发现二进制文件有意外结果,则经常在进行一些轻度编辑后就简单地对其进行重新构建,这使得重新编译能够解决这些 bug。

本文包含以下内容:

  1. 解释错误是什么样的
  2. 从更高层次来解释检测的行为
  3. 解释该检测如何在 Rust 1.52.0 版本中显示出来
  4. 告诉你如果在项目中看到“found unstable fingerprints”,应该怎么做
  5. 介绍我们对 Rust 项目将如何解决这里讨论的问题的计划。

错误是什么样的?

错误消息看起来像这样,关键部分是"found unstable fingerprints" (发现不稳定的指纹)文本。

thread 'rustc' panicked at 'assertion failed: `(left == right)`
  left: `Some(Fingerprint(4565771098143344972, 7869445775526300234))`,
  right: `Some(Fingerprint(14934403843752251060, 623484215826468126))`: found unstable fingerprints for <massive text describing rustc internals elided>

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

这是由内部一致性检查引起的错误,并且如诊断中所述,它会产生"Internal Compiler Error"(或 ICE,即内部编译器错误)。换句话说,它表示 Rust 编译器本身内部的错误。在这种情况下,ICE 在 1.52.0 版本之前揭示了增量编译中的一个错误,如果未发现它,可能会导致错误编译。

什么是指纹?我们为什么要检查它们?

Rust 编译器支持“增量编译”,这已在 2016 年的博客文章中进行了描述。启用增量编译后,编译器会将输入源分成多个部分,并跟踪这些输入部分如何影响最终的构建产品。然后,当输入发生更改时,它会检测到这一点并重用以前构建中的工件,从而努力将精力仅花在构建需要响应输入源代码更改的部分上。

指纹是我们的体系结构的一部分,用于检测输入何时发生变化。更具体地说,指纹(以及其他一些用于建立上下文的状态)是一个 128 位的值,旨在唯一地标识编译器中使用的内部值。运行之间,一些编译器内部结果存储在磁盘上(“缓存”)。指纹用于验证新计算的结果与缓存的结果有没有变化。(有关更多详细信息,请参见 rustc 开发人员指南的相关章节。)

指纹稳定性检查是维护指纹内部一致性的一种安全措施。有时,编译器被迫重新运行查询,并期望输出与先前的增量编译会话的输出相同。新启用的验证将检查该值是否确实符合预期,而不是假设是。在某些情况下,由于编译器实现中的错误,实际上并非如此。

历史

早在 2017 年,我们最初就将这些指纹检查添加为开发 rustc 时使用的工具。它仅通过不稳定的 -Z 选项提供,仅适用于 nightly 和开发版本。

最近,在 3 月,我们遇到了一次错误编译,导致我们默认情况下处于打开状态 verify-ich。Rust编译器团队决定最好捕获指纹问题并中止编译,而不是让潜在的错误编译(以及随后的不当行为)潜入 Rust 开发者的二进制文件中。

默认情况下,当我们首次打开指纹检查功能时,nightly(和 beta)工具链的用户经常提交问题,并且在识别修复程序方面已经取得了稳步进展,其中许多修复程序已经发布。

在过去的一周中,我们已经开始制定计划来提高用户体验,以便检查所发出的诊断将更好地告诉程序员该怎么做。不幸的是,预定的计划是新验证功能将在 1.53 完成和发布,而不是1.52。

事实证明 verify-ich 是在最近发布的 1.52.0 版本中打开的。

如今的新版本 1.52.1 通过临时更改 Rust 编译器中的默认值以禁用增量来解决由新添加的验证引起的损坏,除非用户有意加入,否则禁用增量。

如何显示

本质上,对于某些 crate,某些顺序的编辑和编译循环将导致 rustc 产生 “unstable fingerprints” 的 ICE。我在此博客文章的开头展示了一个示例。

最近的另一个示例如下所示

thread 'rustc' panicked at 'found unstable fingerprints for predicates_of(<massive text describing rustc internals elided>)', /rustc/.../compiler/rustc_query_system/src/query/plumbing.rs:593:5

当将存储在磁盘上的增量编译高速缓存与当前 rustc 调用期间计算的值进行比较时,它们都是由不一致引起的,这意味着它们都是由使用增量编译引起的。

你可以通过几种方式打开增量编译:

  1. 你可能正在使用 devtest 配置文件进行构建,默认情况下启用了增量编译。
  2. 你可能已经设置了环境变量 CARGO_INCREMENTAL=1
  3. 你可能已在 Cargo 配置中启用了该 build.incremental 设置
  4. 你可能已在给定配置文件 Cargo.toml 中启用了 incremental

如果您的项目没有调整默认值,则在所有 Rust 版本1 运行 cargo build --release 或在其他 release 情况下禁用概要文件配置中的增量,那么这些问题不会影响你的发行版。

Rust 开发者面对这问题应该怎么做

内部编译器错误要求你报告错误,如果可以,我们仍然需要该信息。我们知道失败的案例。

但是,无论你是否提交错误,都可以通过以下任一方法最终解决该问题:

  1. 如果尚未升级的话可升级到 1.52.1(这将为您禁用增量)
  2. 或者删除你的增量编译缓存(例如通过运行 cargo clean
  3. 或者强制增量编译被禁用,通过在你的环境设置 CARGO_INCREMENTAL=0 或在 config.tomlbuild.incremental 设为 false

我们建议 1.52.0 的用户升级到 1.52.1,这将禁用增量编译。

我们不建议 1.52.0 的用户降级到 Rust 的早期版本以来回应此问题。如上所述,有一种无声的至少一个实例错误编译造成未被捕获,直到我们加入了指纹检查增量编译。

如果用户愿意处理增量验证 ICE,并希望重新选择 1.52.0 行为,则可以在自己的环境中设置 RUSTC_FORCE_INCREMENTAL1。然后,Rust 编译器将遵循 -CincrementalCargo 传入的选项,尽管添加了验证,但一切仍将像以前一样工作。请注意,如果尚未分别启用此标志(无论是通过 Cargo 还是其他方式),则不会启用增量。

如果您当前使用的是 1.52.0 之前的工具链,并且希望继续使用,我们建议您禁用增量编译,以免发生无提示的错误编译。

在 Rust 引入自渐进式以来的所有版本,构建的编译时间对许多用户来说都是一项重大改进,并且仅随着时间的推移而有所改进。我们承认,此处介绍的变通办法和建议很痛苦,我们将努力跟进以尽可能确保这种情况是一种临时行为。

Rust 项目团队将如何解决此问题

短期计划

我们今天发布了 1.52.1,其中:

  • 禁用Rust编译器中的增量编译(除非新的环境变量要求 RUSTC_FORCE_INCREMENTAL=1)。
  • 如果启用了增量编译,则改进了用于新验证的诊断输出,指示了如何通过清除增量状态或禁用增量来解决错误。

这是为了缓解这种情况,它可以帮助大多数 Rust 用户升级到安全的 Rust 编译器的方式,该编译器不会冒错误地编译其代码的风险,但也为愿意解决错误的用户提供了选择。

我们希望继续积极投入精力来修复错误,并基于我们对修复的信心,可能会发布 1.52.2 的小版本,以将这些修复反向移植到稳定版中。希望帮助我们进行测试的用户可以使用 nightly 版本,看到的任何 ICE 报告的错误可发到 rust-lang/rust。

我们目前还不打算在 beta 通道上禁用增量功能,但尚未坚定地执行此决定。今天 1.53 Beta 中提供了许多修复程序,因此希望继续使用增量功能的用户可以切换到该版本。当然,nightly 版一直会提供最新的修复程序。

长期计划

长期计划是修复错误!增量编译是 Rust 编译器能够为其所有开发者提供快速编辑-编译-运行周期的唯一现实方法,因此,我们需要解决迄今已通过 verify-ich 确定的所有问题。(在撰写本文时,有 32 个此类问题,尽管其中许多是重复的。)

我们正在对此进行积极的投入精力,并且已经发现并修复了许多错误。根据修补程序的状态,将来的稳定版本(1.53 及更高版本)可能会重新启用增量编译。

Rust 团队还将制定计划,以确保我们将来有更好的 bug 跟踪系统,当这些这些功能分发后,既可以防止此类情况再次发生,也可以通过更准确地跟踪 bug 来进一步提高我们版本的稳定性。跨渠道传播。


1

自从首次启用增量功能以来的版本,该功能已在 Rust 1.24 中提供。