The gap
spar has an MSRV. Nothing in the repo states it, and nothing checks it.
[workspace.package] in the root Cargo.toml declares no rust-version.
- There is no
rust-toolchain.toml.
So the effective floor is not a repo property at all. It is
max(rust-version) over the entire RESOLVED DEPENDENCY CLOSURE
— an emergent property of Cargo.lock. It moves on every cargo update, with
no diff anywhere in this repo, and it is discovered at build time by whichever
consumer happens to have the oldest toolchain.
Re-derive it, never retype it:
cargo metadata --format-version 1 --locked \
| jq -r '.packages[] | select(.rust_version) | .rust_version' \
| sort -V | tail -1
Measured today: 152 of 235 packages declare rust-version. The max is
1.89 (smol_str@0.3.6); the next tier is 1.87.0 (wit-bindgen, wasip2).
A single transitive bump of smol_str moves the number with nothing in this
repo changing.
This already caused a defect, which is why it's worth a gate
In #364 the tools/fixture-vm nixpkgs pin was moved 24.05 → 25.05 and recorded
in the flake as "✓ cannot compile → can compile." That was false, and I
wrote it.
The reasoning was: edition 2024 needs rustc ≥ 1.85, 25.05 ships 1.86.0, 1.86 ≥
1.85, done. Every step is true. The conclusion is still wrong, because the
edition floor is a necessary condition that got mistaken for the
condition. Cargo said so one CI dispatch later:
error: rustc 1.86.0 is not supported by the following package:
smol_str@0.3.6 requires rustc 1.89
The failure mode worth naming: the probe genuinely ran and genuinely returned
a true value. rustc.version = 1.86.0 was real, and it cleared the bound it
was compared against. A one-variable check that comes back true is the most
convincing way to not verify something — it produces the feeling of
verification while silently scoping the claim to the one variable you thought of.
Why nothing catches it
| surface |
catches a raised closure floor? |
cargo build in CI |
No — runners use current stable, always above the floor |
rivet validate |
No — not a Rust concern |
Cargo.toml diff review |
No — the floor isn't written anywhere |
tools/fixture-vm nightly |
Only here, and only as a build-time error inside a nix derivation |
That last row is the whole problem: the sole detector is a nightly that was
itself red for 60 consecutive runs (#362), so the detector was dark for two
months. And it fails at build time, not evaluation time, so it survives every
local check the flake permits.
Two honest options
A. Declare rust-version in [workspace.package].
Cheap, one line, makes the floor a reviewable repo fact. Cargo then enforces it
for consumers. Downside: it is a declaration, so it can itself go stale
relative to the closure — it would need the check below anyway to stay honest.
B. A CI check comparing the flake channel's rustc against the closure max.
Directly gates the thing that actually broke:
CLOSURE=$(cargo metadata --format-version 1 --locked \
| jq -r '.packages[]|select(.rust_version)|.rust_version' | sort -V | tail -1)
CHANNEL=$(nix eval --raw \
github:NixOS/nixpkgs/<channel>#legacyPackages.x86_64-linux.rustc.version)
# fail if CHANNEL < CLOSURE
Catches the drift on the PR that introduces it rather than on a nightly two
months later. Costs a nix evaluation in CI.
A and B are complementary, not alternatives — A makes the floor visible, B
keeps it true. Recommend both, B first, since B is what would actually have
caught the #364 defect.
Verifying whatever lands
Two-sidedly, or it's decorative:
- Positive: current
Cargo.lock + nixos-25.11 (rustc 1.91.1) → must pass.
- Negative: same lock pinned against
nixos-25.05 (rustc 1.86.0) → must fail
and name smol_str@0.3.6. If the negative case passes, the check cannot
fire and is worse than nothing, because it reads as coverage.
Scope
CI plumbing + one Cargo.toml line. No rivet artifact, matching the
#353 / #363 / #364 / #366 precedent — this repo carries no REQ-CI-* ids.
Flagged so the omission reads as a choice rather than an oversight.
Suggested for v0.36.0 alongside #358 and #366.
The gap
spar has an MSRV. Nothing in the repo states it, and nothing checks it.
[workspace.package]in the rootCargo.tomldeclares norust-version.rust-toolchain.toml.So the effective floor is not a repo property at all. It is
— an emergent property of
Cargo.lock. It moves on everycargo update, withno diff anywhere in this repo, and it is discovered at build time by whichever
consumer happens to have the oldest toolchain.
Re-derive it, never retype it:
Measured today: 152 of 235 packages declare
rust-version. The max is1.89 (
smol_str@0.3.6); the next tier is1.87.0(wit-bindgen,wasip2).A single transitive bump of
smol_strmoves the number with nothing in thisrepo changing.
This already caused a defect, which is why it's worth a gate
In #364 the
tools/fixture-vmnixpkgs pin was moved 24.05 → 25.05 and recordedin the flake as "✓ cannot compile → can compile." That was false, and I
wrote it.
The reasoning was: edition 2024 needs rustc ≥ 1.85, 25.05 ships 1.86.0, 1.86 ≥
1.85, done. Every step is true. The conclusion is still wrong, because the
edition floor is a necessary condition that got mistaken for the
condition. Cargo said so one CI dispatch later:
The failure mode worth naming: the probe genuinely ran and genuinely returned
a true value.
rustc.version = 1.86.0was real, and it cleared the bound itwas compared against. A one-variable check that comes back true is the most
convincing way to not verify something — it produces the feeling of
verification while silently scoping the claim to the one variable you thought of.
Why nothing catches it
cargo buildin CIrivet validateCargo.tomldiff reviewtools/fixture-vmnightlyThat last row is the whole problem: the sole detector is a nightly that was
itself red for 60 consecutive runs (#362), so the detector was dark for two
months. And it fails at build time, not evaluation time, so it survives every
local check the flake permits.
Two honest options
A. Declare
rust-versionin[workspace.package].Cheap, one line, makes the floor a reviewable repo fact. Cargo then enforces it
for consumers. Downside: it is a declaration, so it can itself go stale
relative to the closure — it would need the check below anyway to stay honest.
B. A CI check comparing the flake channel's rustc against the closure max.
Directly gates the thing that actually broke:
Catches the drift on the PR that introduces it rather than on a nightly two
months later. Costs a nix evaluation in CI.
A and B are complementary, not alternatives — A makes the floor visible, B
keeps it true. Recommend both, B first, since B is what would actually have
caught the #364 defect.
Verifying whatever lands
Two-sidedly, or it's decorative:
Cargo.lock+nixos-25.11(rustc 1.91.1) → must pass.nixos-25.05(rustc 1.86.0) → must failand name
smol_str@0.3.6. If the negative case passes, the check cannotfire and is worse than nothing, because it reads as coverage.
Scope
CI plumbing + one
Cargo.tomlline. No rivet artifact, matching the#353 / #363 / #364 / #366 precedent — this repo carries no
REQ-CI-*ids.Flagged so the omission reads as a choice rather than an oversight.
Suggested for v0.36.0 alongside #358 and #366.