I have mysterious appearance of quinn
dependency in Cargo.lock
in project which includes request
dependency, while I expect it to be not present due to disabled features.
It is very easy to reproduce in sample app, here I provide all the commands to reproduce issue:
❯ cargo --version
cargo 1.83.0 (5ffbef321 2024-10-29)
❯ cargo new reqwest-mystery
Creating binary (application) `reqwest-mystery` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
❯ cd reqwest-mystery
❯ cargo build
Compiling reqwest-mystery v0.1.0 (/Users/user/Developer/Local/reqwest-mystery)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.01s
❯ cat Cargo.lock
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "reqwest-mystery"
version = "0.1.0"
❯ cargo add reqwest --no-default-features
Updating crates.io index
Adding reqwest v0.12.9 to dependencies
Features:
33 deactivated features
Updating crates.io index
Locking 104 packages to latest compatible versions
Adding addr2line v0.24.2
Adding adler2 v2.0.0
Adding backtrace v0.3.74
Adding base64 v0.22.1
Adding bumpalo v3.16.0
Adding bytes v1.9.0
Adding cfg-if v1.0.0
Adding displaydoc v0.2.5
Adding fnv v1.0.7
Adding form_urlencoded v1.2.1
Adding futures-channel v0.3.31
Adding futures-core v0.3.31
Adding futures-task v0.3.31
Adding futures-util v0.3.31
Adding gimli v0.31.1
Adding hermit-abi v0.3.9
Adding http v1.1.0
Adding http-body v1.0.1
Adding http-body-util v0.1.2
Adding httparse v1.9.5
Adding hyper v1.5.1
Adding hyper-util v0.1.10
Adding icu_collections v1.5.0
Adding icu_locid v1.5.0
Adding icu_locid_transform v1.5.0
Adding icu_locid_transform_data v1.5.0
Adding icu_normalizer v1.5.0
Adding icu_normalizer_data v1.5.0
Adding icu_properties v1.5.1
Adding icu_properties_data v1.5.0
Adding icu_provider v1.5.0
Adding icu_provider_macros v1.5.0
Adding idna v1.0.3
Adding idna_adapter v1.2.0
Adding ipnet v2.10.1
Adding itoa v1.0.14
Adding js-sys v0.3.72
Adding libc v0.2.167
Adding litemap v0.7.4
Adding log v0.4.22
Adding memchr v2.7.4
Adding mime v0.3.17
Adding miniz_oxide v0.8.0
Adding mio v1.0.2
Adding object v0.36.5
Adding once_cell v1.20.2
Adding percent-encoding v2.3.1
Adding pin-project-lite v0.2.15
Adding pin-utils v0.1.0
Adding proc-macro2 v1.0.92
Adding quote v1.0.37
Adding reqwest v0.12.9
Adding rustc-demangle v0.1.24
Adding ryu v1.0.18
Adding serde v1.0.215
Adding serde_derive v1.0.215
Adding serde_json v1.0.133
Adding serde_urlencoded v0.7.1
Adding smallvec v1.13.2
Adding socket2 v0.5.8
Adding stable_deref_trait v1.2.0
Adding syn v2.0.89
Adding sync_wrapper v1.0.2
Adding synstructure v0.13.1
Adding tinystr v0.7.6
Adding tokio v1.41.1
Adding tower-service v0.3.3
Adding tracing v0.1.41
Adding tracing-core v0.1.33
Adding try-lock v0.2.5
Adding unicode-ident v1.0.14
Adding url v2.5.4
Adding utf16_iter v1.0.5
Adding utf8_iter v1.0.4
Adding want v0.3.1
Adding wasi v0.11.0+wasi-snapshot-preview1
Adding wasm-bindgen v0.2.95
Adding wasm-bindgen-backend v0.2.95
Adding wasm-bindgen-futures v0.4.45
Adding wasm-bindgen-macro v0.2.95
Adding wasm-bindgen-macro-support v0.2.95
Adding wasm-bindgen-shared v0.2.95
Adding web-sys v0.3.72
Adding windows-registry v0.2.0
Adding windows-result v0.2.0
Adding windows-strings v0.1.0
Adding windows-sys v0.52.0
Adding windows-targets v0.52.6
Adding windows_aarch64_gnullvm v0.52.6
Adding windows_aarch64_msvc v0.52.6
Adding windows_i686_gnu v0.52.6
Adding windows_i686_gnullvm v0.52.6
Adding windows_i686_msvc v0.52.6
Adding windows_x86_64_gnu v0.52.6
Adding windows_x86_64_gnullvm v0.52.6
Adding windows_x86_64_msvc v0.52.6
Adding write16 v1.0.0
Adding writeable v0.5.5
Adding yoke v0.7.5
Adding yoke-derive v0.7.5
Adding zerofrom v0.1.5
Adding zerofrom-derive v0.1.5
Adding zerovec v0.10.4
Adding zerovec-derive v0.10.3
❯ cat Cargo.toml
[package]
name = "reqwest-mystery"
version = "0.1.0"
edition = "2021"
[dependencies]
reqwest = { version = "0.12.9", default-features = false }
❯ cat Cargo.lock | grep -iE quinn
[no output]
❯ cargo add reqwest --no-default-features --features rustls-tls
Updating crates.io index
Adding reqwest v0.12.9 to dependencies
Features:
+ __rustls
+ __rustls-ring
+ __tls
+ rustls-tls
+ rustls-tls-webpki-roots
+ rustls-tls-webpki-roots-no-provider
27 deactivated features
Locking 34 packages to latest compatible versions
Adding autocfg v1.4.0
Adding byteorder v1.5.0
Adding cc v1.2.2
Adding cfg_aliases v0.2.1
Adding getrandom v0.2.15
Adding hyper-rustls v0.27.3
Adding ppv-lite86 v0.2.20
Adding quinn v0.11.6
Adding quinn-proto v0.11.9
Adding quinn-udp v0.5.7
Adding rand v0.8.5
Adding rand_chacha v0.3.1
Adding rand_core v0.6.4
Adding ring v0.17.8
Adding rustc-hash v2.0.0
Adding rustls v0.23.19
Adding rustls-pemfile v2.2.0
Adding rustls-pki-types v1.10.0
Adding rustls-webpki v0.102.8
Adding shlex v1.3.0
Adding slab v0.4.9
Adding spin v0.9.8
Adding subtle v2.6.1
Adding thiserror v2.0.3
Adding thiserror-impl v2.0.3
Adding tinyvec v1.8.0
Adding tinyvec_macros v0.1.1
Adding tokio-rustls v0.26.0
Adding untrusted v0.9.0
Adding web-time v1.1.0
Adding webpki-roots v0.26.7
Adding zerocopy v0.7.35
Adding zerocopy-derive v0.7.35
Adding zeroize v1.8.1
❯ cat Cargo.toml
[package]
name = "reqwest-mystery"
version = "0.1.0"
edition = "2021"
[dependencies]
reqwest = { version = "0.12.9", default-features = false, features = ["rustls-tls"] }
❯ cat Cargo.lock | grep -iE quinn
name = "quinn"
"quinn-proto",
"quinn-udp",
name = "quinn-proto"
name = "quinn-udp"
"quinn",
I've tried to use cargo tree
to find out how why dependency is added - but quinn
is not included into cargo tree
output.
❯ cargo tree -e normal --no-dedupe | grep -iE quinn
[no output]
❯ cargo tree -e features --no-dedupe | grep -iE quinn
[no output]
❯ cargo tree -e all --no-dedupe | grep -iE quinn
[no output]
So my question is how to properly debug dependency tree? How to understand WHY particular dependency included in Cargo.lock
?
So far the only reliable way I've found is randomly commenting stuff in Cargo.toml
to understand which dependencies are eventually included in Cargo.lock
, but there must be a better way.
This is a bug in Cargo and hopefully, it will get fixed one day. As of 2024, Cargo generates lockfiles under an assumption that all features might be enabled. Keep in mind that even though the package is in your Cargo.lock, it doesn't mean that it ever gets compiled. Obviously, it might be problematic for many other reasons — for instance, your CI running cargo-audit or a similar tool might report security issues about packages that you don't ever use. You might even run into a situation where there's no possibility to resolve the dependencies of your project because of this.
If you need to find out which package uses the problematic crate, it's slightly complicated because, well, it is a bug. There are at least two ways, though:
[[package]]
name = "reqwest"
version = "0.12.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f"
dependencies = [
...
"quinn",
...
]
cargo tree
is affected by the bug, cargo metadata
is not. You can just run it in your crate root and it will return a JSON file that contains all the packages used in the dependency tree along with their dependencies. Keep in mind though that this file might get quite large and is not made to be human-readable (using tools like jq might help).For more context: you can read in the bug report, that:
lockfile generation requires the assumption that all possible features are enabled. Generating a lockfile without optional features is covered by #5133
You might want to track the issue #5133 to be notified when this gets resolved.