12
votes

I have a project that has a dependency (a cookie utility) that has a dependency on iron >= 0.3, <= 0.4.

My project has a dependency on iron 0.3 (so I can use the router middleware that hasn't yet been updated to the latest iron).

When I try to compile my project, the cookie utility pulls the 0.4 version of iron, and I get errors since different versions of iron are being used.

However, I can do:

cargo update -p <cookie utility>

which (usually) changes that package's dependency on iron to match the one I am using, and removes the extraneous dependency on iron 0.4. (Bizarrely, I sometimes have to run that command a couple of times before it updates.)

Apparently I can't specify the dependency version of a dependency: Set specific version of the dependency of a project's dependency in Cargo.toml or Cargo.lock.

It would be nice if cargo could guess that I want to use a single version of iron, but I understand why it can't. However, I'm confused about why cargo update -p <package> actually works; it seems non-intuitive that it would update a dependency for the package.


I guess my first real question is: how can I specify the dependency versions of dependencies (when and only when the version I want is within the supported version range of that library)? I don't think the solutions suggested in the question linked above are ideal. I feel like it would be better if Cargo could support this well, so that libraries could leave their dependency version ranges as open as their functionality allows.

At the same time, I found this "trick" that seems to do what I want (cargo update -p <pkg>). I haven't looked super hard, but this behavior doesn't seem to be described in any obvious place. My second question is: is this a valid way to coalesce dependencies? Is there any place I can find more information about this?


And steps to reproduce:

  1. Create a new project: cargo new --bin ironapp; cd ironapp.
  2. Create the cookie dependency: cargo new cookie_util.
  3. In cookie_util/Cargo.toml add one dependency: iron = ">= 0.3, <= 0.4".
  4. In Cargo.toml add two dependencies: iron = "0.3.0" and cookie_util = { path = "cookie_util"}.
  5. cargo build. Confirm that two versions of iron are required in Cargo.lock.
  6. Run cargo update -p cookie_util anywhere between 1 and 4 (or more) times. Eventually it will remove the dependency on iron 0.4.0.

I just tested this on rustc-1.10.0/cargo-0.11.0. I made sure target and Cargo.lock were both absent at the start of step 1.

1
This might be worth creating an issue here.squiguy
I second the comment from @squiguy; create an issue. However, make sure you provide a minimal reproducible example when filing the issue. And here.Shepmaster
Thanks for the comments. I've tried to clarify my questions a little bitJacob Brown
I think this is related to Cargo issue 2164, and I've added a comment on that issue.Jacob Brown

1 Answers

6
votes

Reading through the comments of cargo/issues/2064, I realized that a more robust way of resolving these types of dependencies is to use the --precise flag. For my example,

cargo update -p iron:0.4.0 --precise 0.3.0

removes the unnecessary dependency. This requires one to dig into Cargo.lock and manually determine where dependencies can converge, but is far better than running cargo update -p <pkg> and hoping for the best, or manually editing Cargo.lock.