2021 年 5 月 10 日,Felix Klock 和 Mark Rousskov 代表 Rust 编译器团队发布文章 Announcing Rust 1.52.1,官宣发布 Rust 1.52.1。
以下为官方公告原文——
Rust 团队新发布的 Rust 1.52.1,解决了一个增量编译中的 bug,这个 bug 在 1.52.0 中,会导致一个编译器错误。我们建议所有 Rust 用户(包括使用 1.52.0 及之前稳定版本的用户)升级到 1.52.1,或者也可以禁用增量编译。如下是升级指导。
如果你已通过 rustup
安装了 Rust 的早期版本,那么更新到 Rust 1.52.1 相当容易:
rustup update stable
如果您还未安装过 Rust,可以从 Rust 官网页面获取 rustup
。
如果官方途径安装速度较慢,可以配置 Rust 工具链的国内源,请参阅《配置 Rust 工具链的国内源》。
此次发布,是针对 1.52.0 版本上的问题构建的,这些问题因新添加的验测而起。此次验测工作检测到的 bug,存在于 Rust 1.24 之后的版本中(因为增量编译是自 Rust 1.24 启用)。并且可能触发增量构建中的错误编译,因此降级到以前的稳定版本,并非解决方案。
因此,建议所有用户升级到 1.52.1,或在本地环境中禁用增量(如果使用 1.52.0 及之前版本):有关如何禁用增量
的详细信息,请参阅小节: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.
这是内部一致性检查导致的错误,如诊断中所述,它会产生“内部编译器错误”,也称作 ICE。换句话说,它代表了 Rust 编译器内部的一个 bug。具体在本例中,既是 ICE 揭示了关于增量编译的一个 bug。在早于 1.52.0 的版本中,或许没有捕获到它,但可能会导致错误编译。
Rust 编译器支持“增量编译”,在 2016 年的博客文章中,对有描述。当增量式编译开启时,编译器会将输入源分割成多个片段,并追踪这些输入片段如何影响最终的构建产品。然后,当输入发生变化时,它会检测到这一点并重用以前构建的工件,努力让构建需要的响应输入,仅在源代码发生变化的部分上花费精力。
编译器指纹(fingerprints)是我们体系结构的一部分,用来检测输入变化。更具体地说,编译器指纹(fingerprints,以及建立上下文的一些其它状态)是一个 128 位的值,用于唯一标识编译器中使用的内部值。某些编译器内部结果,在运行时缓存(cached)在磁盘上。编译器指纹(fingerprints)用于验证新计算的结果,是否与缓存的结果相同(有关这方面的详细信息,请参阅《rustc 开发指南》的相关章节)。
编译器指纹(fingerprints)的稳定性检查,是维护编译器指纹(fingerprints)内部一致性的保障措施。有时,编译器被迫重新运行检查,并期望输出与以前会话的增量编译输出相同。新启用的验证,将检查该值是否确实如预期的那样,而不是假设是这样。但在某些情况下,由于编译器实现中的错误,实际情况并非如此。
我们将编译器指纹(fingerprints)检查作为 rustc 开发工具的最初时间,是在 2017 年。它是作为一个不稳定的(unstable)标志 -Z
提供的,只对 nightly 版和开发版的构建可用。
最近,在 3 月份,我们遇到了一个错误编译,导致我们在默认情况下打开了 verify-ich
。Rust 编译器团队认为:最好是捕获编译器指纹(fingerprints)问题并中止编译,而不是允许潜在的错误编译(以及随后的错误行为),以防止错误潜入二进制文件中。
当我们第一次默认开启编译器指纹(fingerprints)检查时,nightly 和 beta 版工具链的用户,会不断提交问题(issues),并且在修复方面也取得了稳步进展。其中一些已经解决。
上周,我们已经开始编制改善用户体验的计划,这样检查发出的诊断就可以更好地告诉程序员应该做什么。不幸的是,这样做的前提是:新的验证本将在 1.53 中发布,而非 1.52。
但最近发布的版本 Rust 1.52.0(请参阅 Rust 1.52.0 已正式发布,及其新特性详述),启用了 verify-ich
。
今天的新版本 Rust 1.52.1,解决了因新添加的验证而导致的问题。此版本中,临时将 Rust 编译器中的默认值更改为禁用增量编译
,除非用户有意选择启用。
从本质上讲,对于某些 crate,特定的编辑-编译(edit-compile)周期序列,将导致 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
调用期间计算的值进行比较时,出现了不一致情况。这意味着,它们都是由于使用增量编译造成的。
如下方法可以开启增量编译:
dev
或 test
配置文件进行构建。CARGO_INCREMENTAL=1
。build.incremental
。incremental
。如果项目中没有调整默认值,那么当运行 cargo build --release
时,或在 release
配置文件中,所有 Rust 1.x 都将禁用增量编译
。这些问题,不应该影响你的版本发布。
如果你发生内部编译器错误,请你报告此 bug。我们仍然需要该方面的信息,想知道失败的案例。
但是,无论你是否提交 bug,你都可以通过以下方式解决问题:
cargo clean
),或者CARGO_INCREMENTAL=0
,或在 config.toml
中指定 build.incremental
为 false
,强制禁用增量编译。我们推荐用户都将 1.52.0 升级为 to 1.52.1,这样做即可禁用增量编译。
我们不建议 Rust 1.52.0 的用户,为了应对这个问题而降级到 Rust 的早期版本。如上所述,至少有一个实例,由于增量编译导致了错误编译。在我们添加编译器指纹(fingerprints)检查之前,错误未被捕获。
Rust 1.52.1 的用户,如果希望自行处理增量验证的 ICE(译注:内部编译错误)问题,并希望选择返回版本 1.52.0。则可以在环境变量中,设置 RUSTC_FORCE_INCREMENTAL=1
。如此,Rust 编译器将执行 Cargo 传递的选项 -Cincremental
,尽管添加了验证,但仍将以前版本一样工作。请注意,Rust 1.52.1 中,如果此标志尚未单独启用(无论是通过 Cargo 还是其它方式),则不会启用增量。
如果你当前正在使用 1.52.0 之前的工具链,并且希望继续这样做,我们建议你禁用增量编译,以避免出现无提示的错误编译。
自从增量编译启用以来,在所有的 Rust 构建中,编译时间对许多用户来说,都是一个重大的改进,而且会随着时间的推移而逐步改进。我们承认,这里提出的解决办法和建议,多用户来说是痛苦的,我们将努力保证这只是暂时的解决方案。
译注:计划方面,和上文多有重复,即是配置环境变量和设置指定文件的反复。所以未再详细翻译,所有翻译开源在 github.com/zzy/blog.rust-lang.org-zh-cn,欢迎你补充和完善。
既是我们发布了此 1.52.1 版本。
修复错误。
谢谢您的阅读,欢迎交流。