完成向新借用检查器的过渡

2019 年 11 月 1 日 · Niko Matsakis

在 2018 年的大部分时间里,我们一直在针对借用检查器中我们计划修复的各种错误发布警告 -- 大约两个月前,在当前的 Rust nightly 版本中,这些警告变成了硬错误。大约两周后,当 nightly 分支成为 beta 版本时,这些硬错误将进入 beta 构建版本,并最终在 12 月 19 日随 Rust 1.40.0 一起进入 stable 版本。如果您正在使用 Nightly 版本进行测试,那么您应该没问题 -- 但否则,您可能需要去检查以确保您的代码仍然可以构建。如果不能,我们有关于修复常见问题的建议如下。

背景:非词法生命周期的过渡

当我们在 Rust 1.31 中发布 Rust 2018 时,它包含了一个新版本的借用检查器,该版本实现了“非词法生命周期”。这个新的借用检查器比原始版本进行了更精确的分析,使我们能够消除许多不必要的错误,并使 Rust 更易于使用。我认为大多数使用 Rust 2015 的人都可以证明这个转变是一个巨大的改进。

新的借用检查器也修复了许多错误

可能不太为人所知的是,新的借用检查器实现修复了许多错误。换句话说,新的借用检查器不仅仅接受了更多程序 -- 它也拒绝了一些原本只因旧借用检查器中的内存不安全错误而被接受的程序!

直到最近,这些已修复的错误才会产生警告而非错误

显然,我们不希望接受可能损害 Rust 安全保证的程序。同时,作为我们对稳定性的承诺的一部分,我们尽量避免进行会影响大量代码的突然错误修复。只要可能,我们更倾向于逐步“分阶段引入”这些更改。我们通常从“未来兼容性警告”开始,例如,然后(有时一次只改动一点)将这些警告变为硬错误。由于借用检查器的错误修复影响了许多 crate,我们知道在将它们变为硬错误之前需要一个警告期。

为了实现这个警告期,我们保留了借用检查器的两个副本(这实际上是我们经常使用的一个技巧)。新的检查器首先运行。如果它发现错误,我们不会直接报告它们:而是运行旧的检查器,以查看该 crate 之前是否可以编译。如果可以,我们就将这些错误报告为未来兼容性警告,因为我们将之前可以编译的东西更改为错误。

好事终将结束;坏事也一样

随着时间的推移,我们一直在将这些未来兼容性警告缓慢地、一点一点地转变为错误。大约两个月前,我们决定是时候完成这项工作了。因此,通过两个 PR(拉取请求),我们将所有剩余警告转换为错误,然后移除了旧的借用检查器实现

这对您意味着什么

如果您正在使用 nightly 版本测试您的包,那么您应该没问题。实际上,即使您在 stable 版本上构建,我们也始终建议您在 CI 中使用 nightly 版本测试您的构建,以便您可以及早发现即将出现的问题并报告给我们。

否则,您可能需要检查您的依赖项。当我们决定移除旧的借用检查器时,我们还分析了哪些 crate 会停止编译。对于任何看起来被广泛使用的东西,我们都确保有可用的更新版本的该 crate,这些版本确实可以编译(大部分情况下,这在警告期内就已经完成了)。但是,如果您的 Cargo.lock 文件中有那些旧版本,并且您只使用 stable 构建版本,那么一旦 1.40.0 发布,您可能会发现您的代码无法再构建 -- 您将不得不升级依赖项。

受影响的最常见 crate 如下

  • url 1.7.0 版本 -- 您可以升级到 1.7.2,不过最好升级到 2.1.0
  • nalgebra 0.16.13 版本 -- 您可以升级到 0.16.14,不过最好升级到 0.19.0
  • rusttype 0.2.0 到 0.2.3 版本 -- 您可以升级到 0.2.4,不过最好升级到 0.8.1

您可以使用 cargo-tree 命令找出您依赖于哪些 crate。如果您发现您确实(例如)依赖于 url 1.7.0,您可以通过执行以下命令升级到 1.7.2

$ cargo update --package url --precise 1.7.2

想了解更多?

如果您想了解更多关于已修复错误的类型 -- 或者如果您的代码中出现了需要修复的错误 -- 请查看 Felix Klock 这篇出色的博客文章,其中详细介绍了相关内容。