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 picks an older version of a dep that breaks the build #7866

Closed
zhaojiangbin opened this issue Feb 5, 2020 · 5 comments
Closed

Cargo picks an older version of a dep that breaks the build #7866

zhaojiangbin opened this issue Feb 5, 2020 · 5 comments
Labels
C-bug Category: bug

Comments

@zhaojiangbin
Copy link

Problem
This is tricky issue. Cargo insists on using an older and incompatible version of a dep crate that breaks the build, only in certain combination(s) of the deps.

This the compilation error comes from the simplified reproduction when it fails:

error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
 --> one/src/main.rs:4:27
  |
4 |     const HDRLEN: usize = MutableUdpPacket::minimum_packet_size();
  |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This dep crate name is pnet_macros. In v0.21.0 of this crate, this function minimum_packet_size() was indeed not const. It's declared const since v0.22.0. There are newer versions of this crate in crates.io. Cargo picks v0.21.0 in the reproduction setup, and a newer version in a non-reproduction setup.

This crate is part of libpnet which consists of a few more crates. One of them depends on pnet_macros with this spec:

pnet_packet/Cargo.toml:pnet_macros = { path = "../pnet_macros", version = ">=0.20" }

My crate does not use pnet_macros directly. It uses pnet_packet. I was using libpnet v0.23.0. It was yanked. So I upgraded to libpnet v0.25.0. Build fails with both.

My crate shares a workspace with another crate. The issue didn't happen until I added a benchmark test, and dev-dep on criterion, in the second crate. The second crate does not use libpnet. The two crates are not related (In the future one crate will use another but that is irrelevant here).

It looks like that adding dev-dep on criterion somehow causes Cargo to pick an older version of another dep that breaks the build.

Cargo should be consistent in picking the dep versions.

Steps

  1. Clone this git repo for the simplified reproduction: https://github.com/zhaojiangbin/cargo-issue-reproduction.git
  2. Use the master branch to reproduce the issue with cargo build --bin one.
  3. Switch to the no-reproduction branch which removes the benchmark test and dev-dep on criterion. Run cargo build --bin one and expect the build to finish without issue.
  4. Please pay attention to the different versions of pnet_macros that cargo downloads/compiles in building the two branches.

Possible Solution(s)

Notes

Output of cargo version:
cargo 1.41.0 (626f0f4 2019-12-03)

  1. Cargo.lock is not included in the reproduction git repo on purpose. I reproduced the issue with ~/.cargo/registry removed, cargo clean run and Cargo.lock deleted.
  2. The actual benchmark test code does not matter. In the git repo the test .rs file is empty as a placeholder.
  3. The actual code of the second crate in this reproduction git repo probably doesn't matter either. You don't even need to build the second crate to see the issue happening.
  4. In addition to adding dev-dep on criterion specifically, I don't know if adding a different dep, dev or not, can reproduce the issue, too. In my "real" workspace, the second crate does have a few deps such as libc, anyhow. Adding them did not trigger the issue.
  5. The reproduction probably does not even need the second crate if the benchmark test and dev-dep on criterion were added in the first crate. I didn't test though.
@ehuss
Copy link
Contributor

ehuss commented Feb 5, 2020

I think it is working as expected. pnet_macros 0.25 declares a dependency on regex = "1.0.*" and criterion declares a dependency regex = { version = "1.3", default-features = false, features = ["std"] }. There is no compatible 1.*.* version of regex that satisfies both requirements, so Cargo starts looking for older versions that will. pnet_macros 0.21 has the requirement version = "0.2.*" for regex, and Cargo allows that because 0.* and 1.* can coexist.

I don't know why pnet_macros has such a strict requirement. It should generally be avoided if possible.

@zhaojiangbin
Copy link
Author

zhaojiangbin commented Feb 6, 2020

@ehuss Thanks for the quick response.

What you explained makes sense. I am able to simplify the reproduction further to just one new crate that:

  1. uses that function MutableUdpPacket::minimum_packet_size() as const,
  2. has the dep on pnet "0.25.0" and the dev-dep on criterion "0.3.1".

I will update the issue I filed on libpnet.

Now I feel that we could use a bit more visibility from Cargo. Would cargo build or cargo update be able to, by a command option, put up a warning even just saying "Unable to use a more recent version of pnet_macros" in a case like this?

Or maybe another command line option to "explain" how the dep versions are calculated?

Also do you think it would have avoided this issue if pnet_packet was requiring a more recent version of pnet_macros? Or would that have caused conflicting dep specs thus stopped cargo from finding a version?

[Minor grammar fixes]

@zhaojiangbin
Copy link
Author

UPDATE:

If I add a dep on pnet_macros in a crate, like below:

[dependencies]
pnet = "0.25.0"
pnet_macros = "0.25.0"
[dev-dependencies]
criterion = "0.3.1"

cargo build fails with:

$ cargo build
    Updating crates.io index
error: failed to select a version for `regex`.
    ... required by package `pnet_macros v0.25.0`
    ... which is depended on by `foo v0.1.0 (/Users/jzhao/CodeWorks/Rust/foo)`
versions that meet the requirements `1.0.*` are: 1.0.6, 1.0.5, 1.0.4, 1.0.3, 1.0.2, 1.0.1, 1.0.0

all possible versions conflict with previously selected packages.

  previously selected package `regex v1.3.0`
    ... which is depended on by `criterion v0.3.1`
    ... which is depended on by `foo v0.1.0 (/Users/jzhao/CodeWorks/Rust/foo)`

failed to select a version for `regex` which could resolve this conflict

@ehuss
Copy link
Contributor

ehuss commented Feb 25, 2020

I'm going to close this since it is expected behavior. However, I have opened #7929 for the feature request to make it easier to discover and explain why it happens.

@ehuss ehuss closed this as completed Feb 25, 2020
@zhaojiangbin
Copy link
Author

@ehuss Thanks for creating the feature request issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug
Projects
None yet
Development

No branches or pull requests

2 participants