Cargo dependency resolution discrepancy

I have a library where I defined dependency as

crypto-bigint = { version = "<= 0.7.0-rc.9", default-features = false, optional = true }

(I wanted to exclude 0.7.0-rc.10 that breaks the build)
This is being resolved to 0.7.0-rc.9 as expected.
However, when I reference this library from other project, this (now transitive) dependency resolves to 0.6.1.
Why would that be?
Thanks!

Would you mind pasting the cargo tree output from your project here?

Sure:

cargo tree
zinc-piop v0.1.0 (/home/fs/code/zinc-plus/piop)
β”œβ”€β”€ ark-std v0.5.0
β”‚   β”œβ”€β”€ num-traits v0.2.19
β”‚   β”‚   [build-dependencies]
β”‚   β”‚   └── autocfg v1.5.0
β”‚   └── rand v0.8.5
β”‚       β”œβ”€β”€ rand_chacha v0.3.1
β”‚       β”‚   β”œβ”€β”€ ppv-lite86 v0.2.21
β”‚       β”‚   β”‚   └── zerocopy v0.8.31
β”‚       β”‚   β”‚       └── zerocopy-derive v0.8.31 (proc-macro)
β”‚       β”‚   β”‚           β”œβ”€β”€ proc-macro2 v1.0.103
β”‚       β”‚   β”‚           β”‚   └── unicode-ident v1.0.22
β”‚       β”‚   β”‚           β”œβ”€β”€ quote v1.0.42
β”‚       β”‚   β”‚           β”‚   └── proc-macro2 v1.0.103 (*)
β”‚       β”‚   β”‚           └── syn v2.0.111
β”‚       β”‚   β”‚               β”œβ”€β”€ proc-macro2 v1.0.103 (*)
β”‚       β”‚   β”‚               β”œβ”€β”€ quote v1.0.42 (*)
β”‚       β”‚   β”‚               └── unicode-ident v1.0.22
β”‚       β”‚   └── rand_core v0.6.4
β”‚       └── rand_core v0.6.4
β”œβ”€β”€ crypto-primitives v0.1.0 (https://github.com/NethermindEth/crypto-primitives.git?rev=4d25cfd#4d25cfdd)
β”‚   β”œβ”€β”€ ark-ff v0.5.0
β”‚   β”‚   β”œβ”€β”€ ark-ff-asm v0.5.0 (proc-macro)
β”‚   β”‚   β”‚   β”œβ”€β”€ quote v1.0.42 (*)
β”‚   β”‚   β”‚   └── syn v2.0.111 (*)
β”‚   β”‚   β”œβ”€β”€ ark-ff-macros v0.5.0 (proc-macro)
β”‚   β”‚   β”‚   β”œβ”€β”€ num-bigint v0.4.6
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ num-integer v0.1.46
β”‚   β”‚   β”‚   β”‚   β”‚   └── num-traits v0.2.19
β”‚   β”‚   β”‚   β”‚   β”‚       [build-dependencies]
β”‚   β”‚   β”‚   β”‚   β”‚       └── autocfg v1.5.0
β”‚   β”‚   β”‚   β”‚   └── num-traits v0.2.19 (*)
β”‚   β”‚   β”‚   β”œβ”€β”€ num-traits v0.2.19 (*)
β”‚   β”‚   β”‚   β”œβ”€β”€ proc-macro2 v1.0.103 (*)
β”‚   β”‚   β”‚   β”œβ”€β”€ quote v1.0.42 (*)
β”‚   β”‚   β”‚   └── syn v2.0.111 (*)
β”‚   β”‚   β”œβ”€β”€ ark-serialize v0.5.0
β”‚   β”‚   β”‚   β”œβ”€β”€ ark-serialize-derive v0.5.0 (proc-macro)
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ proc-macro2 v1.0.103 (*)
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ quote v1.0.42 (*)
β”‚   β”‚   β”‚   β”‚   └── syn v2.0.111 (*)
β”‚   β”‚   β”‚   β”œβ”€β”€ ark-std v0.5.0 (*)
β”‚   β”‚   β”‚   β”œβ”€β”€ arrayvec v0.7.6
β”‚   β”‚   β”‚   β”œβ”€β”€ 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.7
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ generic-array v0.14.7 (*)
β”‚   β”‚   β”‚   β”‚       └── typenum v1.19.0
β”‚   β”‚   β”‚   └── num-bigint v0.4.6 (*)
β”‚   β”‚   β”œβ”€β”€ ark-std v0.5.0 (*)
β”‚   β”‚   β”œβ”€β”€ arrayvec v0.7.6
β”‚   β”‚   β”œβ”€β”€ digest v0.10.7 (*)
β”‚   β”‚   β”œβ”€β”€ educe v0.6.0 (proc-macro)
β”‚   β”‚   β”‚   β”œβ”€β”€ enum-ordinalize v4.3.2
β”‚   β”‚   β”‚   β”‚   └── enum-ordinalize-derive v4.3.2 (proc-macro)
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ proc-macro2 v1.0.103 (*)
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ quote v1.0.42 (*)
β”‚   β”‚   β”‚   β”‚       └── syn v2.0.111 (*)
β”‚   β”‚   β”‚   β”œβ”€β”€ proc-macro2 v1.0.103 (*)
β”‚   β”‚   β”‚   β”œβ”€β”€ quote v1.0.42 (*)
β”‚   β”‚   β”‚   └── syn v2.0.111 (*)
β”‚   β”‚   β”œβ”€β”€ itertools v0.13.0
β”‚   β”‚   β”‚   └── either v1.15.0
β”‚   β”‚   β”œβ”€β”€ num-bigint v0.4.6 (*)
β”‚   β”‚   β”œβ”€β”€ num-traits v0.2.19 (*)
β”‚   β”‚   β”œβ”€β”€ paste v1.0.15 (proc-macro)
β”‚   β”‚   └── zeroize v1.8.2
β”‚   β”‚       └── zeroize_derive v1.4.2 (proc-macro)
β”‚   β”‚           β”œβ”€β”€ proc-macro2 v1.0.103 (*)
β”‚   β”‚           β”œβ”€β”€ quote v1.0.42 (*)
β”‚   β”‚           └── syn v2.0.111 (*)
β”‚   β”œβ”€β”€ ark-std v0.5.0 (*)
β”‚   β”œβ”€β”€ crypto-bigint v0.6.1
β”‚   β”‚   β”œβ”€β”€ num-traits v0.2.19 (*)
β”‚   β”‚   β”œβ”€β”€ rand_core v0.6.4
β”‚   β”‚   β”œβ”€β”€ serdect v0.3.0
β”‚   β”‚   β”‚   β”œβ”€β”€ base16ct v0.2.0
β”‚   β”‚   β”‚   └── serde v1.0.228
β”‚   β”‚   β”‚       β”œβ”€β”€ serde_core v1.0.228
β”‚   β”‚   β”‚       └── serde_derive v1.0.228 (proc-macro)
β”‚   β”‚   β”‚           β”œβ”€β”€ proc-macro2 v1.0.103 (*)
β”‚   β”‚   β”‚           β”œβ”€β”€ quote v1.0.42 (*)
β”‚   β”‚   β”‚           └── syn v2.0.111 (*)
β”‚   β”‚   └── subtle v2.6.1
β”‚   β”œβ”€β”€ crypto-primitives-proc-macros v0.1.0 (proc-macro) (https://github.com/NethermindEth/crypto-primitives.git?rev=4d25cfd#4d25cfdd)
β”‚   β”‚   β”œβ”€β”€ proc-macro2 v1.0.103 (*)
β”‚   β”‚   β”œβ”€β”€ quote v1.0.42 (*)
β”‚   β”‚   └── syn v2.0.111 (*)
β”‚   β”œβ”€β”€ num-traits v0.2.19 (*)
β”‚   β”œβ”€β”€ pastey v0.2.1 (proc-macro)
β”‚   β”œβ”€β”€ rand v0.9.2
β”‚   β”‚   β”œβ”€β”€ rand_chacha v0.9.0
β”‚   β”‚   β”‚   β”œβ”€β”€ ppv-lite86 v0.2.21 (*)
β”‚   β”‚   β”‚   └── rand_core v0.9.3
β”‚   β”‚   β”‚       └── getrandom v0.3.4
β”‚   β”‚   β”‚           β”œβ”€β”€ cfg-if v1.0.4
β”‚   β”‚   β”‚           └── libc v0.2.178
β”‚   β”‚   └── rand_core v0.9.3 (*)
β”‚   β”œβ”€β”€ serde v1.0.228 (*)
β”‚   β”œβ”€β”€ thiserror v2.0.17
β”‚   β”‚   └── thiserror-impl v2.0.17 (proc-macro)
β”‚   β”‚       β”œβ”€β”€ proc-macro2 v1.0.103 (*)
β”‚   β”‚       β”œβ”€β”€ quote v1.0.42 (*)
β”‚   β”‚       └── syn v2.0.111 (*)
β”‚   └── zeroize v1.8.2 (*)
β”œβ”€β”€ num-traits v0.2.19 (*)
β”œβ”€β”€ thiserror v2.0.17 (*)
β”œβ”€β”€ zinc-poly v0.1.0 (/home/fs/code/zinc-plus/poly)
β”‚   β”œβ”€β”€ ark-std v0.5.0 (*)
β”‚   β”œβ”€β”€ crypto-bigint v0.7.0-rc.10
β”‚   β”‚   β”œβ”€β”€ num-traits v0.2.19 (*)
β”‚   β”‚   β”œβ”€β”€ rand_core v0.10.0-rc-3
β”‚   β”‚   β”œβ”€β”€ subtle v2.6.1
β”‚   β”‚   └── zeroize v1.8.2 (*)
β”‚   β”œβ”€β”€ crypto-primitives v0.1.0 (https://github.com/NethermindEth/crypto-primitives.git?rev=4d25cfd#4d25cfdd) (*)
β”‚   β”œβ”€β”€ displaydoc v0.2.5 (proc-macro)
β”‚   β”‚   β”œβ”€β”€ proc-macro2 v1.0.103 (*)
β”‚   β”‚   β”œβ”€β”€ quote v1.0.42 (*)
β”‚   β”‚   └── syn v2.0.111 (*)
β”‚   β”œβ”€β”€ itertools v0.14.0
β”‚   β”‚   └── either v1.15.0
β”‚   β”œβ”€β”€ num-traits v0.2.19 (*)
β”‚   β”œβ”€β”€ rand v0.9.2 (*)
β”‚   β”œβ”€β”€ rand_core v0.9.3 (*)
β”‚   β”œβ”€β”€ thiserror v2.0.17 (*)
β”‚   β”œβ”€β”€ zinc-transcript v0.1.0 (/home/fs/code/zinc-plus/transcript)
β”‚   β”‚   β”œβ”€β”€ crypto-bigint v0.7.0-rc.10 (*)
β”‚   β”‚   β”œβ”€β”€ crypto-primitives v0.1.0 (https://github.com/NethermindEth/crypto-primitives.git?rev=4d25cfd#4d25cfdd) (*)
β”‚   β”‚   β”œβ”€β”€ itertools v0.14.0 (*)
β”‚   β”‚   β”œβ”€β”€ num-traits v0.2.19 (*)
β”‚   β”‚   β”œβ”€β”€ sha3 v0.10.8
β”‚   β”‚   β”‚   β”œβ”€β”€ digest v0.10.7 (*)
β”‚   β”‚   β”‚   └── keccak v0.1.5
β”‚   β”‚   β”‚       └── cpufeatures v0.2.17
β”‚   β”‚   β”‚           └── libc v0.2.178
β”‚   β”‚   └── zinc-primality v0.1.0 (/home/fs/code/zinc-plus/primality)
β”‚   β”‚       β”œβ”€β”€ crypto-bigint v0.7.0-rc.10 (*)
β”‚   β”‚       β”œβ”€β”€ crypto-primes v0.7.0-pre.3
β”‚   β”‚       β”‚   β”œβ”€β”€ crypto-bigint v0.7.0-rc.10 (*)
β”‚   β”‚       β”‚   β”œβ”€β”€ libm v0.2.15
β”‚   β”‚       β”‚   └── rand_core v0.9.3 (*)
β”‚   β”‚       └── crypto-primitives v0.1.0 (https://github.com/NethermindEth/crypto-primitives.git?rev=4d25cfd#4d25cfdd) (*)
β”‚   └── zinc-utils v0.1.0 (/home/fs/code/zinc-plus/utils)
β”‚       β”œβ”€β”€ crypto-bigint v0.7.0-rc.10 (*)
β”‚       β”œβ”€β”€ crypto-primitives v0.1.0 (https://github.com/NethermindEth/crypto-primitives.git?rev=4d25cfd#4d25cfdd) (*)
β”‚       β”œβ”€β”€ num-traits v0.2.19 (*)
β”‚       └── thiserror v2.0.17 (*)
β”‚       [dev-dependencies]
β”‚       └── proptest v1.9.0
β”‚           β”œβ”€β”€ bit-set v0.8.0
β”‚           β”‚   └── bit-vec v0.8.0
β”‚           β”œβ”€β”€ bit-vec v0.8.0
β”‚           β”œβ”€β”€ bitflags v2.10.0
β”‚           β”œβ”€β”€ num-traits v0.2.19 (*)
β”‚           β”œβ”€β”€ rand v0.9.2 (*)
β”‚           β”œβ”€β”€ rand_chacha v0.9.0 (*)
β”‚           β”œβ”€β”€ rand_xorshift v0.4.0
β”‚           β”‚   └── rand_core v0.9.3 (*)
β”‚           β”œβ”€β”€ regex-syntax v0.8.8
β”‚           β”œβ”€β”€ rusty-fork v0.3.1
β”‚           β”‚   β”œβ”€β”€ fnv v1.0.7
β”‚           β”‚   β”œβ”€β”€ quick-error v1.2.3
β”‚           β”‚   β”œβ”€β”€ tempfile v3.24.0
β”‚           β”‚   β”‚   β”œβ”€β”€ fastrand v2.3.0
β”‚           β”‚   β”‚   β”œβ”€β”€ getrandom v0.3.4 (*)
β”‚           β”‚   β”‚   β”œβ”€β”€ once_cell v1.21.3
β”‚           β”‚   β”‚   └── rustix v1.1.3
β”‚           β”‚   β”‚       β”œβ”€β”€ bitflags v2.10.0
β”‚           β”‚   β”‚       └── linux-raw-sys v0.11.0
β”‚           β”‚   └── wait-timeout v0.2.1
β”‚           β”‚       └── libc v0.2.178
β”‚           β”œβ”€β”€ tempfile v3.24.0 (*)
β”‚           └── unarray v0.1.4
β”‚   [dev-dependencies]
β”‚   β”œβ”€β”€ criterion v0.7.0
β”‚   β”‚   β”œβ”€β”€ anes v0.1.6
β”‚   β”‚   β”œβ”€β”€ cast v0.3.0
β”‚   β”‚   β”œβ”€β”€ ciborium v0.2.2
β”‚   β”‚   β”‚   β”œβ”€β”€ ciborium-io v0.2.2
β”‚   β”‚   β”‚   β”œβ”€β”€ ciborium-ll v0.2.2
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ciborium-io v0.2.2
β”‚   β”‚   β”‚   β”‚   └── half v2.7.1
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ cfg-if v1.0.4
β”‚   β”‚   β”‚   β”‚       └── zerocopy v0.8.31 (*)
β”‚   β”‚   β”‚   └── serde v1.0.228 (*)
β”‚   β”‚   β”œβ”€β”€ clap v4.5.53
β”‚   β”‚   β”‚   └── clap_builder v4.5.53
β”‚   β”‚   β”‚       β”œβ”€β”€ anstyle v1.0.13
β”‚   β”‚   β”‚       └── clap_lex v0.7.6
β”‚   β”‚   β”œβ”€β”€ criterion-plot v0.6.0
β”‚   β”‚   β”‚   β”œβ”€β”€ cast v0.3.0
β”‚   β”‚   β”‚   └── itertools v0.13.0 (*)
β”‚   β”‚   β”œβ”€β”€ itertools v0.13.0 (*)
β”‚   β”‚   β”œβ”€β”€ num-traits v0.2.19 (*)
β”‚   β”‚   β”œβ”€β”€ oorandom v11.1.5
β”‚   β”‚   β”œβ”€β”€ plotters v0.3.7
β”‚   β”‚   β”‚   β”œβ”€β”€ num-traits v0.2.19 (*)
β”‚   β”‚   β”‚   β”œβ”€β”€ plotters-backend v0.3.7
β”‚   β”‚   β”‚   └── plotters-svg v0.3.7
β”‚   β”‚   β”‚       └── plotters-backend v0.3.7
β”‚   β”‚   β”œβ”€β”€ rayon v1.11.0
β”‚   β”‚   β”‚   β”œβ”€β”€ either v1.15.0
β”‚   β”‚   β”‚   └── rayon-core v1.13.0
β”‚   β”‚   β”‚       β”œβ”€β”€ crossbeam-deque v0.8.6
β”‚   β”‚   β”‚       β”‚   β”œβ”€β”€ crossbeam-epoch v0.9.18
β”‚   β”‚   β”‚       β”‚   β”‚   └── crossbeam-utils v0.8.21
β”‚   β”‚   β”‚       β”‚   └── crossbeam-utils v0.8.21
β”‚   β”‚   β”‚       └── crossbeam-utils v0.8.21
β”‚   β”‚   β”œβ”€β”€ regex v1.12.2
β”‚   β”‚   β”‚   β”œβ”€β”€ regex-automata v0.4.13
β”‚   β”‚   β”‚   β”‚   └── regex-syntax v0.8.8
β”‚   β”‚   β”‚   └── regex-syntax v0.8.8
β”‚   β”‚   β”œβ”€β”€ serde v1.0.228 (*)
β”‚   β”‚   β”œβ”€β”€ serde_json v1.0.147
β”‚   β”‚   β”‚   β”œβ”€β”€ itoa v1.0.16
β”‚   β”‚   β”‚   β”œβ”€β”€ memchr v2.7.6
β”‚   β”‚   β”‚   β”œβ”€β”€ serde_core v1.0.228
β”‚   β”‚   β”‚   └── zmij v0.1.8
β”‚   β”‚   β”œβ”€β”€ tinytemplate v1.2.1
β”‚   β”‚   β”‚   β”œβ”€β”€ serde v1.0.228 (*)
β”‚   β”‚   β”‚   └── serde_json v1.0.147 (*)
β”‚   β”‚   └── walkdir v2.5.0
β”‚   β”‚       └── same-file v1.0.6
β”‚   └── proptest v1.9.0 (*)
β”œβ”€β”€ zinc-transcript v0.1.0 (/home/fs/code/zinc-plus/transcript) (*)
└── zinc-utils v0.1.0 (/home/fs/code/zinc-plus/utils) (*)
[dev-dependencies]
β”œβ”€β”€ crypto-bigint v0.7.0-rc.10 (*)
β”œβ”€β”€ itertools v0.14.0 (*)
└── rand v0.9.2 (*)

zinc-poly v0.1.0 (/home/fs/code/zinc-plus/poly) (*)

zinc-primality v0.1.0 (/home/fs/code/zinc-plus/primality) (*)

zinc-transcript v0.1.0 (/home/fs/code/zinc-plus/transcript) (*)

zinc-utils v0.1.0 (/home/fs/code/zinc-plus/utils) (*)

zip-plus v0.1.0 (/home/fs/code/zinc-plus/zip-plus)
β”œβ”€β”€ ark-ff v0.5.0 (*)
β”œβ”€β”€ ark-poly v0.5.0
β”‚   β”œβ”€β”€ ahash v0.8.12
β”‚   β”‚   β”œβ”€β”€ cfg-if v1.0.4
β”‚   β”‚   β”œβ”€β”€ once_cell v1.21.3
β”‚   β”‚   └── zerocopy v0.8.31 (*)
β”‚   β”‚   [build-dependencies]
β”‚   β”‚   └── version_check v0.9.5
β”‚   β”œβ”€β”€ ark-ff v0.5.0 (*)
β”‚   β”œβ”€β”€ ark-serialize v0.5.0 (*)
β”‚   β”œβ”€β”€ ark-std v0.5.0 (*)
β”‚   β”œβ”€β”€ educe v0.6.0 (proc-macro) (*)
β”‚   └── hashbrown v0.15.5
β”‚       └── allocator-api2 v0.2.21
β”œβ”€β”€ ark-std v0.5.0 (*)
β”œβ”€β”€ blake3 v1.8.2
β”‚   β”œβ”€β”€ arrayref v0.3.9
β”‚   β”œβ”€β”€ arrayvec v0.7.6
β”‚   β”œβ”€β”€ cfg-if v1.0.4
β”‚   └── constant_time_eq v0.3.1
β”‚   [build-dependencies]
β”‚   └── cc v1.2.50
β”‚       β”œβ”€β”€ find-msvc-tools v0.1.5
β”‚       └── shlex v1.3.0
β”œβ”€β”€ crypto-bigint v0.7.0-rc.10 (*)
β”œβ”€β”€ crypto-primitives v0.1.0 (https://github.com/NethermindEth/crypto-primitives.git?rev=4d25cfd#4d25cfdd) (*)
β”œβ”€β”€ itertools v0.14.0 (*)
β”œβ”€β”€ num-traits v0.2.19 (*)
β”œβ”€β”€ rand v0.9.2 (*)
β”œβ”€β”€ rand_core v0.9.3 (*)
β”œβ”€β”€ thiserror v2.0.17 (*)
β”œβ”€β”€ uninit v0.6.2
β”œβ”€β”€ zinc-poly v0.1.0 (/home/fs/code/zinc-plus/poly) (*)
β”œβ”€β”€ zinc-primality v0.1.0 (/home/fs/code/zinc-plus/primality) (*)
β”œβ”€β”€ zinc-transcript v0.1.0 (/home/fs/code/zinc-plus/transcript) (*)
└── zinc-utils v0.1.0 (/home/fs/code/zinc-plus/utils) (*)
[dev-dependencies]
β”œβ”€β”€ criterion v0.7.0 (*)
└── proptest v1.9.0 (

This crypto-primitives is the library in question

Interesting. Maybe try cargo cleaning your project? I've never seen a <= dependency declaration with pre-releases, but I can't imagine Cargo treating 0.6.1 to be compatible with a <= 0.7.0-rc.9 declaration.

1 Like

AFAIK <= 0.7.0-rc.9 will be considered compatible with all versions up to 0.7.0-rc.9 irrespective of major or minor version. Try >= 0.7.0-rc.0, <= 0.7.0-rc.9.

3 Likes

Yeah, it does make sense that 0.6.1 is compatible with <= 0.7.0-rc.9, and I should've declared it as >= 0.7.0-rc.0, <= 0.7.0-rc.9 to begin with (since my code is not compatible with 0.6)
I'm still curious why Cargo chooses 0.6.1 for <= 0.7.0-rc.9 bound though, given that it picks 0.7.0-rc.9 when compiling the library standalone. cargo clean does not change this.
Is there a way to trace the logic of picking a certain version?

The resolver is coarsely documented here:

and the entry point of the source code of the resolver can be found here:

The resolver is a terribly complex peace of logic though. My guess as to why 0.6.1 was chosen would be because Cargo de-duplicated dependencies or because 0.7.0-rc.9 and 0.7.0-rc.10 (the latter being used by some other dependencies of yours) are unresolvable together.

1 Like

Thank you so much for this insight!