Rust 2024 Edition
Migration with cargo fix --edition
cargo fix --edition is Cargo's automated migration tool that inspects your package under its current edition, enables the target edition's compatibility lint group (rust-2024-compatibility), and rewrites your source files in place so they compile cleanly under both the old and new editions.
4-Step Automated Edition Migration Workflow:
Step 1: Verify clean working tree & passing tests on current edition (`edition = "2021"`)
`cargo test --workspace --all-targets --all-features`
|
v
Step 2: Run automated edition migration rewrites
`cargo fix --edition --workspace --all-targets --all-features`
|
v
Step 3: Update `Cargo.toml` to `edition = "2024"`
(and `resolver = "3"` if specified in a virtual `[workspace]`)
|
v
Step 4: Format & verify under Rust 2024
`cargo fmt --all` && `cargo test --workspace --all-targets --all-features`
Lints Included in the rust-2024-compatibility Group
When you run cargo fix --edition, rustc activates the rust-2024-compatibility lint group and automatically applies code transformations for each lint:
| Compatibility Lint | What cargo fix --edition Rewrites Automatically |
|---|---|
missing_unsafe_on_extern |
Rewrites extern "C" { ... } to unsafe extern "C" { ... }. |
unsafe_attr_outside_unsafe |
Rewrites #[no_mangle], #[export_name = "..."], and #[link_section = "..."] to #[unsafe(no_mangle)], etc. |
deprecated_safe_2024 |
Wraps calls to std::env::set_var and std::env::remove_var in unsafe { ... } blocks (if not already inside one). |
keyword_idents_2024 |
Rewrites any variable, function, or type named gen to the raw identifier r#gen. |
impl_trait_overcaptures |
Appends + use<...> to -> impl Trait return types where existing call sites relied on Rust 2021's narrower lifetime capture rules! |
| Match Ergonomics Migration | Rewrites patterns with redundant ref / mut under reference binding modes to explicit & / * forms. |
boxed_slice_into_iter |
Rewrites boxed_slice.into_iter() calls in pre-2024 code to boxed_slice.iter() so their item type stays &T (since Box<[T]>::into_iter() now yields T by value in Rust 2024!). |
never_type_fallback_flowing_into_unsafe |
Adds explicit type annotations (::<()>) where !-to-() fallback changes affect type inference. |
Example Before and After cargo fix --edition
// BEFORE running `cargo fix --edition` (in a Rust 2021 crate):
//
// #[no_mangle]
// pub extern "C" fn gen(x: i32) -> i32 {
// let boxed: Box<[i32]> = Box::new([1, 2, 3]);
// boxed.into_iter().map(|&v| v + x).sum()
// }
// AFTER running `cargo fix --edition` (valid in BOTH Rust 2021 and Rust 2024!):
#[unsafe(no_mangle)]
pub extern "C" fn r#gen(x: i32) -> i32 {
let boxed: Box<[i32]> = Box::new([1, 2, 3]);
// In Rust 2024, `Box<[T]>` implements `IntoIterator` by VALUE (`Item = i32`)!
boxed.into_iter().map(|v| v + x).sum()
}
fn main() {
println!("Result of migrated function: {}", r#gen(10));
}
Result of migrated function: 36
Handling Feature-Gated and Platform-Specific Code During Migration
Because cargo fix --edition only rewrites code that rustc actually compiles during the invocation:
- Always pass
--all-targets --all-features(cargo fix --edition --all-targets --all-features) so unit tests, integration tests, examples, benchmarks, and optional feature blocks are all migrated. - If your crate has platform-specific modules (
#[cfg(windows)]vs#[cfg(unix)]), runcargo check --target <triple>(or rely on CI across Linux, macOS, and Windows) after switching toedition = "2024"to verify all platform branches.