Repository navigation
fix(rust): correct the declared MSRV to 1.96 and enforce it in CI - #987
Merged
Merged
Conversation
The workspace declared rust-version = "1.87", set once when the Rust workspace was added (0ddf611, June 2026) and never revisited. crates.io publishes that field verbatim, so the jscpd crate page advertised a floor the crate cannot actually build on: $ cargo +1.93 check -p jscpd error: rustc 1.93.1 is not supported by the following packages: oxc_allocator@0.147.0 requires rustc 1.96.0 ... The real floor is 1.96.0, forced by the 13 oxc_* crates that reach the published crate through the mandatory oxc_parser -> cpd-tokenizer -> jscpd chain. ignore, globset and askama independently require 1.88. The number was probably accurate at the time — oxc was pinned to 0.133 then — and drifted silently as oxc raised its own MSRV across later bumps. Nothing caught the drift because every workflow pins the toolchain to 1.97.1, so no job ever built at the declared MSRV. This adds an `msrv` job that reads rust-version straight out of Cargo.toml and runs cargo check against exactly that toolchain, so the next oxc bump fails loudly instead of quietly falsifying published metadata. The check uses `cargo +<version>` rather than relying on the toolchain installed by the action: rust-toolchain.toml pins 1.97.1 for development and would otherwise take precedence, making the job test the wrong compiler. rust/README.md claimed 1.87+ and pointed at rust-toolchain.toml, which actually pins 1.97.1 — the two never agreed. It now states the MSRV and explains what the pin is for. Verified: cargo +1.96 check --workspace --all-targets --locked passes, so 1.96 is achievable including dev-dependencies.
Raising rust-version to 1.96 turned on 11 clippy::collapsible_if errors across four crates, failing the Clippy step with -D warnings. The lint is MSRV-gated: its suggested fix is a let-chain, stabilised in Rust 1.88, so clippy stayed silent while the workspace claimed 1.87. The violations were always there — the wrong MSRV was suppressing them. Applied with `cargo clippy --fix` (machine-applicable suggestions only), then `cargo fmt` to repair the indentation the fixer leaves behind. Every site is a plain nested if with no else branch, so each collapse is a pure rewrite with no change in control flow. cpd-tokenizer javascript.rs, razor.rs, sfc.rs, ts_strip.rs (1 each) cpd-finder walker.rs (5) cpd-reporter sarif.rs (2) jscpd main.rs (3) Verified: clippy --workspace -- -D warnings clean, cargo fmt --check clean, 847 tests pass, and cargo +1.96 check --workspace --all-targets --locked still passes (let-chains predate the MSRV by eight releases).
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.
The problem
The crates.io page for
jscpdadvertises Rust 1.87 as the minimum supported version. The crate cannot build on it:crates.io renders
[workspace.package] rust-versionverbatim, so anyone trusting the badge and installing 1.87 hits a hard resolution error rather than a build.Why it's wrong
The real floor is 1.96.0. These are not optional or dev-only deps —
oxc_parser→cpd-tokenizer→jscpdis a mandatory chain:oxc_*0.147.0cpd-tokenizer→jscpdignore,globsetcpd-finder→jscpdaskama0.16 + macroscpd-reporter→jscpdgit log -L 13,13:rust/Cargo.tomlshows one commit ever touched the line —0ddf611(2026-06-04), when the Rust workspace was added. It was likely accurate then (oxc was pinned to0.133) and drifted as oxc raised its own MSRV across later bumps.Why nothing caught it
Every workflow pins the toolchain to
1.97.1—rust.yml:29,release.yml:130,crates-publish.yml:77,npm-rust-publish.yml:151. No job has ever built at the declared MSRV, so the field was free to rot.Changes
rust/Cargo.toml—rust-version1.87 → 1.96..github/workflows/rust.yml— newmsrvjob. It readsrust-versionstraight out ofCargo.tomlrather than hardcoding it, so the workflow can't drift out of sync with the manifest, then runscargo check --workspace --all-targets --lockedagainst exactly that toolchain.rust/README.md— said "Requires Rust 1.87+ (seerust-toolchain.toml)", but that file pins1.97.1; the two never agreed. Now states the MSRV and explains what the pin is for.The job invokes
cargo +<version>explicitly instead of relying on the toolchain the action installs —rust-toolchain.tomlpins 1.97.1 for development and would otherwise take precedence, silently testing the wrong compiler.Verification
Passes with
--all-targets, so 1.96 is achievable including dev-dependencies.--lockedconfirms it holds against the committed lockfile.Metadata and CI only — no source or behaviour changes.
This change is