-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Description
Problem
Lets say I have two crates, with these contents of Cargo.toml. The Rust code does not matter here.
# foo/Cargo.toml
[dependencies]
serde = {version = "1.0.133", optional = true, default-features = false}
time = {version = "=0.3.10", optional = true, default-features = false}
chrono = {version = "=0.4.18", optional = true, default-features = false}
[features]
serialization = ["dep:serde", "time?/serde-well-known"]# bar/Cargo.toml
[dependencies]
foo.features = ["serialization"]
foo.path = "../foo"
# time = "=0.3.11"
# chrono = "=0.4.19"As you can see, bar depends on foo and enables the serialization feature, but it does not enable the time nor the chrono feature.
This results in the following bar/Cargo.lock file:
bar/Cargo.lock
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "app"
version = "0.1.0"
dependencies = [
"foo",
]
[[package]]
name = "foo"
version = "0.1.0"
dependencies = [
"serde",
"time",
]
[[package]]
name = "itoa"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
[[package]]
name = "libc"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]]
name = "serde"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
[[package]]
name = "time"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82501a4c1c0330d640a6e176a3d6a204f5ec5237aca029029d21864a902e27b0"
dependencies = [
"itoa",
"libc",
"num_threads",
"serde",
]The relevant snippet is at the end:
[[package]]
name = "time"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82501a4c1c0330d640a6e176a3d6a204f5ec5237aca029029d21864a902e27b0"
dependencies = [
"itoa",
"libc",
"num_threads",
"serde",
]Here the dependency time is declared, even though it is an optional dependency and nothing enabled the corresponding feature on foo. The time dependency even has serde listed as one of its dependencies too.
I think this is problematic in a couple of ways.
It bloats the Cargo.lock and makes it imply that changes are larger than they actually are. In the above example adding foo will also add time even if that is not necessary.
Dependency management tools will get confused by this. I mean tools like dependabot or cargo audit, which use the Cargo.lock as source of truth. Since these tools will see an entry for time, even if it is unused, they will create pull requests or warn about security vulnerabilities which do not exists.
This prevents using two crates with conflicting version requirements. You can see what happens if you uncomment the lines in bar/Cargo.toml.
Uncommenting time will fail, since now two conflicting version constraints (=0.3.10 != =0.3.11) exist.
However, uncommenting chrono works with the conflicting versions (=0.4.18 != =0.4.19).
Steps
- Create project
foowith the above content forCargo.toml. - Create project
barwith the above content forCargo.toml. - Observe how the
Cargo.lockofbarcontains an entry fortimeand even a transitiveserdedependency intime.
Possible Solution(s)
Disabled optional dependencies should not be tracked in Cargo.lock, even if there is a weak dependency linking to it. This brings it in line with "normal" optional dependencies.
Notes
While the time entry exists in the Cargo.lock, it appears cargo correctly ignores it when building the code. There is neither a Compiling time ... log line nor are there any artifacts in the target folder associated with time.
I checked various issues and documentation entries, but I couldn't find if this is a bug or intended.
The tracking issue (#8832) and documentation (https://doc.rust-lang.org/nightly/cargo/reference/features.html#dependency-features) do not mention any changes in to Cargo.lock. Neither does the implementation PR (#8818), which does not even seem to have any lock files.
Version
cargo 1.62.0 (a748cf5a3 2022-06-08)
release: 1.62.0
commit-hash: a748cf5a3e666bc2dcdf54f37adef8ef22196452
commit-date: 2022-06-08
host: x86_64-unknown-linux-gnu
libgit2: 1.4.2 (sys:0.14.2 vendored)
libcurl: 7.80.0-DEV (sys:0.4.51+curl-7.80.0 vendored ssl:OpenSSL/1.1.1n)
os: OracleLinux 36.0.0 [64-bit]
FYI: My OS is Fedora 36, but this is the output of `cargo version --verbose`.