ci(msrv): enforce the declared rust-version = "1.86" - #302
Merged
Merged
Conversation
Cargo.toml declares `rust-version = "1.86"` and CONTRIBUTING.md states it as the contract for contributors, but the workflow only ever installed `stable` (1.98 today) — so the declaration had no enforcer at all. This repo has already felt the consequences: clippy suggests APIs that are newer than the declared MSRV (e.g. `unsigned_is_multiple_of`, stable only since 1.87), and every such suggestion is green on stable. Add a `msrv` job that installs the toolchain the manifest declares and builds with `--locked` against the committed Cargo.lock. A second step asserts that the installed rustc really is the declared version, so bumping `rust-version` without bumping this job fails loudly instead of silently re-creating the gap. No production code changes; the existing `ci` job is untouched.
This was referenced Sep 26, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
.github/workflows/ci.ymlinstalleddtolnay/rust-toolchain@stableand nothing else, whileCargo.toml:8declaresrust-version = "1.86"andCONTRIBUTING.md:7states that declaration as the contract for contributors. Nothing in the repository ever checked it, so the declaration had no enforcer: every build and every test ran on the newest stable (1.98.0 today).That is not hypothetical here.
cargo clippy --all-targets -- -D warningsis a required check, and clippy's lints propose APIs that are newer than the declared MSRV. Measured on this tree: a build containingn.is_multiple_of(2)(unsigned_is_multiple_of, stable only since 1.87, rust-lang/rust#128101) is green on stable and red on 1.86 — a clippy-suggested fix can push production code past the line the manifest declares, and CI still passes.This PR gives the declaration its first enforcer: a
msrvjob that installs the version the manifest declares and builds the crate with that toolchain.Related Issue
None: no open issue covers this, and it is a self-contained change to one workflow file. (Recorded so the reviewer knows why no issue is linked and the linked-issue field stays empty.)
Changes
.github/workflows/ci.yml— newmsrvjob (a separate job, so it runs in parallel withciand reports its own status check):dtolnay/rust-toolchain@1.86, then runscargo build --locked;--lockedpins the committedCargo.lock: without it, a runner whose lockfile no longer matchesCargo.tomlre-resolves in place and still builds, while the committed lockfile stays broken;rustcreally is therust-versioninCargo.toml— bumping the declaration without bumping this job then fails loudly instead of silently re-creating the same gap.cijob is untouched.Tests
cargo testall pass — 396 passed / 0 failed (unchanged; this PR adds no Rust code).cargo fmt --checkpasses (rc 0).cargo clippy --all-targets -- -D warningspasses (rc 0).The declared MSRV is true on this tree (measured, not assumed)
With 1.86.0 actually installed:
and the two steps the new job runs:
The new job has teeth
A/B in the same clone, with a temporary mutation of
src/main.rsthat uses<u32>::is_multiple_of(reverted afterwards; final tree is the single commit below):cargo build --lockedmsrverror[E0658]: use of unstable library feature 'unsigned_is_multiple_of'ciFinishedThe existing check is blind to exactly this class of regression; the new one is not.
The locked dependency graph is MSRV-safe
cargo metadata --lockedlists 294 packages, 218 of which declarerust-version. Exactly one exceeds 1.86:wasip2 1.0.4+wasi-0.2.12(declares 1.87.0). Its only inbound edge is target-gated —getrandom 0.3.4,cfg(all(target_arch = "wasm32", target_os = "wasi", target_env = "p2"))— so it is never built in this job.Cargo.tomlhas no[target.'cfg(...)'.dependencies]sections, and the versions are pinned by the committed lockfile, so the Linux runner builds the same graph that was measured here.The action ref is valid
dtolnay/rust-toolchainpublishes one branch per Rust version (stable,beta,nightlyare branches too); the repository has exactly one tag,v1.Scope
This job builds production code, which is what
rust-versionpromises downstream.cargo testalso passes on 1.86 (396/0 above), so extending the job to--all-targetsis a one-line change if you would rather cover test code too — say the word and I'll send it.Checklist
ci/, matching the existingci(docker):commit in this repo)