rust-lang / cargo

The Rust package manager
https://doc.rust-lang.org/cargo
Apache License 2.0
12.81k stars 2.43k forks source link

Patching an indirect dependency with `package = "xxx"` renaming #13734

Open billy1624 opened 7 months ago

billy1624 commented 7 months ago

Problem

Context

We have three crates:

Where client depends on child and child depends on parent.

We want to patch (overriding) the parent used by child.

First Try: with package renaming

Here, we would use the patch syntax in client/Cargo.toml:

[patch.'https://github.com/billy1624/test-cargo-patch.git'] 
parent = { path = "../parent-x", package = "parent-x" } 

https://github.com/billy1624/test-cargo-patch/blob/2257248f866c8bd9efcc635b33075cb66f89fd93/client/Cargo.toml#L1-L17

Overriding parent with parent-x. The parent-x is being renamed as parent as follows:

Checkout the branch.

$ cd client

$ cargo b
   Compiling child v0.1.0 (https://github.com/billy1624/test-cargo-patch.git#12ec7298)
error[E0061]: this function takes 1 argument but 0 arguments were supplied
 --> /Users/billy/.cargo/git/checkouts/test-cargo-patch-ae21da568fb3f50c/12ec729/child/src/lib.rs:2:5
  |
2 |     parent::func();
  |     ^^^^^^^^^^^^-- an argument of type `String` is missing
  |
note: function defined here
 --> /Users/billy/.cargo/git/checkouts/test-cargo-patch-ae21da568fb3f50c/12ec729/parent/src/lib.rs:1:8
  |
1 | pub fn func(_: String) -> &'static str {
  |        ^^^^
help: provide the argument
  |
2 |     parent::func(/* String */);
  |                 ~~~~~~~~~~~~~~

For more information about this error, try `rustc --explain E0061`.
error: could not compile `child` (lib) due to 1 previous error

$ cargo tree
client v0.1.0 (/Users/billy/Projects/test-cargo-patch/client)
├── child v0.1.0 (https://github.com/billy1624/test-cargo-patch.git#12ec7298)
│   └── parent v0.1.0 (https://github.com/billy1624/test-cargo-patch.git#12ec7298)
└── parent-x v0.1.0 (/Users/billy/Projects/test-cargo-patch/parent-x)

From the result of cargo build and cargo tree, we saw that it did NOT patch (override) the parent dependency that's used in child.

Second Try: without package renaming

Overriding parent with parent-x. The package in parent-x is being named as parent, without any renaming:

https://github.com/billy1624/test-cargo-patch/blob/18d4e28b039b851e8ab18cf2749b8700f7d91935/client/Cargo.toml#L1-L17

https://github.com/billy1624/test-cargo-patch/blob/18d4e28b039b851e8ab18cf2749b8700f7d91935/parent-x/Cargo.toml#L1-L12

Checkout the branch.

$ cd client

❯ cargo b
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s

❯ cargo tree
client v0.1.0 (/Users/billy/Projects/test-cargo-patch/client)
├── child v0.1.0 (https://github.com/billy1624/test-cargo-patch.git#12ec7298)
│   └── parent v0.1.0 (/Users/billy/Projects/test-cargo-patch/parent-x)
└── parent v0.1.0 (/Users/billy/Projects/test-cargo-patch/parent-x)

Here, we successfully patch (override) the parent dependency that's used in child.

Questions

Steps

No response

Possible Solution(s)

No response

Notes

No response

Version

No response

weihanglo commented 7 months ago

[patch] only looks at the canonical package name, i.e. value specified in package.name, when patching a package. Dependency renaming is not considered and only useful for resolving conflicts due to the limitation of the TOML format. See "Using [patch] with multiple versions".

You could look closer at the output of cargo tree. The first one didn't work because you were patching parent-x from a Git source, however non-existent in the dependency tree. The second one worked because it certainly patched parent since the package.name is now parent for the package under parent-x directory.