Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cargo update -p $some_dependency causes unexpected dependency downgrades #14456

Closed
eric-seppanen opened this issue Aug 26, 2024 · 1 comment
Closed
Labels
C-bug Category: bug Command-update S-triage Status: This issue is waiting on initial triage.

Comments

@eric-seppanen
Copy link

eric-seppanen commented Aug 26, 2024

Problem

When I run cargo update -p $SOME_DEPENDENCY I sometimes notice unexpected changes in Cargo.lock for unexpected packages, specifically some crates depend on a lower major version than before.

I've been puzzled by this for a while, but today it struck again and I was able to reproduce the behavior.

A short description of the problem:

  • When there are multiple major versions of a dependency in use in the workspace (say aaa 0.1.0 and aaa 0.2.0), and
  • Some crate bbb in the dependency tree is compatible with multiple major versions (aaa = { version = ">=0.1, <=0.2" }),
  • Running cargo update -p ccc on an unrelated dependency can cause bbb to switch from using aaa 0.2.0 to aaa 0.1.0 in Cargo.lock.

My naive expectation is that cargo update -p should not modify unrelated dependency edges unnecessarily. Downgrading across a major version is particularly unwelcome (even when the dependent appears to permit it). The resulting Cargo.lock should only contain changes that are forced by the package that was updated.

Steps

Here is one way to reproduce the issue with some common dependencies:

  1. start by pinning dependency versions to give us a Cargo.lock with some versions from the past:
[package]
name = "cargo_version_jitter"
version = "0.1.0"
edition = "2021"

[dependencies]
diesel = "=2.2.2"
prost-build = "=0.12.6"
  1. cargo check to create a Cargo.lock with those dependency versions.
    We now have a transitive dependency on heck 0.5.0.

  2. Add another direct dependency on clap_derive:

[package]
name = "cargo_version_jitter"
version = "0.1.0"
edition = "2021"

[dependencies]
diesel = "=2.2.2"
prost-build = "=0.12.6"
clap_derive = "=4.4.7"
  1. cargo check to update Cargo.lock.
    Note we are now (indirectly) depending on heck 0.4.0 and heck 0.5.0.

  2. Remove the version pinning:

[package]
name = "cargo_version_jitter"
version = "0.1.0"
edition = "2021"

[dependencies]
diesel = "2.2.2"
prost-build = "0.12.6"
clap_derive = "4.4.7"

If you want you can run cargo check again, but it won't change Cargo.lock since all dependencies are satisfied.

  1. Run cargo tree and observe that prost-build is using heck 0.5.0:
...
└── prost-build v0.12.6
    ├── bytes v1.7.1
    ├── heck v0.5.0

or look at Cargo.lock:

[[package]]
name = "prost-build"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4"
dependencies = [
 "bytes",
 "heck 0.5.0",
 "itertools",
 "log",
 "multimap",
 "once_cell",
 "petgraph",
 "prettyplease",
 "prost",
 "prost-types",
 "regex",
 "syn",
 "tempfile",
]
  1. Run cargo update -p diesel. (Because of a new rustsec vulnerability.)

  2. Observe that Cargo.lock has changed in unexpected ways:

[[package]]
 name = "prost-build"
 version = "0.12.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4"
 dependencies = [
  "bytes",
- "heck 0.5.0",
+ "heck 0.4.1",
  "itertools",
  "log",
  "multimap",
  "once_cell",
  "petgraph",
  "prettyplease",
  "prost",
  "prost-types",
  "regex",
  "syn",
  "tempfile",
 ]
  1. Further observe that if I manually revert this change from Cargo.lock, the dependency tree is stable, i.e. running cargo check will not force it to be downgraded again.

  2. If I go back to the state before I ran cargo update and instead modify Cargo.toml to say diesel = "2.2.3" and run cargo check then I do not see the unrelated change in Cargo.lock. From this I conclude that this was an unnecessary/unforced change to Cargo.lock that seems to be specific to cargo update.

Possible Solution(s)

No idea.

Notes

I work in a very large Cargo workspace with thousands of dependencies, and updating all workspace dependencies at once is too disruptive. We perform minimal dependency updates when rustsec advisories appear.

Version

cargo 1.80.0 (376290515 2024-07-16)
release: 1.80.0
commit-hash: 37629051518c3df9ac2c1744589362a02ecafa99
commit-date: 2024-07-16
host: x86_64-unknown-linux-gnu
libgit2: 1.7.2 (sys:0.18.3 vendored)
libcurl: 8.6.0-DEV (sys:0.4.72+curl-8.6.0 vendored ssl:OpenSSL/1.1.1w)
ssl: OpenSSL 1.1.1w  11 Sep 2023
os: Ubuntu 22.4.0 (jammy) [64-bit]
@eric-seppanen eric-seppanen added C-bug Category: bug S-triage Status: This issue is waiting on initial triage. labels Aug 26, 2024
@epage
Copy link
Contributor

epage commented Aug 26, 2024

This sounds like its a duplicate of #5529 and so closing in favor of that, If there is a reason to keep this open separately, let us know!

@epage epage closed this as not planned Won't fix, can't repro, duplicate, stale Aug 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug Command-update S-triage Status: This issue is waiting on initial triage.
Projects
None yet
Development

No branches or pull requests

4 participants
@epage @eric-seppanen and others