dtolnay / dtolnay/trybuild

Inconsistent dependency versions from weird cargo behaviours

Open
#261 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
998
Forks
84
PR merge metrics
No merged PRs in 30d

Description

Hi.

I found this strange issue while working on derive-deftly, which uses multiple crates in the workspace, with various cargo features; and also has quite relaxed dependency specifications.

In https://gitlab.torproject.org/Diziet/rust-derive-deftly/-/jobs/507457 it appears that cargo concluded it didn't need to download toml 0.5.11 for the proposed test run:

```
Running `/builds/Diziet/rust-derive-deftly/target/debug/deps/trybuild-27b1d08daa9c16ae`
running 1 test
error: failed to download `toml v0.5.11`
Caused by:
attempting to make an HTTP request, but --offline was specified
test run_pass_expand ... FAILED
failures:
---- run_pass_expand stdout ----
thread 'run_pass_expand' panicked at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/trybuild-1.0.90/src/run.rs:61:13:
```

Looking at the dependencies there, cargo is (as far as it could tell) correct: the requested test run does not enable the features that pull in `macrotest` and it's `macrotest` that wants `toml 0.5.11`. The lockfile says to use `toml 0.8.2` for `derive-deftly-tests`, which is the crate containing the `trybuild` calls.

But when cargo tries to build trybuild's test crate `derive-deftly-tests-tests`, cargo chooses to use `toml 0.5.11` to satisfy the dependency. (I have observed this locally by looking in `target/tests/trybuild/derive-deftly-tests/Cargo.lock`.) This may be because `macrotest` demands `0.5` and nothing else in *that* crate tree *demands* `0.8`, so cargo thinks it can save on duplication this way. (I think because the synthetic crate isn't part of the workspace, the *other* crates in the workspace that would bring in `0.8` aren't there.)

As a result, that build needs `toml 0.5.11` which hasn't been downloaded. I'm working around this for now with an additional call to `cargo fetch`. That fetches `toml 0.5.11` so the test passes.

But that's not really right: what we want is for the syntehtic test crate to use the same versions as the crate containing the trybuild calls. I haven't tested it, but:

I think a big part of the reason this is happening is that cargo is forced to make up a whole new lockfile entry for the synthetic crate. So I suggest the following strategy: after copying the workspace `Cargo.lock`, add an additional `[[package]]` entry for the synthetic crate, which is simply a copy of the invoking crate's entry (with changed `name` and `version`). Maybe if we did that cargo would leave it alone.

I think we would still need `cargo fetch`.

Another option might be to try to avoid this situation where the synthetic crate isn't part of the workspace. If the other workspace members were present to influence dependency selection, we could hope that cargo would do the same for the synthetic crate as for the invoking crate, and then everything would be fine. I think?

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.