Stable Language Evolution

Minimum Supported Rust Version

A project's Minimum Supported Rust Version (MSRV) is the oldest stable Rust compiler release on which the crate promises to compile and pass its test suite. Establishing a clear MSRV policy—and verifying it automatically in Continuous Integration—helps downstream enterprise users, Linux distribution packagers, and long-term support (LTS) projects upgrade safely.

Common MSRV Policies in the Rust Ecosystem:

  1. Rolling Window Policy (e.g., "Latest Stable minus N releases"):
     - N = 4 releases (~6 months of support) or N = 8 releases (~1 year of support)
     - Bumping MSRV is treated as a Minor SemVer bump (`0.2.0 -> 0.3.0` or `1.4.0 -> 1.5.0`)

  2. Edition-Aligned Policy:
     - Tracks the baseline compiler of the current Rust Edition (e.g., `1.85.0` for Rust 2024)

  3. Latest Stable Policy (Typical for internal applications & leaf binaries):
     - Always tracks current stable via `rust-toolchain.toml`

Discovering and Verifying Your Crate's MSRV (cargo-msrv)

What if you aren't sure which minimum version of rustc your crate currently requires, or you want to verify that a pull request didn't accidentally call a brand-new standard library method stabilised after your declared rust-version?

  1. Automated binary search with cargo-msrv (cargo install cargo-msrv --locked): Performs a binary search across historical rustup toolchains to find the exact minimum rustc version that compiles your crate (cargo msrv find) or verifies your declared rust-version (cargo msrv verify).
  2. Clippy MSRV lint (clippy::incompatible_msrv): When rust-version is set in Cargo.toml (or msrv is set in clippy.toml), running cargo clippy on the latest compiler warns you immediately if you call any standard library function that was stabilized after your declared rust-version!
#![warn(clippy::incompatible_msrv)]

/// If `Cargo.toml` declares `rust-version = "1.85"`, Clippy checks every std call
/// against its `#[stable(since = "...")]` metadata even when you develop on a newer compiler!
pub fn parse_hex_u16(input: &str) -> Option<u16> {
    let stripped = input.strip_prefix("0x").unwrap_or(input);
    u16::from_str_radix(stripped, 16).ok()
}

fn main() {
    assert_eq!(parse_hex_u16("0x1a2b"), Some(0x1a2b));
    println!("Parsed hex u16 under MSRV check: {:#x}", parse_hex_u16("0x1a2b").unwrap());
}
Parsed hex u16 under MSRV check: 0x1a2b

Testing MSRV in Continuous Integration

In GitHub Actions, add a dedicated MSRV job that reads rust-version directly from Cargo.toml so it never drifts out of sync with your manifest:

  msrv:
    name: MSRV Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install MSRV toolchain from Cargo.toml
        uses: dtolnay/rust-toolchain@master
        with:
          # Or pin explicitly to match `rust-version` in Cargo.toml:
          toolchain: "1.85.0"
      - run: cargo check --workspace --all-targets --all-features