How to unify the version used through vendored crates?

Consider the following cargo tree output:

myproj v0.1.0 (Z:\repos\myproj)
├── win32job v2.0.0
│   ├── thiserror v1.0.58
│   │   └── thiserror-impl v1.0.58 (proc-macro)
│   │       ├── proc-macro2 v1.0.81
│   │       │   └── unicode-ident v1.0.12
│   │       ├── quote v1.0.36
│   │       │   └── proc-macro2 v1.0.81 (*)
│   │       └── syn v2.0.59
│   │           ├── proc-macro2 v1.0.81 (*)
│   │           ├── quote v1.0.36 (*)
│   │           └── unicode-ident v1.0.12
│   └── windows v0.52.0
│       ├── windows-core v0.52.0
│       │   └── windows-targets v0.52.5
│       │       └── windows_x86_64_msvc v0.52.5
│       └── windows-targets v0.52.5 (*)
└── windows v0.56.0
    ├── windows-core v0.56.0
    │   ├── windows-implement v0.56.0 (proc-macro)
    │   │   ├── proc-macro2 v1.0.81 (*)
    │   │   ├── quote v1.0.36 (*)
    │   │   └── syn v2.0.59 (*)
    │   ├── windows-interface v0.56.0 (proc-macro)
    │   │   ├── proc-macro2 v1.0.81 (*)
    │   │   ├── quote v1.0.36 (*)
    │   │   └── syn v2.0.59 (*)
    │   ├── windows-result v0.1.1
    │   │   └── windows-targets v0.52.5 (*)
    │   └── windows-targets v0.52.5 (*)
    └── windows-targets v0.52.5 (*)

As you can see win32job requires windows but has pegged it to version 0.52. I went with version = "*" for the direct dependency.

After reading this, I thought I'd give the [patch] section a try and added the following in my .cargo/config.toml (local to the project):

[patch.crates-io.windows]
version = "*"

Most subsequent cargo invocations will then, however, give me an error such as this:

$ cargo tree
error: failed to resolve patches for `https://github.com/rust-lang/crates.io-index`

Caused by:
  patch for `windows` in `https://github.com/rust-lang/crates.io-index` points to the same source, but patches must point to different sources

This appears to make sense (see full .cargo/config.toml below), but on the other hand it raises the question how to override the version key for a transient dependency in such a scenario.

Does anyone know?

PS: my full .cargo/config.toml looks like this, because I am using cargo vendor:

[source.crates-io]
replace-with = "vendored-sources"

[source.vendored-sources]
directory = "vendor"

[patch.crates-io.windows]
version = "*"

You should never use "*" version requirements for non-throwaway code, because it allows cargo update to give you breaking changes. It's a good way to end up with “this code doesn't work any more and I can't figure out why”. Even if you need to ensure there is a single version, it's usually better to use a specific version, get an explicit type mismatch or linker error, and fix that.

This doesn't mean anything useful, because the version key in [patch] does not mean “use this version instead”, it means “I want to patch this version” (in case of there being multiple major versions already). Cargo is giving you an error because patches need to specify a replacement package source to do anything useful, but you haven't.

You cannot use [patch] to weaken an existing package's version requirement; you can only use it to replace the source code with different source code (and the replacement must have a compatible version number). That is, [patch] is for going from 0.52.0 to 0.52.0-mycustompatches, not 0.52.0 to 0.56.0.

The only way to cause win32job to use windows 0.56.0 is to fork it, change its [dependencies], then use [patch] (or a git or path dependency) to point at your fork. (Or send a PR upstream, of course.)

2 Likes

I get that point, but right here and right now I wanted both simply to end up using the exact same crate version (in order to vendor only one of them), which is why I opted for "*". Also, I think the problem you mentioned (and I am aware) is manageable as long as Cargo.lock comes committed and instructions state to use cargo ... --locked.

Still, I appreciate the reminder.

Alright, thanks. This was something I thought of doing first, but hoped that I'd be able to get away with [patch] somehow.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.