Builds in cargo workspaces

I am trying to understand how cargo builds crates within workspaces.

For this Cargo.toml at root directory in crossbeam project.

user@ultrabook:~/Packages/crossbeam$ cat Cargo.toml 
[package]
name = "crossbeam"
# When publishing a new version:
# - Update CHANGELOG.md
# - Update README.md (when increasing major or minor version)
# - Run './tools/publish.sh crossbeam <version>'
version = "0.8.4"
edition = "2021"
rust-version = "1.61"
license = "MIT OR Apache-2.0"
repository = "https://github.com/crossbeam-rs/crossbeam"
homepage = "https://github.com/crossbeam-rs/crossbeam"
description = "Tools for concurrent programming"
keywords = ["atomic", "garbage", "non-blocking", "lock-free", "rcu"]
categories = ["concurrency", "memory-management", "data-structures", "no-std"]
exclude = ["/.*", "/ci", "/tools"]

[features]
default = ["std"]

# Enable to use APIs that require `std`.
# This is enabled by default.
std = [
  "alloc",
  "crossbeam-channel/std",
  "crossbeam-deque/std",
  "crossbeam-epoch/std",
  "crossbeam-queue/std",
  "crossbeam-utils/std",
]

# Enable to use APIs that require `alloc`.
# This is enabled by default and also enabled if the `std` feature is enabled.
alloc = ["crossbeam-epoch/alloc", "crossbeam-queue/alloc"]

[dependencies]
crossbeam-channel = { version = "0.5.10", path = "crossbeam-channel", default-features = false, optional = true }
crossbeam-deque = { version = "0.8.4", path = "crossbeam-deque", default-features = false, optional = true }
crossbeam-epoch = { version = "0.9.17", path = "crossbeam-epoch", default-features = false, optional = true }
crossbeam-queue = { version = "0.3.10", path = "crossbeam-queue", default-features = false, optional = true }
crossbeam-utils = { version = "0.8.18", path = "crossbeam-utils", default-features = false, features = ["atomic"] }

Why does cargo test use crossbeam-epoch v0.9.18 instead of the version 0.9.17 specified above as per Cargo.toml?

user@ultrabook:~/Packages/crossbeam$ cargo clean
warning: ignoring `resolver.feature-unification` without `-Zfeature-unification`
     Removed 15710 files, 3.9GiB total
user@ultrabook:~/Packages/crossbeam$ cargo t
warning: ignoring `resolver.feature-unification` without `-Zfeature-unification`
   Compiling atomic-maybe-uninit v0.3.13
   Compiling crossbeam-utils v0.8.21 (/home/user/Packages/crossbeam/crossbeam-utils)
   Compiling crossbeam-epoch v0.9.18 (/home/user/Packages/crossbeam/crossbeam-epoch)
   Compiling crossbeam-channel v0.5.15 (/home/user/Packages/crossbeam/crossbeam-channel)
   Compiling crossbeam-queue v0.3.12 (/home/user/Packages/crossbeam/crossbeam-queue)
   Compiling crossbeam-deque v0.8.6 (/home/user/Packages/crossbeam/crossbeam-deque)
   Compiling crossbeam v0.8.4 (/home/user/Packages/crossbeam)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 1.03s
     Running unittests src/lib.rs (/home/user/~/.cargo/build-cache/debug/deps/crossbeam-4e531462c2db7866)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/subcrates.rs (/home/user/~/.cargo/build-cache/debug/deps/subcrates-1e40968ff29872ef)

running 5 tests
test channel ... ok
test deque ... ok
test epoch ... ok
test queue ... ok
test utils ... ok

The default kind of version requirement, that you get when you write just a version number in Cargo.toml, specifies a minimum version. The version actually used in the build is specified by Cargo.lock, not Cargo.toml; it is always compatible with the version requirement in Cargo.toml, and can be changed to the latest or a different version using the cargo update command.

2 Likes

I wonder what we can do to help users with this. The only thing I've come up with so far are:

  • lint for version reqs being behind the lockfile (Lint that a version requirement is lower than what is currently in `Cargo.lock` · Issue #15583 · rust-lang/cargo · GitHub) with a note explaining the situation. For the original motivation, this would have qualified as allow by default and we don't have precedence for having "teaching" lints warn by default. But being allow by default means it won't help users who need it.
  • lint for use of implicit version req operator to help draw attention to "something else is going on here". Maybe I'm biased by familiarity but I like seeing versions without an operator. It also draws attention to the use of other operators which should be minimized.
1 Like