Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On trait bound mismatch, detect multiple crate versions in dep tree #124944

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

estebank
Copy link
Contributor

@estebank estebank commented May 9, 2024

When encountering an E0277, if the type and the trait both come from a crate with the same name but different crate number, we explain that there are multiple crate versions in the dependency tree.

If there's a type that fulfills the bound, and it has the same name as the passed in type and has the same crate name, we explain that the same type in two different versions of the same crate are different.

error[E0277]: the trait bound `Type: dependency::Trait` is not satisfied
 --> src/main.rs:4:18
  |
4 |     do_something(Type);
  |     ------------ ^^^^ the trait `dependency::Trait` is not implemented for `Type`
  |     |
  |     required by a bound introduced by this call
  |
help: you have multiple different versions of crate `dependency` in your dependency graph
 --> src/main.rs:1:5
  |
1 | use bar::do_something;
  |     ^^^ one version of crate `dependency` is used here, as a dependency of crate `bar`
2 | use dependency::Type;
  |     ^^^^^^^^^^ one version of crate `dependency` is used here, as a direct dependency of the current crate
note: two types coming from two different versions of the same crate are different types even if they look the same
 --> /home/gh-estebank/crate_versions/baz-2/src/lib.rs:1:1
  |
1 | pub struct Type;
  | ^^^^^^^^^^^^^^^ this type doesn't implement the required trait
  |
 ::: /home/gh-estebank/crate_versions/baz/src/lib.rs:1:1
  |
1 | pub struct Type;
  | ^^^^^^^^^^^^^^^ this type implements the required trait
2 | pub trait Trait {}
  | --------------- this is the required trait
note: required by a bound in `bar::do_something`
 --> /home/gh-estebank/crate_versions/baz/src/lib.rs:4:24
  |
4 | pub fn do_something<X: Trait>(_: X) {}
  |                        ^^^^^ required by this bound in `do_something`

Address #22750.

When encountering an E0277, if the type and the trait both come from a crate with the same name but different crate number, we explain that there are multiple crate versions in the dependency tree.

If there's a type that fulfills the bound, and it has the same name as the passed in type and has the same crate name, we explain that the same type in two different versions of the same crate *are different*.

```
error[E0277]: the trait bound `Type: dependency::Trait` is not satisfied
 --> src/main.rs:4:18
  |
4 |     do_something(Type);
  |     ------------ ^^^^ the trait `dependency::Trait` is not implemented for `Type`
  |     |
  |     required by a bound introduced by this call
  |
help: you have multiple different versions of crate `dependency` in your dependency graph
 --> src/main.rs:1:5
  |
1 | use bar::do_something;
  |     ^^^ one version of crate `dependency` is used here, as a dependency of crate `bar`
2 | use dependency::Type;
  |     ^^^^^^^^^^ one version of crate `dependency` is used here, as a direct dependency of the current crate
note: two types coming from two different versions of the same crate are different types even if they look the same
 --> /home/gh-estebank/crate_versions/baz-2/src/lib.rs:1:1
  |
1 | pub struct Type;
  | ^^^^^^^^^^^^^^^ this type doesn't implement the required trait
  |
 ::: /home/gh-estebank/crate_versions/baz/src/lib.rs:1:1
  |
1 | pub struct Type;
  | ^^^^^^^^^^^^^^^ this type implements the required trait
2 | pub trait Trait {}
  | --------------- this is the required trait
note: required by a bound in `bar::do_something`
 --> /home/gh-estebank/crate_versions/baz/src/lib.rs:4:24
  |
4 | pub fn do_something<X: Trait>(_: X) {}
  |                        ^^^^^ required by this bound in `do_something`
```

Address rust-lang#22750.
@rustbot
Copy link
Collaborator

rustbot commented May 9, 2024

r? @fee1-dead

rustbot has assigned @fee1-dead.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 9, 2024
Copy link
Member

@fee1-dead fee1-dead left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! It would be nice if we could add a test for this though. Maybe run-make?

@weiznich
Copy link
Contributor

This new error message looks great ❤️

I think it would even be more helpful if it would point the user to use cargo tree as debugging tool for finding the sources of the duplicated crates in their dependency tree. From my experience from helping users with such issues they are often not aware that they have several versions of the same crate in their dependency tree. Sometimes the even question that this might be the issue. This is almost always resolved by pointing them to cargo tree -p $crate -i, although that command will likely not work out of the box as it requires specifying the version of $crate if it appears in different versions in your dependency tree. By default cargo tree will print a error message that contains the different versions that occur in your tree, so the user has at least a starting point from there.

Something else I noticed with this error message is that it only describes what's the problem, but it does not really mention how to resolve it. Maybe include something that essentially says: Try to restructure your dependency tree in such way that this uses the same version of that crate here?

@estebank
Copy link
Contributor Author

@weiznich added a note about cargo tree, but it gets somewhat lost in the noise :-/

@estebank
Copy link
Contributor Author

@fee1-dead added test

@fee1-dead
Copy link
Member

Looks great! Thanks for working on this!

@bors
Copy link
Contributor

bors commented May 13, 2024

📌 Commit 782cba8 has been approved by fee1-dead

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 13, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request May 13, 2024
…fee1-dead

On trait bound mismatch, detect multiple crate versions in dep tree

When encountering an E0277, if the type and the trait both come from a crate with the same name but different crate number, we explain that there are multiple crate versions in the dependency tree.

If there's a type that fulfills the bound, and it has the same name as the passed in type and has the same crate name, we explain that the same type in two different versions of the same crate *are different*.

```
error[E0277]: the trait bound `Type: dependency::Trait` is not satisfied
 --> src/main.rs:4:18
  |
4 |     do_something(Type);
  |     ------------ ^^^^ the trait `dependency::Trait` is not implemented for `Type`
  |     |
  |     required by a bound introduced by this call
  |
help: you have multiple different versions of crate `dependency` in your dependency graph
 --> src/main.rs:1:5
  |
1 | use bar::do_something;
  |     ^^^ one version of crate `dependency` is used here, as a dependency of crate `bar`
2 | use dependency::Type;
  |     ^^^^^^^^^^ one version of crate `dependency` is used here, as a direct dependency of the current crate
note: two types coming from two different versions of the same crate are different types even if they look the same
 --> /home/gh-estebank/crate_versions/baz-2/src/lib.rs:1:1
  |
1 | pub struct Type;
  | ^^^^^^^^^^^^^^^ this type doesn't implement the required trait
  |
 ::: /home/gh-estebank/crate_versions/baz/src/lib.rs:1:1
  |
1 | pub struct Type;
  | ^^^^^^^^^^^^^^^ this type implements the required trait
2 | pub trait Trait {}
  | --------------- this is the required trait
note: required by a bound in `bar::do_something`
 --> /home/gh-estebank/crate_versions/baz/src/lib.rs:4:24
  |
4 | pub fn do_something<X: Trait>(_: X) {}
  |                        ^^^^^ required by this bound in `do_something`
```

Address rust-lang#22750.
@bors
Copy link
Contributor

bors commented May 13, 2024

⌛ Testing commit 782cba8 with merge 3a9190b...

@rust-log-analyzer
Copy link
Collaborator

The job test-various failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)

---- [ui] tests/ui/crate-loading/multiple-dep-versions.rs stdout ----
diff of svg:

- <svg width="1054px" height="704px" xmlns="http://www.w3.org/2000/svg">
2   <style>
3     .fg { fill: #AAAAAA }
4     .bg { background: #000000 }

5     .fg-ansi256-009 { fill: #FF5555 }
-     .fg-ansi256-010 { fill: #55FF55 }
7     .fg-ansi256-012 { fill: #5555FF }
-     .fg-ansi256-014 { fill: #55FFFF }
-     .fg-magenta { fill: #AA00AA }
10     .container {
11       padding: 0 10px;
12       line-height: 18px;

22   <rect width="100%" height="100%" y="0" rx="4.5" class="bg" />
23 
24   <text xml:space="preserve" class="container fg">
-     <tspan x="10px" y="28px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: the trait bound `Type: dependency::Trait` is not satisfied</tspan>
26 </tspan>
-     <tspan x="10px" y="46px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/multiple-dep-versions.rs:13:18</tspan>
28 </tspan>
29     <tspan x="10px" y="64px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
30 </tspan>

-     <tspan x="10px" y="82px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     do_something(Type);</tspan>
32 </tspan>
-     <tspan x="10px" y="100px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">------------</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">the trait `dependency::Trait` is not implemented for `Type`</tspan>
34 </tspan>
-     <tspan x="10px" y="118px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
36 </tspan>
-     <tspan x="10px" y="136px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">required by a bound introduced by this call</tspan>
38 </tspan>
-     <tspan x="10px" y="154px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
40 </tspan>
-     <tspan x="10px" y="172px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: you have </tspan><tspan class="fg-magenta bold">multiple different versions</tspan><tspan> of crate `</tspan><tspan class="fg-magenta bold">dependency</tspan><tspan>` in your dependency graph</tspan>
42 </tspan>
-     <tspan x="10px" y="190px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/multiple-dep-versions.rs:7:1</tspan>
44 </tspan>
-     <tspan x="10px" y="208px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
46 </tspan>
-     <tspan x="10px" y="226px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> extern crate dependency;</tspan>
48 </tspan>
-     <tspan x="10px" y="244px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">^^^^^^^^^^^^^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">one version of crate `dependency` is used here, as a direct dependency of the current crate</tspan>
50 </tspan>
-     <tspan x="10px" y="262px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> extern crate dep_2_reexport;</tspan>
52 </tspan>
-     <tspan x="10px" y="280px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">^^^^^^^^^^^^^^^^^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">one version of crate `dependency` is used here, as a dependency of crate `dep_2_reexport`</tspan>
54 </tspan>
-     <tspan x="10px" y="298px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: two types coming from two different versions of the same crate are different types </tspan><tspan class="fg-magenta bold">even if they look the same</tspan>
56 </tspan>
-     <tspan x="10px" y="316px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/auxiliary/multiple-dep-versions-1.rs:4:1</tspan>
58 </tspan>
-     <tspan x="10px" y="334px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
60 </tspan>
-     <tspan x="10px" y="352px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> pub struct Type;</tspan>
62 </tspan>
-     <tspan x="10px" y="370px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-010 bold">^^^^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-010 bold">this type doesn't implement the required trait</tspan>
64 </tspan>
-     <tspan x="10px" y="388px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
66 </tspan>
-     <tspan x="10px" y="406px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">::: </tspan><tspan>$DIR/auxiliary/multiple-dep-versions-2.rs:4:1</tspan>
68 </tspan>
-     <tspan x="10px" y="424px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
70 </tspan>
-     <tspan x="10px" y="442px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> pub struct Type(pub i32);</tspan>
72 </tspan>
-     <tspan x="10px" y="460px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-010 bold">^^^^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-010 bold">this type implements the required trait</tspan>
74 </tspan>
-     <tspan x="10px" y="478px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> pub trait Trait {}</tspan>
76 </tspan>
-     <tspan x="10px" y="496px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is the required trait</tspan>
78 </tspan>
-     <tspan x="10px" y="514px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: you can use `cargo tree` to explore your dependency tree</tspan>
80 </tspan>
-     <tspan x="10px" y="532px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `dep_2_reexport::do_something`</tspan>
82 </tspan>
-     <tspan x="10px" y="550px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/auxiliary/multiple-dep-versions-2.rs:7:24</tspan>
84 </tspan>
-     <tspan x="10px" y="568px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
86 </tspan>
-     <tspan x="10px" y="586px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> pub fn do_something&lt;X: Trait&gt;(_: X) {}</tspan>
88 </tspan>
-     <tspan x="10px" y="604px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                        </tspan><tspan class="fg-ansi256-010 bold">^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-010 bold">required by this bound in `do_something`</tspan>
90 </tspan>
-     <tspan x="10px" y="622px">
92 </tspan>
-     <tspan x="10px" y="640px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 1 previous error</tspan>
94 </tspan>
-     <tspan x="10px" y="658px">
96 </tspan>
-     <tspan x="10px" y="676px"><tspan class="bold">For more information about this error, try `rustc --explain E0277`.</tspan>
98 </tspan>
-     <tspan x="10px" y="694px">
100 </tspan>
101   </text>



The actual svg differed from the expected svg.
Actual svg saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/crate-loading/multiple-dep-versions/multiple-dep-versions.svg
To only update this specific test, also pass `--test-args crate-loading/multiple-dep-versions.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/crate-loading/multiple-dep-versions.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=wasm32-wasip1" "--check-cfg" "cfg(FALSE)" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/crate-loading/multiple-dep-versions" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/wasm32-wasip1/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/crate-loading/multiple-dep-versions/auxiliary" "--edition=2021" "--error-format=human" "--color=always" "--crate-type" "bin" "--extern" "dependency=/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/crate-loading/multiple-dep-versions/auxiliary/libdependency-1.so" "--extern" "dep_2_reexport=/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/crate-loading/multiple-dep-versions/auxiliary/libdep_2_reexport.so"
--- stderr -------------------------------
--- stderr -------------------------------
error: extern location for dependency does not exist: /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/crate-loading/multiple-dep-versions/auxiliary/libdependency-1.so
  --> /checkout/tests/ui/crate-loading/multiple-dep-versions.rs:7:1
LL | extern crate dependency;
   | ^^^^^^^^^^^^^^^^^^^^^^^^


error: extern location for dep_2_reexport does not exist: /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/crate-loading/multiple-dep-versions/auxiliary/libdep_2_reexport.so
  --> /checkout/tests/ui/crate-loading/multiple-dep-versions.rs:8:1
LL | extern crate dep_2_reexport;
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

@bors
Copy link
Contributor

bors commented May 13, 2024

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 13, 2024
@estebank
Copy link
Contributor Author

Need to fix the tests, clearly they worked because of dirty environment only. I'll fix them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants