将现有项目迁移到新版本

Rust 包含用于自动将项目从一个版本迁移到下一个版本的工具。它将更新您的源代码,使其与新版本兼容。简而言之,更新到新版本的步骤如下:

  1. 运行 cargo update 以将您的依赖项更新到最新版本。
  2. 运行 cargo fix --edition
  3. 编辑 Cargo.toml 并将 edition 字段设置为新版本,例如 edition = "2024"
  4. 运行 cargo buildcargo test 以验证修复是否有效。
  5. 运行 cargo fmt 以重新格式化您的项目。

以下章节将深入探讨这些步骤的细节,以及您可能在此过程中遇到的一些问题。

我们的目标是尽可能顺利地迁移到新版本。如果您发现升级到最新版本很困难,我们认为这是一个 bug。如果您在此过程中遇到问题,请提交 bug 报告。谢谢!

开始迁移

作为一个例子,让我们看看从 2015 版本迁移到 2018 版本。迁移到其他版本(如 2021 版本)的步骤基本相同。

假设我们有一个 crate,其 src/lib.rs 中有以下代码

#![allow(unused)]
fn main() {
trait Foo {
    fn foo(&self, i32);
}
}

此代码使用了一个匿名参数,即 i32。Rust 2018 不支持 这样做,因此这将无法编译。让我们更新这段代码!

更新您的依赖项

在开始之前,建议您更新您的依赖项。一些依赖项,特别是某些 proc-macros 或执行构建时代码生成的依赖项,可能与较新的版本存在兼容性问题。自您上次更新以来,可能已经发布了新的版本,这些版本可能会修复这些问题。运行以下命令

cargo update

更新后,您可能需要运行测试以验证一切是否正常工作。如果您正在使用诸如 git 之类的源代码控制工具,您可能希望单独提交这些更改,以保持提交的逻辑分离。

更新您的代码以与新版本兼容

您的代码可能使用也可能不使用与新版本不兼容的功能。为了帮助迁移到新版本,Cargo 包含 cargo fix 子命令,以自动更新您的源代码。要开始,让我们运行它

cargo fix --edition

这将检查您的代码,并自动修复它可以修复的任何问题。让我们再次查看 src/lib.rs

#![allow(unused)]
fn main() {
trait Foo {
    fn foo(&self, _: i32);
}
}

它已经重写了我们的代码,为 i32 值引入了一个参数名称。在本例中,由于它没有名称,cargo fix 将其替换为 _,这是未使用的变量的惯例。

cargo fix 并不总是能自动修复您的代码。如果 cargo fix 无法修复某些内容,它将在控制台中打印无法修复的警告。如果您看到这些警告之一,您将必须手动更新您的代码。有关迁移过程的更多信息,请参阅高级迁移策略章节,并阅读本指南中解释需要哪些更改的章节。如果您遇到问题,请在 用户论坛 寻求帮助。

启用新版本以使用新功能

为了使用一些新功能,您必须显式选择加入新版本。一旦您准备好继续,请更改您的 Cargo.toml 以添加新的 edition 键/值对。例如

[package]
name = "foo"
version = "0.1.0"
edition = "2018"

如果不存在 edition 键,Cargo 将默认使用 Rust 2015 版本。但在本例中,我们选择了 2018,因此我们的代码将使用 Rust 2018 编译!

在新版本中测试您的代码

下一步是在新版本上测试您的项目。运行您的项目测试以验证一切是否仍然正常工作,例如运行 cargo test。如果发出新的警告,您可能需要考虑再次运行 cargo fix(不带 --edition 标志)以应用编译器给出的任何建议。

此时,您可能仍然需要进行一些手动更改。例如,自动迁移不会更新 doctest,并且构建时代码生成或宏可能需要手动更新。有关更多信息,请参阅高级迁移章节

恭喜!您的代码现在在 Rust 2015 和 Rust 2018 中都有效!

使用 rustfmt 重新格式化

如果您使用 rustfmt 来自动维护项目中的格式,那么您应该考虑使用新版本的新的格式规则重新格式化。

在重新格式化之前,如果您正在使用诸如 git 之类的源代码控制工具,您可能希望在执行此步骤之前提交您到目前为止所做的所有更改。将格式更改放在单独的提交中可能很有用,因为这样您就可以看到哪些更改只是格式更改,哪些是其他代码更改,并且还可以忽略 git blame 中的格式更改。

cargo fmt

有关更多信息,请参阅风格版本章节

迁移到不稳定版本

版本发布后,到下一个版本发布大约有三年的窗口期。在此期间,可能会向下一个版本添加新功能,这些功能仅在 nightly channel 上可用。如果您想在这些新功能稳定之前帮助测试它们,您可以使用 nightly channel 来试用它们。

这些步骤与稳定通道大致相似

  1. 安装最新的 nightly 版本:rustup update nightly
  2. 运行 cargo +nightly fix --edition
  3. 编辑 Cargo.toml 并在顶部([package] 之上)放置 cargo-features = ["edition20xx"],并将 edition 字段更改为 edition = "20xx",其中 20xx 是您要升级到的版本。
  4. 运行 cargo +nightly check 以验证它现在在新版本中是否有效。

⚠ 注意:在下一个版本中实现的功能可能没有使用 cargo fix 实现的自动迁移,并且这些功能本身可能尚未完成。如果可能,本指南应包含有关哪些功能在 nightly 版本上实现的信息以及有关其状态的更多信息。在新版本稳定之前的几个月,所有新功能都应完全实现,并且 Rust 博客 将发布征集测试的公告。