DEV Community

Cover image for Your Crate's MSRV Is Probably Wrong (And You Won't Know Until Someone's Build Breaks)
Dev Encyclopedia
Dev Encyclopedia

Posted on • Originally published at devencyclopedia.com

Your Crate's MSRV Is Probably Wrong (And You Won't Know Until Someone's Build Breaks)

Here's a scenario that plays out constantly in Rust projects: your Cargo.toml declares rust-version = "1.70", your CI is green, your tests pass. Then a contributor on an older pinned toolchain opens an issue because their build fails on a syntax error you've never seen.

Somewhere between when you set that rust-version and now, a PR quietly introduced a feature that needs something newer. Maybe it was a let-else statement. Maybe someone swapped in OnceLock instead of the once_cell crate. Nothing failed locally because your own toolchain is newer than what you claim to support.

The tricky part is that Rust features fall into different categories with very different implications. Syntax changes like let-else won't parse at all on an older compiler, full stop. Standard library additions like Option::is_some_and often have a crate-based equivalent you can swap in. Trait system changes like generic associated types or native async fn in traits are usually the hardest to walk back since they change what the compiler can express.

I built a small browser tool that pattern-matches pasted Rust source or a Cargo.toml against a feature lookup table spanning Rust 1.60 through 1.82, and reports the newest feature it finds, since that's your actual floor. It also cross-checks a declared rust-version against what it detects and flags the mismatch.

It's a heuristic, not a compiler, so it won't replace cargo-msrv for a final release check. But for eyeballing a PR or a new dependency before you commit real time to it, it's instant. I walk through how it handles trait blocks and the async-trait macro distinction here:
https://devencyclopedia.com/tools/msrvcheck

Top comments (0)