Major-open semver range does not properly unify with closed semver ranges
Problem
If a dependency's version is constrained to cover multiple semver-incompatible releases, the version selected does not unify with more specific restrictions from elsewhere in the build graph. E.g. a requirement for >=0.0.0, <0.9.0 and a requirement for ^0.4.0 results in both version 0.4.x and 0.8.y being pulled in (or 0.4.x and 0.1.0 with -Zminimal-versions), rather than unifying both versions to just 0.4.x.
Manually adjusting the lockfile to use 0.4.x in both cases works as expected; this is just an issue with the "find the best solution" codepath, not the "check the lockfile satisfies" codepath.
Originally reported by @MaximilianKoestler on URLO: https://users.rust-lang.org/t/crate-interoperability-and-3rd-party-types-in-interfaces/53431
Steps
Repro from @MaximilianKoestler : https://github.com/MaximilianKoestler/crate-version-testing
Using the rgb crate as our target, this is exemplified using just the three packages:
[package] name = "lib_a" [dependencies] rgb = ">=0.4.0, <0.5.0"
[package] name = "lib_b" [dependencies] rgb = ">=0.0.0, <0.9.0"
[package] name = "bin_c" [dependencies] lib_a = { path = "../lib_a" } lib_b = { path = "../lib_b" }
The generated lockfile:
# irrelevant parts removed and reordered [[package]] name = "lib_a" dependencies = [ "rgb 0.4.0", ] [[package]] name = "lib_b" dependencies = [ "rgb 0.8.25", ] [[package]] name = "bin_c" dependencies = [ "lib_a", "lib_b", ] [[package]] name = "rgb" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rgb" version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index"
Possible Solution(s)
Ideally, if all constraints overlap, only a single version should be selected. Otherwise, maintaining support for old semver-incompatible versions of public dependencies (when the subset you're using didn't change) is almost meaningless, as cargo won't unify the dependency off of the most recent semver-compatible range (or first with -Zminimal-versions).
Notes
Output of cargo version: cargo 1.50.0-nightly (75d5d8cff 2020-12-22) (also occurs on stable)