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

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 可用,这些 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 的这篇精彩的博文,其中详细介绍了这些内容。