Provide a way to describe why newer versions are not selected
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 15.5k
- Forks
- 3k
- Avg merge
- 23h 30m
- Merged PRs (30d)
- 51
Description
Describe the problem you are trying to solve
Sometimes it can be confusing why newer versions of a package are not selected by the resolver. It would be nice to have some way for Cargo to tell you that there is a newer version available, but it is not able to select it due to some requirement.
There are different reasons this can happen. Some I can think of:
- Multiple version constraints of different styles. For example one package has "1.0.*", and another has "^1.0".
- Features were removed in an otherwise semver-compatible release. Packages probably shouldn't do that, but it can still be silently confusing. See #7167 for more details.
- Cargo fails to parse the newer version index entry.
- Newer version is yanked.
- New
linkscollision (I think?)
This is in spirit with #6199 and #5284, but this is not for errors but for when otherwise compatible versions are skipped.
Describe the solution you'd like
I'm not sure of the best way to convey this information. Maybe cargo update -v could include a detailed message? Or maybe make it part of CARGO_LOG? Or something else?
It could say something like:
info: a newer version of package `bar` is available,
but it is unable to be selected due to restricted requirements
`bar` 1.1.0 is available, but
`somedep`'s requirement `^1.0` selected older version `1.0.0` because
`restrictor` has the requirement `1.0.*` which prevents the newer version from being selected
Example
Some examples using Cargo's test notation:
#[cargo_test]
fn describe_restricted_dep() {
// Example showing a newer version not selected due to an unrelated
// package's over-restrictive requirements.
Package::new("dep", "1.0.0").publish();
Package::new("dep", "1.1.0").publish();
Package::new("restrictor", "1.0.0")
.dep("dep", "1.0.*")
.publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "1.0.0"
[dependencies]
restrictor = "1.0"
dep = "1.0"
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("update -v").with_stderr("[UPDATING] [..]").run();
}
#[cargo_test]
fn describe_misfeatured_dep() {
// Example showing a newer version not selected due to missing features.
Package::new("dep", "1.0.0").feature("f1", &[]).publish();
Package::new("dep", "1.0.1").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "1.0.0"
[dependencies]
dep = { version = "1.0", features = ["f1"] }
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("update -v").with_stderr("[UPDATING] [..]").run();
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the cargo update -v entry point and the existing describe_restricted_dep and describe_misfeatured_dep cargo_test cases. Trace how dependency resolution reports updates and skipped versions, then determine a user-facing diagnostic design that covers the examples in the issue. Done means the selected output explains why an available newer version was not chosen, with tests covering the described scenarios.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 28/100