Skip to content

Vendored cargo warns cargo_multi_version_old_cargo ("declares no rust-version") when the root package inherits rust-version from [workspace.package] #651

Description

[agent] Found by the scheduled Cargo bug-hunt routine (ledger #315).

Summary

When a second version of one crate is vendored, vendor decides whether to emit cargo_multi_version_old_cargo by reading the project's declared cargo floor (declared_cargo_minor). A workspace-root manifest whose [package] inherits the floor with rust-version.workspace = true (and [workspace.package] rust-version = "1.70") is treated as declaring nothing. The project gets the warning, and the warning says it "declares no rust-version or toolchain, so the cargo that builds it is unknown".

The cause: [package].rust-version is present but is a table ({ workspace = true }), not a string. .get("rust-version") returns Some(table), so the .or_else fallback to [workspace.package].rust-version never runs, and then .as_str() yields None.

Impact

Low severity. It's a false, misleading warning, not a broken build. The build is fine. Workspace inheritance needs cargo 1.64+, so any project using rust-version.workspace = true already can't be built by the pre-1.45 cargo the warning is about. Root packages that inherit from [workspace.package] are the standard modern workspace layout, so every multi-version vendor in such a project emits a spurious warning, which trains users to ignore it.

Repro

This used a scratch copy of crates/socket-patch-cli/tests/e2e_vendor_cargo_build.rs (stage_two_versions fixture: cfg-if 1.x plus cfg_if_old = { package = "cfg-if", version = "0.1" }, a marker patch per version, and the prebuilt_common artifact server). Only the root Cargo.toml was swapped, then I ran socket-patch vendor --json --offline:

[workspace]

[workspace.package]
rust-version = "1.70"

[package]
name = "consumer"
version = "0.1.0"
edition = "2018"
rust-version.workspace = true

[dependencies]
cfg-if = "1.0"
cfg_if_old = { package = "cfg-if", version = "0.1" }
root Cargo.toml shape cargo build --locked before vendor exit cargo_multi_version_old_cargo cargo run --locked --offline after
rust-version = "1.70" in [package] ok 0 no (correct) MARKER:1:2
rust-version.workspace = true + [workspace.package] rust-version = "1.70" ok 0 yes (wrong) MARKER:1:2
BOM + rust-version = "1.70" ok 0 no (correct) MARKER:1:2
no rust-version (control) ok 0 yes (correct) MARKER:1:2

I ran the scratch test twice with identical results. The warning text on the inherited shape:

cfg-if is now vendored at TWO versions (… beside …), which needs cargo 1.45 or newer — this project declares no rust-version or toolchain, so the cargo that builds it is unknown. …

Expected vs actual

  • Expected. CLI_CONTRACT.md (cargo vendored row) says "a project that does not pin cargo ≥ 1.45 (rust-version or toolchain file) gets the cargo_multi_version_old_cargo warning", and docs/ecosystems.md says the warning is skipped when "the project's rust-version … promises cargo 1.45+". The doc comment on declared_cargo_minor reads "[package], else [workspace.package]". This project does pin 1.70, through cargo's documented inheritance, so it should get no warning.
  • Actual. The warning fires and claims the project declares no rust-version.

OS × version

OS cargo result
Linux (sandbox) 1.93.1 fail (reproduced twice)
macOS / Windows — untested (pure manifest parsing, so no OS dependence is expected)

Main 045d7ec (CLI 4.0.0). I didn't bisect this: the multi-version warning was added with the v5 manifest wiring.

Suspect code

crates/socket-patch-core/src/vendor/cargo.rs:90-99 (declared_cargo_minor): doc.get("package").and_then(|p| p.get("rust-version")).or_else(...) short-circuits on the { workspace = true } table. Treat a non-string [package].rust-version (or rust-version.workspace = true) as "look in [workspace.package]". Optionally, treat any use of workspace inheritance as proof of cargo ≥ 1.64.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions