Repository navigation
Description
Follow-ups found while reviewing #2012 (the folded Cargo VEX stack). All three predate #2012 or are remedy text. None of them blocks it.
1. False attestation: an ignored [patch] Socket pin as a transitive crate's only wiring (also on main)
hosted_from_lock (vex/discover/cargo.rs) keeps the Cargo.lock ref whenever any declaration names the lock's socket-patch-<uuid> registry: regs.iter().any(|d| d.registry == reg). It doesn't check d.live. Cargo can ignore a root [patch.crates-io] serde = { registry = "socket-patch-<U>" } entry in two ways:
- a
[patch."https://github.com/rust-lang/crates.io-index"]table replaces[patch.crates-io]; - a project-config
[patch]item redefines the key.
If that ignored entry is the only wiring of a transitive crate, the ref is still attested. Cargo actually re-resolves serde from crates.io.
Reproduced on #2012's head (f1eb764), with a root manifest carrying that [patch.crates-io] pin and a crates.io-URL [patch] table, and a Socket-sourced serde 1.0.1 in the lock:
- refs:
[(pkg:cargo/serde@1.0.1, U, Hosted)] - unattested:
[] - diagnostics:
[patched_ref_invalid]("cargo ignores that[patch]entry")
The discovery diagnoses the entry as ignored and still attests the ref.
main has the same gate (regs.iter().any(|r| r.as_deref() == Some(reg))) and no [patch] precedence model at all, so it attests this shape too. #2012 didn't introduce it. The fix probably belongs in hosted_from_lock: count only live declarations for the "names this patch's registry" gate, and treat a ref whose only wiring is a dead [patch] pin like a reverted pin (patched_ref_invalid, no ref).
2. Remedy text: ambiguous cargo update -p / cargo tree -i beside the tagged vendored copy
When vex_cargo_patch_bypassed fires on a same-version lock entry, the detail suggests cargo update -p <crate> and cargo tree -i <crate>@<version>. The lock also holds the vendored copy at <version>+socket.<uuid>, and cargo ignores build metadata when matching a package spec. So both commands fail with "specification … is ambiguous". The remedy should print a source-qualified spec, for example registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4, or the git/registry source of the offending entry.
3. Remedy text: a stale entry from another registry gets no re-lock advice
The stale-entry check maps a lock source to a DeclSource only for crates.io and git (DeclSource::of_lock_source). Take a copy wired under [patch."https://my-corp.example/index"] (or [patch.my-corp]) with a stale registry+https://my-corp.example/index entry at the patched version. It isn't recognized as stale, so the user is sent to cargo tree -i to look for a declaring dependency that may not exist. Mapping registry+ / sparse+ sources to DeclSource::RegistryIndex(url) would reuse patched_by.
Checked and not an issue: sparse index URLs. #2012 compares sparse+ URLs with one trailing / ignored, and so does cargo. CanonicalUrl::new (src/util/canonical_url.rs) strips a trailing slash for every URL, and skips only the GitHub lower-casing and .git stripping for schemes containing +.
Activity