How do I pin indirect dependencies of a crate?

Manual editing

You can check out Iron, modify Cargo.toml to specify versions (as you have already done). Then you repeat the process, checking out url, modifying its Cargo.toml, then make sure you are using your version of url in Iron’s Cargo.toml. Rinse and repeat.

Patch overrides

From the Cargo docs:

The [patch] section of Cargo.toml can be used to override dependencies with other copies. The syntax is similar to the [dependencies] section:

[patch.crates-io]
foo = { git="https://github.com/example/foo" }
bar = { path="my/local/bar" }

Sources can be patched with versions of crates that do not exist, and they can also be patched with versions of crates that already exist. If a source is patched with a crate version that already exists in the source, then the source’s original crate is replaced.

Path overrides

From the Cargo docs:

Sometimes you’re only temporarily working on a crate and you don’t want to have to modify Cargo.toml like with the [patch] section above. For this use case Cargo offers a much more limited version of overrides called path overrides.

Path overrides are specified through .cargo/config.toml instead of Cargo.toml. Inside of .cargo/config.toml you’ll specify a key called paths:

paths = ["/path/to/uuid"]

Specific versions

You might be able to simply specify versions (or SHA hashes) for each dependency that you know works with your Rust version. Cargo should be able to resolve the transitive dependencies and lock you to a previous version if there is one that fits all the requirements.

Alternatively, you can use cargo update -p somecrate --precise major.minor.patch to specify the exact version of a crate and record it in your Cargo.lock.

This may not work in all cases; Rust can have multiple versions of the same library compiled into one binary. That would mean that there’s no one place you can specify a version that applies all over.

Addressing the bounty

John adds:

I have a crate that depends on zstd. zstd depends on zstd-safe. zstd-safe depends on zstd-sys. My crate gets linked into a C++ binary that also links zstd as a C library. The versions of the zstd C library and the zstd vendored by zstd-sys must match exactly, or I get link errors. So I want to pin an exact version of zstd-sys

This case can follow the “specific versions” example above, but because zstd-sys uses a links key, there can only ever be exactly one of that crate in the entire crate graph. That means you can add zstd-sys to your top-level dependencies and feel comfortable that Cargo will complain if a conflicting version is introduced:

[dependencies]
zstd = "0.9.0"
zstd-sys = "=1.6.1"

If I edit this to specify version 1.6.0, I get an error:

error: failed to select a version for `zstd-sys`.
    ... required by package `zstd-safe v4.1.1+zstd.1.5.0`
    ... which is depended on by `zstd v0.9.0+zstd.1.5.0`
    ... which is depended on by `so v0.1.0 (/private/tmp/so)`
versions that meet the requirements `=1.6.1` are: 1.6.1+zstd.1.5.0

the package `zstd-sys` links to the native library `zstd`, but it conflicts with a previous package which links to `zstd` as well:
package `zstd-sys v1.6.0+zstd.1.5.0`
    ... which is depended on by `so v0.1.0 (/private/tmp/so)`

Leave a Comment