Part of the “Rustober” series.
Rust’s cargo
tool is quite pleasant to use. I know that Rust projects generally use many dependencies in total (dozens) and I thought: how do I get a dependency tree? Turns out, cargo
has a [built-in tree
command].
The output for my project that I described in “A Rust web service” is a bit scary! The stars *
mean that this dependency is present somewhere else in the list, so its dependencies are omitted.
[REDACTED] v0.1.0 (/Users/ykar/Documents/Programming/[REDACTED])
├── askama v0.14.0
│ ├── askama_derive v0.14.0 (proc-macro)
│ │ ├── askama_parser v0.14.0
│ │ │ ├── memchr v2.7.6
│ │ │ ├── serde v1.0.228
│ │ │ │ ├── serde_core v1.0.228
│ │ │ │ └── serde_derive v1.0.228 (proc-macro)
│ │ │ │ ├── proc-macro2 v1.0.101
│ │ │ │ │ └── unicode-ident v1.0.19
│ │ │ │ ├── quote v1.0.41
│ │ │ │ │ └── proc-macro2 v1.0.101 (*)
│ │ │ │ └── syn v2.0.106
│ │ │ │ ├── proc-macro2 v1.0.101 (*)
│ │ │ │ ├── quote v1.0.41 (*)
│ │ │ │ └── unicode-ident v1.0.19
│ │ │ ├── serde_derive v1.0.228 (proc-macro) (*)
│ │ │ └── winnow v0.7.13
│ │ ├── basic-toml v0.1.10
│ │ │ └── serde v1.0.228 (*)
│ │ ├── memchr v2.7.6
│ │ ├── proc-macro2 v1.0.101 (*)
│ │ ├── quote v1.0.41 (*)
│ │ ├── rustc-hash v2.1.1
│ │ ├── serde v1.0.228 (*)
│ │ ├── serde_derive v1.0.228 (proc-macro) (*)
│ │ └── syn v2.0.106 (*)
│ ├── itoa v1.0.15
│ └── percent-encoding v2.3.2
├── axum v0.8.6
│ ├── axum-core v0.5.5
│ │ ├── bytes v1.10.1
│ │ ├── futures-core v0.3.31
│ │ ├── http v1.3.1
│ │ │ ├── bytes v1.10.1
│ │ │ ├── fnv v1.0.7
│ │ │ └── itoa v1.0.15
│ │ ├── http-body v1.0.1
│ │ │ ├── bytes v1.10.1
│ │ │ └── http v1.3.1 (*)
│ │ ├── http-body-util v0.1.3
│ │ │ ├── bytes v1.10.1
│ │ │ ├── futures-core v0.3.31
│ │ │ ├── http v1.3.1 (*)
│ │ │ ├── http-body v1.0.1 (*)
│ │ │ └── pin-project-lite v0.2.16
│ │ ├── mime v0.3.17
│ │ ├── pin-project-lite v0.2.16
│ │ ├── sync_wrapper v1.0.2
│ │ ├── tower-layer v0.3.3
│ │ ├── tower-service v0.3.3
│ │ └── tracing v0.1.41
│ │ ├── log v0.4.28
│ │ ├── pin-project-lite v0.2.16
│ │ ├── tracing-attributes v0.1.30 (proc-macro)
│ │ │ ├── proc-macro2 v1.0.101 (*)
│ │ │ ├── quote v1.0.41 (*)
│ │ │ └── syn v2.0.106 (*)
│ │ └── tracing-core v0.1.34
│ │ └── once_cell v1.21.3
│ ├── bytes v1.10.1
│ ├── form_urlencoded v1.2.2
│ │ └── percent-encoding v2.3.2
│ ├── futures-util v0.3.31
│ │ ├── futures-core v0.3.31
│ │ ├── futures-io v0.3.31
│ │ ├── futures-sink v0.3.31
│ │ ├── futures-task v0.3.31
│ │ ├── memchr v2.7.6
│ │ ├── pin-project-lite v0.2.16
│ │ ├── pin-utils v0.1.0
│ │ └── slab v0.4.11
│ ├── http v1.3.1 (*)
│ ├── http-body v1.0.1 (*)
│ ├── http-body-util v0.1.3 (*)
│ ├── hyper v1.7.0
│ │ ├── atomic-waker v1.1.2
│ │ ├── bytes v1.10.1
│ │ ├── futures-channel v0.3.31
│ │ │ └── futures-core v0.3.31
│ │ ├── futures-core v0.3.31
│ │ ├── http v1.3.1 (*)
│ │ ├── http-body v1.0.1 (*)
│ │ ├── httparse v1.10.1
│ │ ├── httpdate v1.0.3
│ │ ├── itoa v1.0.15
│ │ ├── pin-project-lite v0.2.16
│ │ ├── pin-utils v0.1.0
│ │ ├── smallvec v1.15.1
│ │ └── tokio v1.47.1
│ │ ├── bytes v1.10.1
│ │ ├── libc v0.2.177
│ │ ├── mio v1.0.4
│ │ │ └── libc v0.2.177
│ │ ├── parking_lot v0.12.5
│ │ │ ├── lock_api v0.4.14
│ │ │ │ └── scopeguard v1.2.0
│ │ │ └── parking_lot_core v0.9.12
│ │ │ ├── cfg-if v1.0.3
│ │ │ ├── libc v0.2.177
│ │ │ └── smallvec v1.15.1
│ │ ├── pin-project-lite v0.2.16
│ │ ├── signal-hook-registry v1.4.6
│ │ │ └── libc v0.2.177
│ │ ├── socket2 v0.6.0
│ │ │ └── libc v0.2.177
│ │ └── tokio-macros v2.5.0 (proc-macro)
│ │ ├── proc-macro2 v1.0.101 (*)
│ │ ├── quote v1.0.41 (*)
│ │ └── syn v2.0.106 (*)
│ ├── hyper-util v0.1.17
│ │ ├── bytes v1.10.1
│ │ ├── futures-core v0.3.31
│ │ ├── http v1.3.1 (*)
│ │ ├── http-body v1.0.1 (*)
│ │ ├── hyper v1.7.0 (*)
│ │ ├── pin-project-lite v0.2.16
│ │ ├── tokio v1.47.1 (*)
│ │ └── tower-service v0.3.3
│ ├── itoa v1.0.15
│ ├── matchit v0.8.4
│ ├── memchr v2.7.6
│ ├── mime v0.3.17
│ ├── percent-encoding v2.3.2
│ ├── pin-project-lite v0.2.16
│ ├── serde_core v1.0.228
│ ├── serde_json v1.0.145
│ │ ├── itoa v1.0.15
│ │ ├── memchr v2.7.6
│ │ ├── ryu v1.0.20
│ │ └── serde_core v1.0.228
│ ├── serde_path_to_error v0.1.20
│ │ ├── itoa v1.0.15
│ │ └── serde_core v1.0.228
│ ├── serde_urlencoded v0.7.1
│ │ ├── form_urlencoded v1.2.2 (*)
│ │ ├── itoa v1.0.15
│ │ ├── ryu v1.0.20
│ │ └── serde v1.0.228 (*)
│ ├── sync_wrapper v1.0.2
│ ├── tokio v1.47.1 (*)
│ ├── tower v0.5.2
│ │ ├── futures-core v0.3.31
│ │ ├── futures-util v0.3.31 (*)
│ │ ├── pin-project-lite v0.2.16
│ │ ├── sync_wrapper v1.0.2
│ │ ├── tokio v1.47.1 (*)
│ │ ├── tower-layer v0.3.3
│ │ ├── tower-service v0.3.3
│ │ └── tracing v0.1.41 (*)
│ ├── tower-layer v0.3.3
│ ├── tower-service v0.3.3
│ └── tracing v0.1.41 (*)
├── serde v1.0.228 (*)
├── sqlx v0.8.6
│ ├── sqlx-core v0.8.6
│ │ ├── base64 v0.22.1
│ │ ├── bytes v1.10.1
│ │ ├── crc v3.3.0
│ │ │ └── crc-catalog v2.4.0
│ │ ├── crossbeam-queue v0.3.12
│ │ │ └── crossbeam-utils v0.8.21
│ │ ├── either v1.15.0
│ │ │ └── serde v1.0.228 (*)
│ │ ├── event-listener v5.4.1
│ │ │ ├── concurrent-queue v2.5.0
│ │ │ │ └── crossbeam-utils v0.8.21
│ │ │ ├── parking v2.2.1
│ │ │ └── pin-project-lite v0.2.16
│ │ ├── futures-core v0.3.31
│ │ ├── futures-intrusive v0.5.0
│ │ │ ├── futures-core v0.3.31
│ │ │ ├── lock_api v0.4.14 (*)
│ │ │ └── parking_lot v0.12.5 (*)
│ │ ├── futures-io v0.3.31
│ │ ├── futures-util v0.3.31 (*)
│ │ ├── hashbrown v0.15.5
│ │ │ ├── allocator-api2 v0.2.21
│ │ │ ├── equivalent v1.0.2
│ │ │ └── foldhash v0.1.5
│ │ ├── hashlink v0.10.0
│ │ │ └── hashbrown v0.15.5 (*)
│ │ ├── indexmap v2.11.4
│ │ │ ├── equivalent v1.0.2
│ │ │ └── hashbrown v0.16.0
│ │ ├── log v0.4.28
│ │ ├── memchr v2.7.6
│ │ ├── once_cell v1.21.3
│ │ ├── percent-encoding v2.3.2
│ │ ├── serde v1.0.228 (*)
│ │ ├── serde_json v1.0.145 (*)
│ │ ├── sha2 v0.10.9
│ │ │ ├── cfg-if v1.0.3
│ │ │ ├── cpufeatures v0.2.17
│ │ │ │ └── libc v0.2.177
│ │ │ └── digest v0.10.7
│ │ │ ├── block-buffer v0.10.4
│ │ │ │ └── generic-array v0.14.7
│ │ │ │ └── typenum v1.19.0
│ │ │ │ [build-dependencies]
│ │ │ │ └── version_check v0.9.5
│ │ │ └── crypto-common v0.1.6
│ │ │ ├── generic-array v0.14.7 (*)
│ │ │ └── typenum v1.19.0
│ │ ├── smallvec v1.15.1
│ │ ├── thiserror v2.0.17
│ │ │ └── thiserror-impl v2.0.17 (proc-macro)
│ │ │ ├── proc-macro2 v1.0.101 (*)
│ │ │ ├── quote v1.0.41 (*)
│ │ │ └── syn v2.0.106 (*)
│ │ ├── tracing v0.1.41 (*)
│ │ └── url v2.5.7
│ │ ├── form_urlencoded v1.2.2 (*)
│ │ ├── idna v1.1.0
│ │ │ ├── idna_adapter v1.2.1
│ │ │ │ ├── icu_normalizer v2.0.0
│ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro)
│ │ │ │ │ │ ├── proc-macro2 v1.0.101 (*)
│ │ │ │ │ │ ├── quote v1.0.41 (*)
│ │ │ │ │ │ └── syn v2.0.106 (*)
│ │ │ │ │ ├── icu_collections v2.0.0
│ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*)
│ │ │ │ │ │ ├── potential_utf v0.1.3
│ │ │ │ │ │ │ └── zerovec v0.11.4
│ │ │ │ │ │ │ ├── yoke v0.8.0
│ │ │ │ │ │ │ │ ├── stable_deref_trait v1.2.1
│ │ │ │ │ │ │ │ ├── yoke-derive v0.8.0 (proc-macro)
│ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.101 (*)
│ │ │ │ │ │ │ │ │ ├── quote v1.0.41 (*)
│ │ │ │ │ │ │ │ │ ├── syn v2.0.106 (*)
│ │ │ │ │ │ │ │ │ └── synstructure v0.13.2
│ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.101 (*)
│ │ │ │ │ │ │ │ │ ├── quote v1.0.41 (*)
│ │ │ │ │ │ │ │ │ └── syn v2.0.106 (*)
│ │ │ │ │ │ │ │ └── zerofrom v0.1.6
│ │ │ │ │ │ │ │ └── zerofrom-derive v0.1.6 (proc-macro)
│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.101 (*)
│ │ │ │ │ │ │ │ ├── quote v1.0.41 (*)
│ │ │ │ │ │ │ │ ├── syn v2.0.106 (*)
│ │ │ │ │ │ │ │ └── synstructure v0.13.2 (*)
│ │ │ │ │ │ │ ├── zerofrom v0.1.6 (*)
│ │ │ │ │ │ │ └── zerovec-derive v0.11.1 (proc-macro)
│ │ │ │ │ │ │ ├── proc-macro2 v1.0.101 (*)
│ │ │ │ │ │ │ ├── quote v1.0.41 (*)
│ │ │ │ │ │ │ └── syn v2.0.106 (*)
│ │ │ │ │ │ ├── yoke v0.8.0 (*)
│ │ │ │ │ │ ├── zerofrom v0.1.6 (*)
│ │ │ │ │ │ └── zerovec v0.11.4 (*)
│ │ │ │ │ ├── icu_normalizer_data v2.0.0
│ │ │ │ │ ├── icu_provider v2.0.0
│ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*)
│ │ │ │ │ │ ├── icu_locale_core v2.0.0
│ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*)
│ │ │ │ │ │ │ ├── litemap v0.8.0
│ │ │ │ │ │ │ ├── tinystr v0.8.1
│ │ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*)
│ │ │ │ │ │ │ │ └── zerovec v0.11.4 (*)
│ │ │ │ │ │ │ ├── writeable v0.6.1
│ │ │ │ │ │ │ └── zerovec v0.11.4 (*)
│ │ │ │ │ │ ├── stable_deref_trait v1.2.1
│ │ │ │ │ │ ├── tinystr v0.8.1 (*)
│ │ │ │ │ │ ├── writeable v0.6.1
│ │ │ │ │ │ ├── yoke v0.8.0 (*)
│ │ │ │ │ │ ├── zerofrom v0.1.6 (*)
│ │ │ │ │ │ ├── zerotrie v0.2.2
│ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*)
│ │ │ │ │ │ │ ├── yoke v0.8.0 (*)
│ │ │ │ │ │ │ └── zerofrom v0.1.6 (*)
│ │ │ │ │ │ └── zerovec v0.11.4 (*)
│ │ │ │ │ ├── smallvec v1.15.1
│ │ │ │ │ └── zerovec v0.11.4 (*)
│ │ │ │ └── icu_properties v2.0.1
│ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*)
│ │ │ │ ├── icu_collections v2.0.0 (*)
│ │ │ │ ├── icu_locale_core v2.0.0 (*)
│ │ │ │ ├── icu_properties_data v2.0.1
│ │ │ │ ├── icu_provider v2.0.0 (*)
│ │ │ │ ├── potential_utf v0.1.3 (*)
│ │ │ │ ├── zerotrie v0.2.2 (*)
│ │ │ │ └── zerovec v0.11.4 (*)
│ │ │ ├── smallvec v1.15.1
│ │ │ └── utf8_iter v1.0.4
│ │ ├── percent-encoding v2.3.2
│ │ └── serde v1.0.228 (*)
│ └── sqlx-macros v0.8.6 (proc-macro)
│ ├── proc-macro2 v1.0.101 (*)
│ ├── quote v1.0.41 (*)
│ ├── sqlx-core v0.8.6 (*)
│ ├── sqlx-macros-core v0.8.6
│ │ ├── dotenvy v0.15.7
│ │ ├── either v1.15.0 (*)
│ │ ├── heck v0.5.0
│ │ ├── hex v0.4.3
│ │ ├── once_cell v1.21.3
│ │ ├── proc-macro2 v1.0.101 (*)
│ │ ├── quote v1.0.41 (*)
│ │ ├── serde v1.0.228 (*)
│ │ ├── serde_json v1.0.145 (*)
│ │ ├── sha2 v0.10.9
│ │ │ ├── cfg-if v1.0.3
│ │ │ ├── cpufeatures v0.2.17 (*)
│ │ │ └── digest v0.10.7
│ │ │ ├── block-buffer v0.10.4 (*)
│ │ │ └── crypto-common v0.1.6
│ │ │ ├── generic-array v0.14.7 (*)
│ │ │ └── typenum v1.19.0
│ │ ├── sqlx-core v0.8.6 (*)
│ │ ├── syn v2.0.106 (*)
│ │ └── url v2.5.7 (*)
│ └── syn v2.0.106 (*)
├── tokio v1.47.1 (*)
├── tower v0.5.2 (*)
└── tower-http v0.6.6
├── bitflags v2.9.4
├── bytes v1.10.1
├── futures-core v0.3.31
├── futures-util v0.3.31 (*)
├── http v1.3.1 (*)
├── http-body v1.0.1 (*)
├── http-body-util v0.1.3 (*)
├── http-range-header v0.4.2
├── httpdate v1.0.3
├── mime v0.3.17
├── mime_guess v2.0.5
│ ├── mime v0.3.17
│ └── unicase v2.8.1
│ [build-dependencies]
│ └── unicase v2.8.1
├── percent-encoding v2.3.2
├── pin-project-lite v0.2.16
├── tokio v1.47.1 (*)
├── tokio-util v0.7.16
│ ├── bytes v1.10.1
│ ├── futures-core v0.3.31
│ ├── futures-sink v0.3.31
│ ├── pin-project-lite v0.2.16
│ └── tokio v1.47.1 (*)
├── tower-layer v0.3.3
├── tower-service v0.3.3
└── tracing v0.1.41 (*)
Looking at all the different versions, I immediately thought: what happens if two dependencies use different versions of the same crate? Cargo usually resolves the issue by bumping one version (if possible) to another, but if the versions are SemVer-incompatible (i.e. 1.0 and 2.0), then both are included separately. Of course, this does not always work smoothly, but I don’t expect to run into this kind of problem for my project (and even then there are ways of resolving it).
What’s interesting is that in the latter case you will get an error similar to this (source):
error[E0308]: mismatched types
--> ucat/src/interface.rs:28:5
|
28 | iface.ips.iter().find(|ipn| ipn.is_ipv4())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `ipnetwork::IpNetwork`, found a different enum `ipnetwork::IpNetwork`
|
= note: expected enum `std::option::Option<&ipnetwork::IpNetwork>` (enum `ipnetwork::IpNetwork`)
found enum `std::option::Option<&ipnetwork::IpNetwork>` (enum `ipnetwork::IpNetwork`)
= note: perhaps two different versions of crate `ipnetwork` are being used?
error: aborting due to previous error
Cargo has specific recommendations on how libraries should follow SemVer to reduce the possibility of such problems.