Skip to content

Commit 30c2ed2

Browse files
authored
Rollup merge of rust-lang#133585 - estebank:issue-133563, r=jieyouxu
Do not call `extern_crate` on current trait on crate mismatch errors When we encounter an error caused by traits/types of different versions of the same crate, filter out the current crate when collecting spans to add to the context so we don't call `extern_crate` on the `DefId` of the current crate, which is meaningless and ICEs. Produced output with this filter: ``` error[E0277]: the trait bound `foo::Struct: Trait` is not satisfied --> y.rs:13:19 | 13 | check_trait::<foo::Struct>(); | ^^^^^^^^^^^ the trait `Trait` is not implemented for `foo::Struct` | note: there are multiple different versions of crate `foo` in the dependency graph --> y.rs:7:1 | 4 | extern crate foo; | ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate 5 | 6 | pub struct Struct; | ----------------- this type implements the required trait 7 | pub trait Trait {} | ^^^^^^^^^^^^^^^ this is the required trait | ::: x.rs:4:1 | 4 | pub struct Struct; | ----------------- this type doesn't implement the required trait 5 | pub trait Trait {} | --------------- this is the found trait = note: two types coming from two different versions of the same crate are different types even if they look the same = help: you can use `cargo tree` to explore your dependency tree note: required by a bound in `check_trait` --> y.rs:10:19 | 10 | fn check_trait<T: Trait>() {} | ^^^^^ required by this bound in `check_trait` ``` Fix rust-lang#133563.
2 parents 0f225bd + 998ff2f commit 30c2ed2

File tree

8 files changed

+241
-76
lines changed

8 files changed

+241
-76
lines changed

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17311731
span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait");
17321732
for (sp, label) in [trait_def_id, other_trait_def_id]
17331733
.iter()
1734+
// The current crate-version might depend on another version of the same crate
1735+
// (Think "semver-trick"). Do not call `extern_crate` in that case for the local
1736+
// crate as that doesn't make sense and ICEs (#133563).
1737+
.filter(|def_id| !def_id.is_local())
17341738
.filter_map(|def_id| self.tcx.extern_crate(def_id.krate))
17351739
.map(|data| {
17361740
let dependency = if data.dependency_of == LOCAL_CRATE {

src/tools/run-make-support/src/external_deps/rustc.rs

+6
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,12 @@ impl Rustc {
227227
self
228228
}
229229

230+
/// Normalize the line number in the stderr output
231+
pub fn ui_testing(&mut self) -> &mut Self {
232+
self.cmd.arg(format!("-Zui-testing"));
233+
self
234+
}
235+
230236
/// Specify the target triple, or a path to a custom target json spec file.
231237
pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
232238
let target = target.as_ref();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![crate_type = "lib"]
2+
#![crate_name = "foo"]
3+
4+
extern crate foo;
5+
6+
pub struct Struct;
7+
pub trait Trait {}
8+
impl Trait for Struct {}
9+
10+
fn check_trait<T: Trait>() {}
11+
12+
fn ice() {
13+
check_trait::<foo::Struct>();
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![crate_type = "lib"]
2+
#![crate_name = "foo"]
3+
4+
pub struct Struct;
5+
pub trait Trait {}
6+
impl Trait for Struct {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
error[E0277]: the trait bound `foo::Struct: Trait` is not satisfied
2+
--> foo-current.rs:13:19
3+
|
4+
13 | check_trait::<foo::Struct>();
5+
| ^^^^^^^^^^^ the trait `Trait` is not implemented for `foo::Struct`
6+
|
7+
note: there are multiple different versions of crate `foo` in the dependency graph
8+
--> foo-current.rs:7:1
9+
|
10+
4 | extern crate foo;
11+
| ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate
12+
5 |
13+
6 | pub struct Struct;
14+
| ----------------- this type implements the required trait
15+
7 | pub trait Trait {}
16+
| ^^^^^^^^^^^^^^^ this is the required trait
17+
|
18+
::: foo-prev.rs:X:Y
19+
|
20+
4 | pub struct Struct;
21+
| ----------------- this type doesn't implement the required trait
22+
5 | pub trait Trait {}
23+
| --------------- this is the found trait
24+
= note: two types coming from two different versions of the same crate are different types even if they look the same
25+
= help: you can use `cargo tree` to explore your dependency tree
26+
note: required by a bound in `check_trait`
27+
--> foo-current.rs:10:19
28+
|
29+
10 | fn check_trait<T: Trait>() {}
30+
| ^^^^^ required by this bound in `check_trait`
31+
32+
error: aborting due to 1 previous error
33+
34+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//@ only-linux
2+
//@ ignore-wasm32
3+
//@ ignore-wasm64
4+
// ignore-tidy-linelength
5+
6+
// Verify that if the current crate depends on a different version of the same crate, *and* types
7+
// and traits of the different versions are mixed, we produce diagnostic output and not an ICE.
8+
// #133563
9+
10+
use run_make_support::{diff, rust_lib_name, rustc};
11+
12+
fn main() {
13+
rustc().input("foo-prev.rs").run();
14+
15+
let out = rustc()
16+
.extra_filename("current")
17+
.metadata("current")
18+
.input("foo-current.rs")
19+
.extern_("foo", rust_lib_name("foo"))
20+
.run_fail()
21+
.stderr_utf8();
22+
23+
// We don't remap the path of the `foo-prev` crate, so we remap it here.
24+
let mut lines: Vec<_> = out.lines().collect();
25+
for line in &mut lines {
26+
if line.starts_with(" ::: ") {
27+
*line = " ::: foo-prev.rs:X:Y";
28+
}
29+
}
30+
diff().expected_file("foo.stderr").actual_text("(rustc)", &lines.join("\n")).run();
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied
2+
--> replaced
3+
|
4+
LL | do_something(Type);
5+
| ------------ ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
note: there are multiple different versions of crate `dependency` in the dependency graph
10+
--> replaced
11+
|
12+
LL | pub struct Type(pub i32);
13+
| --------------- this type implements the required trait
14+
LL | pub trait Trait {
15+
| ^^^^^^^^^^^^^^^ this is the required trait
16+
|
17+
::: replaced
18+
|
19+
LL | extern crate dep_2_reexport;
20+
| ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
21+
LL | extern crate dependency;
22+
| ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate
23+
|
24+
::: replaced
25+
|
26+
LL | pub struct Type;
27+
| --------------- this type doesn't implement the required trait
28+
LL | pub trait Trait {
29+
| --------------- this is the found trait
30+
= note: two types coming from two different versions of the same crate are different types even if they look the same
31+
= help: you can use `cargo tree` to explore your dependency tree
32+
note: required by a bound in `do_something`
33+
--> replaced
34+
|
35+
LL | pub fn do_something<X: Trait>(_: X) {}
36+
| ^^^^^ required by this bound in `do_something`
37+
38+
error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope
39+
--> replaced
40+
|
41+
LL | Type.foo();
42+
| ^^^ method not found in `Type`
43+
|
44+
note: there are multiple different versions of crate `dependency` in the dependency graph
45+
--> replaced
46+
|
47+
LL | pub trait Trait {
48+
| ^^^^^^^^^^^^^^^ this is the trait that is needed
49+
LL | fn foo(&self);
50+
| -------------- the method is available for `dep_2_reexport::Type` here
51+
|
52+
::: replaced
53+
|
54+
LL | use dependency::{Trait, do_something};
55+
| ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`
56+
|
57+
::: replaced
58+
|
59+
LL | pub trait Trait {
60+
| --------------- this is the trait that was imported
61+
62+
error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope
63+
--> replaced
64+
|
65+
LL | Type::bar();
66+
| ^^^ function or associated item not found in `Type`
67+
|
68+
note: there are multiple different versions of crate `dependency` in the dependency graph
69+
--> replaced
70+
|
71+
LL | pub trait Trait {
72+
| ^^^^^^^^^^^^^^^ this is the trait that is needed
73+
LL | fn foo(&self);
74+
LL | fn bar();
75+
| --------- the associated function is available for `dep_2_reexport::Type` here
76+
|
77+
::: replaced
78+
|
79+
LL | use dependency::{Trait, do_something};
80+
| ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`
81+
|
82+
::: replaced
83+
|
84+
LL | pub trait Trait {
85+
| --------------- this is the trait that was imported
86+
87+
error[E0277]: the trait bound `OtherType: Trait` is not satisfied
88+
--> replaced
89+
|
90+
LL | do_something(OtherType);
91+
| ------------ ^^^^^^^^^ the trait `Trait` is not implemented for `OtherType`
92+
| |
93+
| required by a bound introduced by this call
94+
|
95+
note: there are multiple different versions of crate `dependency` in the dependency graph
96+
--> replaced
97+
|
98+
LL | pub trait Trait {
99+
| ^^^^^^^^^^^^^^^ this is the required trait
100+
|
101+
::: replaced
102+
|
103+
LL | extern crate dep_2_reexport;
104+
| ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
105+
LL | extern crate dependency;
106+
| ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate
107+
|
108+
::: replaced
109+
|
110+
LL | pub struct OtherType;
111+
| -------------------- this type doesn't implement the required trait
112+
|
113+
::: replaced
114+
|
115+
LL | pub trait Trait {
116+
| --------------- this is the found trait
117+
= help: you can use `cargo tree` to explore your dependency tree
118+
note: required by a bound in `do_something`
119+
--> replaced
120+
|
121+
LL | pub fn do_something<X: Trait>(_: X) {}
122+
| ^^^^^ required by this bound in `do_something`
123+
124+
error: aborting due to 4 previous errors
125+
126+
Some errors have detailed explanations: E0277, E0599.
127+
For more information about an error, try `rustc --explain E0277`.

tests/run-make/crate-loading/rmake.rs

+19-76
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//@ ignore-wasm64
44
// ignore-tidy-linelength
55

6-
use run_make_support::{rust_lib_name, rustc};
6+
use run_make_support::{diff, rust_lib_name, rustc};
77

88
fn main() {
99
rustc().input("multiple-dep-versions-1.rs").run();
@@ -13,83 +13,26 @@ fn main() {
1313
.extern_("dependency", rust_lib_name("dependency2"))
1414
.run();
1515

16-
rustc()
16+
let out = rustc()
1717
.input("multiple-dep-versions.rs")
1818
.extern_("dependency", rust_lib_name("dependency"))
1919
.extern_("dep_2_reexport", rust_lib_name("foo"))
20+
.ui_testing()
2021
.run_fail()
21-
.assert_stderr_contains(r#"error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied
22-
--> multiple-dep-versions.rs:7:18
23-
|
24-
7 | do_something(Type);
25-
| ------------ ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type`
26-
| |
27-
| required by a bound introduced by this call
28-
|
29-
note: there are multiple different versions of crate `dependency` in the dependency graph"#)
30-
.assert_stderr_contains(r#"
31-
3 | pub struct Type(pub i32);
32-
| --------------- this type implements the required trait
33-
4 | pub trait Trait {
34-
| ^^^^^^^^^^^^^^^ this is the required trait
35-
"#)
36-
.assert_stderr_contains(r#"
37-
1 | extern crate dep_2_reexport;
38-
| ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
39-
2 | extern crate dependency;
40-
| ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate"#)
41-
.assert_stderr_contains(r#"
42-
3 | pub struct Type;
43-
| --------------- this type doesn't implement the required trait
44-
4 | pub trait Trait {
45-
| --------------- this is the found trait
46-
= note: two types coming from two different versions of the same crate are different types even if they look the same
47-
= help: you can use `cargo tree` to explore your dependency tree"#)
48-
.assert_stderr_contains(r#"note: required by a bound in `do_something`"#)
49-
.assert_stderr_contains(r#"
50-
12 | pub fn do_something<X: Trait>(_: X) {}
51-
| ^^^^^ required by this bound in `do_something`"#)
52-
.assert_stderr_contains(r#"error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope
53-
--> multiple-dep-versions.rs:8:10
54-
|
55-
8 | Type.foo();
56-
| ^^^ method not found in `Type`
57-
|
58-
note: there are multiple different versions of crate `dependency` in the dependency graph"#)
59-
.assert_stderr_contains(r#"
60-
4 | pub trait Trait {
61-
| ^^^^^^^^^^^^^^^ this is the trait that is needed
62-
5 | fn foo(&self);
63-
| -------------- the method is available for `dep_2_reexport::Type` here
64-
|
65-
::: multiple-dep-versions.rs:4:18
66-
|
67-
4 | use dependency::{Trait, do_something};
68-
| ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#)
69-
.assert_stderr_contains(r#"
70-
4 | pub trait Trait {
71-
| --------------- this is the trait that was imported"#)
72-
.assert_stderr_contains(r#"
73-
error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope
74-
--> multiple-dep-versions.rs:9:11
75-
|
76-
9 | Type::bar();
77-
| ^^^ function or associated item not found in `Type`
78-
|
79-
note: there are multiple different versions of crate `dependency` in the dependency graph"#)
80-
.assert_stderr_contains(r#"
81-
4 | pub trait Trait {
82-
| ^^^^^^^^^^^^^^^ this is the trait that is needed
83-
5 | fn foo(&self);
84-
6 | fn bar();
85-
| --------- the associated function is available for `dep_2_reexport::Type` here
86-
|
87-
::: multiple-dep-versions.rs:4:18
88-
|
89-
4 | use dependency::{Trait, do_something};
90-
| ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#)
91-
.assert_stderr_contains(
92-
r#"
93-
6 | pub struct OtherType;
94-
| -------------------- this type doesn't implement the required trait"#);
22+
.stderr_utf8();
23+
24+
// We don't remap all the paths, so we remap it here.
25+
let mut lines: Vec<_> = out.lines().collect();
26+
for line in &mut lines {
27+
if line.starts_with(" --> ") {
28+
*line = " --> replaced";
29+
}
30+
if line.starts_with(" ::: ") {
31+
*line = " ::: replaced";
32+
}
33+
}
34+
diff()
35+
.expected_file("multiple-dep-versions.stderr")
36+
.actual_text("(rustc)", &lines.join("\n"))
37+
.run();
9538
}

0 commit comments

Comments
 (0)