Rust 2024 Edition

Edition System

The Rust Edition system is an opt-in, per-crate versioning mechanism (edition = "2015" | "2018" | "2021" | "2024" in Cargo.toml) that allows the Rust language, standard library prelude, Cargo dependency resolver, and rustfmt style rules to make backward-incompatible syntax and ergonomic improvements every three years without ever splitting the crate ecosystem.

+-------------------------------------------------------------------+
|                   Rust Compiler (`rustc 1.85+`)                   |
|                                                                   |
|   Crate A (`edition = "2015"`) ---+                                |
|   Crate B (`edition = "2018"`) ---+--> Lowered to Unified HIR/MIR! |
|   Crate C (`edition = "2021"`) ---+    Linked into ONE Binary!     |
|   Crate D (`edition = "2024"`) ---+                                |
+-------------------------------------------------------------------+

How the Edition System Prevents Ecosystem Splits

Unlike Python 2 vs Python 3 (where a Python 3 application could not directly import a Python 2 library), Rust editions exist only at the surface parsing, macro, prelude, and lint levels of each individual crate:

  1. Once rustc parses a crate's source files according to its declared edition and lowers them into High-level and Mid-level Intermediate Representations (HIR/MIR), all editions are identical inside the compiler.
  2. A Rust 2024 binary crate can depend on a Rust 2015, 2018, or 2021 library crate—and vice versa—with zero friction.
  3. Most new Rust features (such as new standard library APIs, const generics, or async traits) are released on all editions simultaneously in regular 6-week compiler releases. Editions are reserved exclusively for changes that would break existing code if enabled silently (such as reserving a new keyword like gen, changing lifetime capture defaults, or promoting warnings to errors).

Evolution of Rust Editions (2015 to 2024)

Edition Stabilized In Key Milestones Introduced
2015 rustc 1.0 (2015) Initial stable release; default edition if edition key is omitted from Cargo.toml.
2018 rustc 1.31 (2018) Reserved async/await keywords, simplified module system (no extern crate), Non-Lexical Lifetimes (NLL), dyn Trait syntax.
2021 rustc 1.56 (2021) Disjoint closure field capture, IntoIterator for [T; N] arrays by value, TryFrom/TryInto/FromIterator in prelude, Cargo Resolver v2.
2024 rustc 1.85 (2025) RPIT lifetime capture of all in-scope lifetimes + use<..> syntax, unsafe extern blocks, #[unsafe(no_mangle)], unsafe fn set_var, reserved gen keyword, Future/IntoFuture in prelude, Temporary Lifetime Extension refinements, Cargo MSRV-aware Resolver v3, merged doc-test binaries.

Selecting an Edition in Cargo.toml and rustc

[package]
name = "modern_service"
version = "0.1.0"
edition = "2024"

When invoking rustc directly without Cargo, pass --edition=2024:

// Future and IntoFuture are included directly in the Rust 2024 prelude
// without requiring `use std::future::{Future, IntoFuture};`!
fn accepts_future<F: Future<Output = u32>>(fut: F) -> F {
    fut
}

fn main() {
    let _f = accepts_future(async { 42 });
    println!("Compiled with Rust 2024 prelude (`Future` in scope automatically)");
}
Compiled with Rust 2024 prelude (`Future` in scope automatically)