Skip to content

Provide a way to describe why newer versions are not selected #7929

@ehuss

Description

@ehuss

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 cargo update should print warnings for incompatible candidates #7167 for more details.
  • Cargo fails to parse the newer version index entry.
  • Newer version is yanked.
  • New links collision (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();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-dependency-resolutionArea: dependency resolution and the resolverC-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`S-needs-designStatus: Needs someone to work further on the design for the feature or fix. NOT YET accepted.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions