Rust 2024 Edition

Edition Compatibility

Edition compatibility guarantees that crates compiled with different Rust editions (2015, 2018, 2021, and 2024) can interoperate seamlessly within the same dependency graph, workspace, and final binary—including calling functions, implementing traits, and expanding macros across edition boundaries.

Workspace with Mixed-Edition Crates:
  ├── `legacy_parser` (`edition = "2018"`)
  ├── `core_engine`   (`edition = "2021"`)
  └── `api_server`    (`edition = "2024"`)
        |
        +--> Imports `legacy_parser` & `core_engine` with ZERO wrappers or glue!

How Cross-Edition Interoperability Works

  1. Types and Traits Are Edition-Agnostic: A struct, enum, or trait compiled in a Rust 2015 or 2021 crate is indistinguishable in HIR/MIR from one compiled in a Rust 2024 crate.
  2. Independent Per-Crate Upgrades: You never have to wait for your dependencies (or your downstream dependents) to upgrade to edition = "2024" before upgrading your own crate!
  3. Edition vs rust-version (MSRV): The only requirement for compiling a crate with edition = "2024" is that the compiler version is at least rustc 1.85.0 (the release that stabilized the 2024 edition).

Writing Edition-Hygienic Declarative Macros (macro_rules!)

There is one subtle place where two editions meet inside the same compilation unit: when a declarative macro (macro_rules!) defined in a Crate of Edition X is expanded inside a caller Crate of Edition Y!

When rustc parses a macro_rules! definition:

  • Tokens written literally inside the macro body are parsed and checked using the defining crate's edition (Edition X).
  • Tokens passed as macro arguments ($expr, $pat, $ident) by the caller are parsed using the calling crate's edition (Edition Y).

To ensure exported #[macro_export] macros work cleanly for callers on any edition:

  1. Prefix standard library paths inside macros with $crate or ::core:: / ::std:: instead of relying on edition-specific prelude items.
  2. In Rust 2024, notice that the expr macro fragment specifier ($e:expr) was updated to also match const { ... } blocks and _ expressions; if a macro must preserve the exact Rust 2021 expr matching rules, Rust 2024 provides the $e:expr_2021 fragment specifier!
Macro Fragment Specifier in Rust 2024 Matches Standard Expressions? Matches const { ... } Blocks & _ Expressions?
$x:expr (2024 Default) Yes Yes
$x:expr_2021 (Compatibility) Yes No (Preserves exact pre-2024 :expr behavior)
/// An edition-hygienic exported macro using fully qualified `::core::` paths
/// and supporting Rust 2024 `const { ... }` expressions via `:expr`!
#[macro_export]
macro_rules! check_non_zero {
    ($val:expr) => {{
        let v = $val;
        if v == 0 {
            ::core::option::Option::None
        } else {
            ::core::option::Option::Some(v)
        }
    }};
}

fn main() {
    // Pass a Rust 2024 inline `const { ... }` block directly into `$val:expr`!
    let result = check_non_zero!(const { 6 * 7 });
    assert_eq!(result, Some(42));
    assert_eq!(check_non_zero!(0), None);

    println!("Edition-hygienic macro with const block: {result:?}");
}
Edition-hygienic macro with const block: Some(42)