Dev Encyclopedia
ArticlesToolsContactAbout

Get notified when new content drops

No spam. Just new articles, tools, and updates straight to your inbox.

Dev Encyclopedia

A reference for builders

Dev.to
Discord
WhatsApp Channel
daily.dev
Hashnode
X

Content

  • Articles
  • Tools
  • About
  • Contact

Connect

  • support@devencyclopedia.com
  • RSS Feed

Legal

  • Privacy Policy
  • Terms of Service
  • Disclaimer

© 2026 Dev Encyclopedia

Back to top ↑
  1. Home
  2. /
  3. Tools
  4. /
  5. MSRVCheck
Free · Private · No toolchains

What Rust version does this code actually need?

Paste your source. Get an instant estimate of the minimum Rust version required, each contributing feature listed, no rustup toolchain installs, no compile time.

Zeeshan Tofiq

Zeeshan Tofiq

Full Stack Developer

How MSRVCheck works

  1. 1

    Paste a Rust file or Cargo.toml

    Drop in a .rs file, a snippet, or a whole Cargo.toml. Nothing is uploaded: parsing happens in your browser tab.

  2. 2

    Comments and string literals are stripped

    MSRVCheck sanitizes the source first, so a feature name mentioned in a comment or a test fixture string doesn't produce a false match.

  3. 3

    Trait and impl blocks are extracted

    For features that only matter inside a trait or impl (generic associated types, native async fn in traits, return-position impl Trait), MSRVCheck locates those blocks by brace-matching before checking inside them.

  4. 4

    Each block and the rest of the source are pattern-matched

    Every entry in the feature lookup table (let-else, OnceLock, is_some_and, and about 20 others) is checked against the sanitized source.

  5. 5

    The newest matched feature sets the estimate

    If your code uses a Rust 1.65 feature and a Rust 1.76 feature, the estimate is 1.76: code can only run on a toolchain new enough for its newest requirement.

  6. 6

    Cargo.toml fields are cross-checked

    If you pasted a manifest with a declared rust-version, MSRVCheck compares it against what it detected and flags it if your code has quietly outgrown your stated minimum.

What each detected category means

Every feature MSRVCheck flags falls into one of three categories. Knowing which one matters, since syntax features are unavoidable (the code won't parse at all on an older toolchain), while standard library features can sometimes be swapped for a crate that backports the same API.

Syntax

A change to the language grammar itself, like let-else or the #[default] attribute on an enum variant. There is no workaround: code using this syntax will not parse on an older compiler, period.

let Ok(n) = input.trim().parse::<u32>() else {
    return Err("not a number".into());
};
Standard library

A new type or method added to std, like OnceLock or Option::is_some_and. Often has a crate-based equivalent (once_cell, itertools) that works on older toolchains, so this category is the easiest to fix if you need to lower your MSRV.

use std::sync::OnceLock;

static CONFIG: OnceLock<Config> = OnceLock::new();
Trait system

A change to how traits work, like generic associated types, native async fn in traits, or return-position impl Trait in traits. Usually the hardest to replace: these change what the compiler can express, not just what's in std.

trait Repository {
    type Item<'a> where Self: 'a;
    async fn find(&self, id: u64) -> Option<Self::Item<'_>>;
}

Full feature lookup table

Every feature MSRVCheck currently checks for, oldest to newest. This is the same table the tool matches your code against.

VersionFeatureCategory
1.60.0integer .abs_diff()Standard library
1.62.0#[default] on an enum variantSyntax
1.63.0array::from_fnStandard library
1.65.0let-else statementsSyntax
1.65.0Generic associated types (GATs)Trait system
1.70.0std::sync::OnceLockStandard library
1.70.0std::cell::OnceCellStandard library
1.70.0std::io::IsTerminalStandard library
1.70.0Option::is_some_andStandard library
1.70.0Result::is_ok_andStandard library
1.73.0integer .div_ceil()Standard library
1.74.0io::Error::otherStandard library
1.75.0Native async fn in traitsTrait system
1.75.0Return-position impl Trait in traits (RPITIT)Trait system
1.76.0Result::inspect_errStandard library
1.76.0ptr::from_ref / ptr::from_mutStandard library
1.80.0std::sync::LazyLockStandard library
1.80.0std::cell::LazyCellStandard library
1.81.0#[expect(lint)] attributeSyntax
1.82.0Option::is_none_orStandard library

Recent Rust release dates

Rust ships a new stable release every six weeks. Useful for checking how old a pinned toolchain actually is.

VersionRelease date
1.85.02025-02-20
1.84.02025-01-09
1.83.02024-11-28
1.82.02024-10-17
1.81.02024-09-05
1.80.02024-07-25
1.79.02024-06-13
1.78.02024-05-02
1.77.02024-03-21
1.76.02024-02-08
1.75.02023-12-28
1.74.02023-11-16
1.73.02023-10-05
1.72.02023-08-24
1.71.02023-07-13
1.70.02023-06-01
1.69.02023-04-20
1.68.02023-03-09
1.67.02023-01-26
1.66.02022-12-15
1.65.02022-11-03
1.64.02022-09-22
1.63.02022-08-11
1.62.02022-06-30
1.61.02022-05-19
1.60.02022-04-07

When to use MSRVCheck

SituationWhat to paste
Reviewing a contributor's PRThe changed .rs files
Evaluating a new dependency before adding itIts main lib.rs or a representative module
Sanity-checking your own MSRV claimYour Cargo.toml plus recently-changed files
Copying a snippet from a blog post or Stack OverflowThe snippet itself
Learning when a specific syntax stabilizedA single line using that syntax
Finalizing an MSRV before publishing a releaseNothing, use cargo-msrv instead for the real check

Frequently Asked Questions

What does MSRVCheck do?

MSRVCheck scans pasted Rust source (or a Cargo.toml) against a lookup table of language and standard library features, and reports the newest one it finds. That's the estimated minimum Rust version the code needs, since using even one feature from Rust 1.75 means the code can't compile on a toolchain older than 1.75.

It runs entirely in your browser using regex pattern matching. There's no compilation, no toolchain installation, and no server involved.

How is MSRVCheck different from cargo-msrv?
MSRVCheckcargo-msrv
SetupNone, paste and goInstall cargo-msrv + rustup toolchains
MethodPattern match against a feature tableActually compiles against a range of toolchains
SpeedInstantMinutes, per toolchain tested
AccuracyHeuristic estimate, lower bound onlyAuthoritative, verified by real compilation
Best forQuick sanity check on a PR or dependencyFinalizing the MSRV for a release

ℹ Not a replacement

cargo-msrv remains the right tool before you commit to an MSRV in a crate's Cargo.toml. MSRVCheck is for the much more common case of eyeballing whether a diff crept past your team's pinned toolchain.

How accurate is the estimate?

It's a lower bound based on known syntax and API patterns, not a guarantee. If MSRVCheck finds a let-else statement, the code needs at least Rust 1.65, full stop, since that syntax didn't parse before then.

What it can't tell you is whether the code compiles cleanly on that version for other reasons: a dependency with its own higher MSRV, a compiler bug fix the code silently relies on, or a feature outside the lookup table entirely. Treat the result as a floor, not a certified MSRV.

Does MSRVCheck send my code anywhere?

No. All scanning happens in JavaScript inside your browser tab. Nothing you paste is sent to a server, logged, or stored. You can even disconnect from the internet after the page loads and MSRVCheck keeps working.

Can I check a Cargo.toml instead of source code?

Yes. Paste the whole Cargo.toml and MSRVCheck reads its edition and rust-version fields directly:

toml
[package]
name = "my-crate"
edition = "2021"
rust-version = "1.70"

edition = "2021" maps to a minimum of Rust 1.56, and edition = "2024" maps to Rust 1.85. If a rust-version field is present, MSRVCheck compares it against whatever it detects in your source and flags a mismatch if your code actually needs more than what you declared.

Why doesn't it flag async fn inside a trait using the async-trait crate?

Native async fn in a trait (stabilized in Rust 1.75) and the #[async_trait] macro from the async-trait crate look similar but have very different MSRVs. The macro rewrites your trait at compile time into something that works on any edition-2018+ toolchain.

MSRVCheck checks for an #[async_trait] attribute directly above the trait or impl block, and skips the async-fn-in-trait rule when it finds one, so a crate using the macro for broad compatibility doesn't get flagged with a Rust 1.75 requirement it doesn't actually have.

💡 Tip

Deciding between native async fn in traits and the async-trait crate? See our guide on Rust async traits and object safety linked below.

Can I check a whole crate or multiple files at once?

Not yet. MSRVCheck's MVP handles one pasted file at a time (source or manifest). For a full crate, run it over your highest-risk files individually, typically wherever a contributor's PR touched trait definitions or added a new dependency, or use cargo-msrv for a whole-crate authoritative check.

Related reading

Guide

Rust Async Traits Still Aren't Object-Safe: The Real Fixes

The three real workarounds for async fn in traits, including why the async-trait crate has a very different MSRV than native async fn in traits.

Guide

GitHub Actions Security: 7 Misconfigurations to Avoid

If your CI pins a specific Rust toolchain for stability, an unpinned or outdated action is often the bigger risk sitting right next to it.

Zeeshan Tofiq

Zeeshan Tofiq

Full Stack Developer

Full stack developer with over 6 years of experience building production applications. Writes practical guides on JavaScript, TypeScript, React, Node.js, and cloud infrastructure. Focused on helping developers solve real problems with clean, maintainable code.

Enjoyed this article?

Get practical dev guides, tool updates, and new articles delivered straight to your inbox. No spam, unsubscribe anytime.