Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 16bf722

Browse files
committedDec 7, 2024
Add more info on type/trait mismatches for different crate versions
When encountering a type or trait mismatch for two types coming from two different crates with the same name, detect if it is either mixing two types/traits from the same crate on different versions: ``` error[E0308]: mismatched types --> replaced | LL | do_something_type(Type); | ----------------- ^^^^ expected `dependency::Type`, found `dep_2_reexport::Type` | | | arguments to this function are incorrect | note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same --> replaced | LL | pub struct Type(pub i32); | ^^^^^^^^^^^^^^^ this is the expected type `dependency::Type` | ::: replaced | LL | pub struct Type; | ^^^^^^^^^^^^^^^ this is the found type `dep_2_reexport::Type` | ::: replaced | LL | extern crate dep_2_reexport; | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` LL | extern crate dependency; | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate = help: you can use `cargo tree` to explore your dependency tree note: function defined here --> replaced | LL | pub fn do_something_type(_: Type) {} | ^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> replaced | LL | do_something_trait(Box::new(Type) as Box<dyn Trait2>); | ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `dependency::Trait2`, found trait `dep_2_reexport::Trait2` | | | arguments to this function are incorrect | note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same --> replaced | LL | pub trait Trait2 {} | ^^^^^^^^^^^^^^^^ this is the expected trait `dependency::Trait2` | ::: replaced | LL | pub trait Trait2 {} | ^^^^^^^^^^^^^^^^ this is the found trait `dep_2_reexport::Trait2` | ::: replaced | LL | extern crate dep_2_reexport; | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` LL | extern crate dependency; | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate = help: you can use `cargo tree` to explore your dependency tree note: function defined here --> replaced | LL | pub fn do_something_trait(_: Box<dyn Trait2>) {} | ^^^^^^^^^^^^^^^^^^ ``` or if it is different crates that were renamed to the same name: ``` error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:21:20 | LL | a::try_foo(foo2); | ---------- ^^^^ expected `main::a::Foo`, found a different `main::a::Foo` | | | arguments to this function are incorrect | note: two types coming from two different crates are different types even if they look the same --> $DIR/auxiliary/crate_a2.rs:1:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^ this is the found type `crate_a2::Foo` | ::: $DIR/auxiliary/crate_a1.rs:1:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^ this is the expected type `crate_a1::Foo` | ::: $DIR/type-mismatch-same-crate-name.rs:13:17 | LL | let foo2 = {extern crate crate_a2 as a; a::Foo}; | --------------------------- one type comes from crate `crate_a2` is used here, which is renamed locally to `a` ... LL | extern crate crate_a1 as a; | --------------------------- one type comes from crate `crate_a1` is used here, which is renamed locally to `a` note: function defined here --> $DIR/auxiliary/crate_a1.rs:10:8 | LL | pub fn try_foo(x: Foo){} | ^^^^^^^ error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:27:20 | LL | a::try_bar(bar2); | ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar` | | | arguments to this function are incorrect | note: two types coming from two different crates are different types even if they look the same --> $DIR/auxiliary/crate_a2.rs:3:1 | LL | pub trait Bar {} | ^^^^^^^^^^^^^ this is the found trait `crate_a2::Bar` | ::: $DIR/auxiliary/crate_a1.rs:3:1 | LL | pub trait Bar {} | ^^^^^^^^^^^^^ this is the expected trait `crate_a1::Bar` | ::: $DIR/type-mismatch-same-crate-name.rs:13:17 | LL | let foo2 = {extern crate crate_a2 as a; a::Foo}; | --------------------------- one trait comes from crate `crate_a2` is used here, which is renamed locally to `a` ... LL | extern crate crate_a1 as a; | --------------------------- one trait comes from crate `crate_a1` is used here, which is renamed locally to `a` note: function defined here --> $DIR/auxiliary/crate_a1.rs:11:8 | LL | pub fn try_bar(x: Box<Bar>){} | ^^^^^^^ ``` This new output unifies the E0308 errors detail with the pre-existing E0277 errors, and better differentiates the "`extern crate` renamed" and "same crate, different versions" cases.
1 parent 8dc8377 commit 16bf722

File tree

15 files changed

+281
-76
lines changed

15 files changed

+281
-76
lines changed
 

‎compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs

Lines changed: 116 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ use std::{cmp, fmt, iter};
5252

5353
use rustc_abi::ExternAbi;
5454
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
55-
use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize};
55+
use rustc_errors::{
56+
Applicability, Diag, DiagStyledString, IntoDiagArg, MultiSpan, StringPart, pluralize,
57+
};
5658
use rustc_hir::def::DefKind;
5759
use rustc_hir::def_id::DefId;
5860
use rustc_hir::intravisit::Visitor;
@@ -67,6 +69,7 @@ use rustc_middle::ty::{
6769
self, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
6870
TypeVisitableExt,
6971
};
72+
use rustc_span::def_id::LOCAL_CRATE;
7073
use rustc_span::{BytePos, DesugaringKind, Pos, Span, sym};
7174
use tracing::{debug, instrument};
7275

@@ -211,7 +214,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
211214
}
212215

213216
/// Adds a note if the types come from similarly named crates
214-
fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) {
217+
fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) -> bool {
218+
// FIXME(estebank): unify with `report_similar_impl_candidates`. The message is similar,
219+
// even if the logic needed to detect the case is very different.
215220
use hir::def_id::CrateNum;
216221
use rustc_hir::definitions::DisambiguatedDefPathData;
217222
use ty::GenericArg;
@@ -285,7 +290,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
285290
}
286291
}
287292

288-
let report_path_match = |err: &mut Diag<'_>, did1: DefId, did2: DefId| {
293+
let report_path_match = |err: &mut Diag<'_>, did1: DefId, did2: DefId, ty: &str| -> bool {
289294
// Only report definitions from different crates. If both definitions
290295
// are from a local module we could have false positives, e.g.
291296
// let _ = [{struct Foo; Foo}, {struct Foo; Foo}];
@@ -297,24 +302,112 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
297302

298303
// We compare strings because DefPath can be different
299304
// for imported and non-imported crates
305+
let expected_str = self.tcx.def_path_str(did1);
306+
let found_str = self.tcx.def_path_str(did2);
307+
let Ok(expected_abs) = abs_path(did1) else { return false };
308+
let Ok(found_abs) = abs_path(did2) else { return false };
300309
let same_path = || -> Result<_, PrintError> {
301-
Ok(self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2)
302-
|| abs_path(did1)? == abs_path(did2)?)
310+
Ok(expected_str == found_str || expected_abs == found_abs)
311+
};
312+
// We want to use as unique a type path as possible. If both types are "locally
313+
// known" by the same name, we use the "absolute path" which uses the original
314+
// crate name instead.
315+
let (expected, found) = if expected_str == found_str {
316+
(expected_abs.join("::"), found_abs.join("::"))
317+
} else {
318+
(expected_str.clone(), found_str.clone())
303319
};
304320
if same_path().unwrap_or(false) {
305-
let crate_name = self.tcx.crate_name(did1.krate);
306-
let msg = if did1.is_local() || did2.is_local() {
321+
// We've displayed "expected `a::b`, found `a::b`". We add context to
322+
// differentiate the different cases where that might happen.
323+
let expected_crate_name = self.tcx.crate_name(did1.krate);
324+
let found_crate_name = self.tcx.crate_name(did2.krate);
325+
let same_crate = expected_crate_name == found_crate_name;
326+
let expected_sp = self.tcx.def_span(did1);
327+
let found_sp = self.tcx.def_span(did2);
328+
329+
let both_direct_dependencies = if !did1.is_local()
330+
&& !did2.is_local()
331+
&& let Some(data1) = self.tcx.extern_crate(did1.krate)
332+
&& let Some(data2) = self.tcx.extern_crate(did2.krate)
333+
&& data1.dependency_of == LOCAL_CRATE
334+
&& data2.dependency_of == LOCAL_CRATE
335+
{
336+
// If both crates are directly depended on, we don't want to mention that
337+
// in the final message, as it is redundant wording.
338+
// We skip the case of semver trick, where one version of the local crate
339+
// depends on another version of itself by checking that both crates at play
340+
// are not the current one.
341+
true
342+
} else {
343+
false
344+
};
345+
346+
let mut span: MultiSpan = vec![expected_sp, found_sp].into();
347+
span.push_span_label(
348+
self.tcx.def_span(did1),
349+
format!("this is the expected {ty} `{expected}`"),
350+
);
351+
span.push_span_label(
352+
self.tcx.def_span(did2),
353+
format!("this is the found {ty} `{found}`"),
354+
);
355+
for def_id in [did1, did2] {
356+
let crate_name = self.tcx.crate_name(def_id.krate);
357+
if !def_id.is_local()
358+
&& let Some(data) = self.tcx.extern_crate(def_id.krate)
359+
{
360+
let descr = if same_crate {
361+
"one version of".to_string()
362+
} else {
363+
format!("one {ty} comes from")
364+
};
365+
let dependency = if both_direct_dependencies {
366+
if let rustc_session::cstore::ExternCrateSource::Extern(def_id) =
367+
data.src
368+
&& let Some(name) = self.tcx.opt_item_name(def_id)
369+
{
370+
format!(", which is renamed locally to `{name}`")
371+
} else {
372+
String::new()
373+
}
374+
} else if data.dependency_of == LOCAL_CRATE {
375+
", as a direct dependency of the current crate".to_string()
376+
} else {
377+
let dep = self.tcx.crate_name(data.dependency_of);
378+
format!(", as a dependency of crate `{dep}`")
379+
};
380+
span.push_span_label(
381+
data.span,
382+
format!("{descr} crate `{crate_name}` used here{dependency}"),
383+
);
384+
}
385+
}
386+
let msg = if (did1.is_local() || did2.is_local()) && same_crate {
387+
format!(
388+
"the crate `{expected_crate_name}` is compiled multiple times, \
389+
possibly with different configurations",
390+
)
391+
} else if same_crate {
307392
format!(
308-
"the crate `{crate_name}` is compiled multiple times, possibly with different configurations"
393+
"two different versions of crate `{expected_crate_name}` are being \
394+
used; two types coming from two different versions of the same crate \
395+
are different types even if they look the same",
309396
)
310397
} else {
311398
format!(
312-
"perhaps two different versions of crate `{crate_name}` are being used?"
399+
"two types coming from two different crates are different types even \
400+
if they look the same",
313401
)
314402
};
315-
err.note(msg);
403+
err.span_note(span, msg);
404+
if same_crate {
405+
err.help("you can use `cargo tree` to explore your dependency tree");
406+
}
407+
return true;
316408
}
317409
}
410+
false
318411
};
319412
match terr {
320413
TypeError::Sorts(ref exp_found) => {
@@ -323,14 +416,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
323416
if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) =
324417
(exp_found.expected.kind(), exp_found.found.kind())
325418
{
326-
report_path_match(err, exp_adt.did(), found_adt.did());
419+
return report_path_match(err, exp_adt.did(), found_adt.did(), "type");
327420
}
328421
}
329422
TypeError::Traits(ref exp_found) => {
330-
report_path_match(err, exp_found.expected, exp_found.found);
423+
return report_path_match(err, exp_found.expected, exp_found.found, "trait");
331424
}
332425
_ => (), // FIXME(#22750) handle traits and stuff
333426
}
427+
false
334428
}
335429

336430
fn note_error_origin(
@@ -1409,6 +1503,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
14091503
label_or_note(span, terr.to_string(self.tcx));
14101504
}
14111505

1506+
if self.check_and_note_conflicting_crates(diag, terr) {
1507+
return;
1508+
}
1509+
14121510
if let Some((expected, found, path)) = expected_found {
14131511
let (expected_label, found_label, exp_found) = match exp_found {
14141512
Mismatch::Variable(ef) => (
@@ -1470,15 +1568,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
14701568
|prim: Ty<'tcx>, shadow: Ty<'tcx>, defid: DefId, diag: &mut Diag<'_>| {
14711569
let name = shadow.sort_string(self.tcx);
14721570
diag.note(format!(
1473-
"{prim} and {name} have similar names, but are actually distinct types"
1571+
"`{prim}` and {name} have similar names, but are actually distinct types"
1572+
));
1573+
diag.note(format!(
1574+
"one `{prim}` is a primitive defined by the language",
14741575
));
1475-
diag.note(format!("{prim} is a primitive defined by the language"));
14761576
let def_span = self.tcx.def_span(defid);
14771577
let msg = if defid.is_local() {
1478-
format!("{name} is defined in the current crate")
1578+
format!("the other {name} is defined in the current crate")
14791579
} else {
14801580
let crate_name = self.tcx.crate_name(defid.krate);
1481-
format!("{name} is defined in crate `{crate_name}`")
1581+
format!("the other {name} is defined in crate `{crate_name}`")
14821582
};
14831583
diag.span_note(def_span, msg);
14841584
};
@@ -1666,8 +1766,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
16661766
}
16671767
}
16681768

1669-
self.check_and_note_conflicting_crates(diag, terr);
1670-
16711769
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
16721770
if let Some(exp_found) = exp_found
16731771
&& let exp_found = TypeError::Sorts(exp_found)

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,9 +1745,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17451745
};
17461746
(
17471747
data.span,
1748-
format!(
1749-
"one version of crate `{crate_name}` is used here, as a {dependency}"
1750-
),
1748+
format!("one version of crate `{crate_name}` used here, as a {dependency}"),
17511749
)
17521750
})
17531751
{

‎tests/incremental/circular-dependencies.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
//@ [cfail2] compile-flags: --test --extern aux={{build-base}}/circular-dependencies/auxiliary/libcircular_dependencies_aux.rmeta -L dependency={{build-base}}/circular-dependencies
77

88
pub struct Foo;
9-
//[cfail2]~^ NOTE `Foo` is defined in the current crate
10-
//[cfail2]~| NOTE `Foo` is defined in the current crate
11-
//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies`
12-
//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies`
9+
//[cfail2]~^ NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
10+
//[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
11+
//[cfail2]~| NOTE this is the expected type `Foo`
12+
//[cfail2]~| NOTE this is the expected type `circular_dependencies::Foo`
13+
//[cfail2]~| NOTE this is the found type `Foo`
14+
//[cfail2]~| NOTE this is the found type `circular_dependencies::Foo`
1315

1416
pub fn consume_foo(_: Foo) {}
1517
//[cfail2]~^ NOTE function defined here
@@ -24,14 +26,12 @@ fn test() {
2426
//[cfail2]~^ ERROR mismatched types [E0308]
2527
//[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo`
2628
//[cfail2]~| NOTE arguments to this function are incorrect
27-
//[cfail2]~| NOTE `Foo` and `circular_dependencies::Foo` have similar names, but are actually distinct types
28-
//[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
2929
//[cfail2]~| NOTE function defined here
30+
//[cfail2]~| NOTE one version of crate `circular_dependencies` used here, as a dependency of crate `circular_dependencies_aux`
31+
//[cfail2]~| NOTE one version of crate `circular_dependencies` used here, as a dependency of crate `circular_dependencies_aux`
3032

3133
consume_foo(aux::produce_foo());
3234
//[cfail2]~^ ERROR mismatched types [E0308]
3335
//[cfail2]~| NOTE expected `Foo`, found `circular_dependencies::Foo`
3436
//[cfail2]~| NOTE arguments to this function are incorrect
35-
//[cfail2]~| NOTE `circular_dependencies::Foo` and `Foo` have similar names, but are actually distinct types
36-
//[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
3737
}

‎tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ note: there are multiple different versions of crate `foo` in the dependency gra
88
--> foo-current.rs:7:1
99
|
1010
4 | extern crate foo;
11-
| ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate
11+
| ----------------- one version of crate `foo` used here, as a direct dependency of the current crate
1212
5 |
1313
6 | pub struct Struct;
1414
| ----------------- this type implements the required trait

‎tests/run-make/crate-loading/multiple-dep-versions-1.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ pub trait Trait {
55
fn foo(&self);
66
fn bar();
77
}
8+
pub trait Trait2 {}
89
impl Trait for Type {
910
fn foo(&self) {}
1011
fn bar() {}
1112
}
1213
pub fn do_something<X: Trait>(_: X) {}
14+
pub fn do_something_type(_: Type) {}
15+
pub fn do_something_trait(_: Box<dyn Trait2>) {}

‎tests/run-make/crate-loading/multiple-dep-versions-2.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ pub trait Trait {
55
fn foo(&self);
66
fn bar();
77
}
8+
pub trait Trait2 {}
9+
impl Trait2 for Type {}
810
impl Trait for Type {
911
fn foo(&self) {}
1012
fn bar() {}
1113
}
1214
pub fn do_something<X: Trait>(_: X) {}
15+
pub fn do_something_type(_: Type) {}
16+
pub fn do_something_trait(_: Box<dyn Trait2>) {}

‎tests/run-make/crate-loading/multiple-dep-versions-3.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![crate_type = "rlib"]
33

44
extern crate dependency;
5-
pub use dependency::Type;
5+
pub use dependency::{Trait2, Type, do_something_trait, do_something_type};
66
pub struct OtherType;
77
impl dependency::Trait for OtherType {
88
fn foo(&self) {}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
extern crate dep_2_reexport;
22
extern crate dependency;
3-
use dep_2_reexport::{OtherType, Type};
4-
use dependency::{Trait, do_something};
3+
use dep_2_reexport::{OtherType, Trait2, Type};
4+
use dependency::{Trait, do_something, do_something_trait, do_something_type};
55

66
fn main() {
77
do_something(Type);
88
Type.foo();
99
Type::bar();
1010
do_something(OtherType);
11+
do_something_type(Type);
12+
do_something_trait(Box::new(Type) as Box<dyn Trait2>);
1113
}

‎tests/run-make/crate-loading/multiple-dep-versions.stderr

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ LL | pub trait Trait {
1717
::: replaced
1818
|
1919
LL | extern crate dep_2_reexport;
20-
| ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
20+
| ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
2121
LL | extern crate dependency;
22-
| ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate
22+
| ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
2323
|
2424
::: replaced
2525
|
@@ -51,7 +51,7 @@ LL | fn foo(&self);
5151
|
5252
::: replaced
5353
|
54-
LL | use dependency::{Trait, do_something};
54+
LL | use dependency::{Trait, do_something, do_something_trait, do_something_type};
5555
| ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`
5656
|
5757
::: replaced
@@ -76,7 +76,7 @@ LL | fn bar();
7676
|
7777
::: replaced
7878
|
79-
LL | use dependency::{Trait, do_something};
79+
LL | use dependency::{Trait, do_something, do_something_trait, do_something_type};
8080
| ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`
8181
|
8282
::: replaced
@@ -101,9 +101,9 @@ LL | pub trait Trait {
101101
::: replaced
102102
|
103103
LL | extern crate dep_2_reexport;
104-
| ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
104+
| ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
105105
LL | extern crate dependency;
106-
| ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate
106+
| ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
107107
|
108108
::: replaced
109109
|
@@ -121,7 +121,71 @@ note: required by a bound in `do_something`
121121
LL | pub fn do_something<X: Trait>(_: X) {}
122122
| ^^^^^ required by this bound in `do_something`
123123

124-
error: aborting due to 4 previous errors
124+
error[E0308]: mismatched types
125+
--> replaced
126+
|
127+
LL | do_something_type(Type);
128+
| ----------------- ^^^^ expected `dependency::Type`, found `dep_2_reexport::Type`
129+
| |
130+
| arguments to this function are incorrect
131+
|
132+
note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same
133+
--> replaced
134+
|
135+
LL | pub struct Type(pub i32);
136+
| ^^^^^^^^^^^^^^^ this is the expected type `dependency::Type`
137+
|
138+
::: replaced
139+
|
140+
LL | pub struct Type;
141+
| ^^^^^^^^^^^^^^^ this is the found type `dep_2_reexport::Type`
142+
|
143+
::: replaced
144+
|
145+
LL | extern crate dep_2_reexport;
146+
| ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
147+
LL | extern crate dependency;
148+
| ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
149+
= help: you can use `cargo tree` to explore your dependency tree
150+
note: function defined here
151+
--> replaced
152+
|
153+
LL | pub fn do_something_type(_: Type) {}
154+
| ^^^^^^^^^^^^^^^^^
155+
156+
error[E0308]: mismatched types
157+
--> replaced
158+
|
159+
LL | do_something_trait(Box::new(Type) as Box<dyn Trait2>);
160+
| ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `dependency::Trait2`, found trait `dep_2_reexport::Trait2`
161+
| |
162+
| arguments to this function are incorrect
163+
|
164+
note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same
165+
--> replaced
166+
|
167+
LL | pub trait Trait2 {}
168+
| ^^^^^^^^^^^^^^^^ this is the expected trait `dependency::Trait2`
169+
|
170+
::: replaced
171+
|
172+
LL | pub trait Trait2 {}
173+
| ^^^^^^^^^^^^^^^^ this is the found trait `dep_2_reexport::Trait2`
174+
|
175+
::: replaced
176+
|
177+
LL | extern crate dep_2_reexport;
178+
| ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
179+
LL | extern crate dependency;
180+
| ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
181+
= help: you can use `cargo tree` to explore your dependency tree
182+
note: function defined here
183+
--> replaced
184+
|
185+
LL | pub fn do_something_trait(_: Box<dyn Trait2>) {}
186+
| ^^^^^^^^^^^^^^^^^^
187+
188+
error: aborting due to 6 previous errors
125189

126-
Some errors have detailed explanations: E0277, E0599.
190+
Some errors have detailed explanations: E0277, E0308, E0599.
127191
For more information about an error, try `rustc --explain E0277`.
Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
#![allow(non_camel_case_types)]
22

3-
struct bool;
4-
struct str;
3+
struct bool; //~ NOTE the other `bool` is defined in the current crate
4+
struct str; //~ NOTE the other `str` is defined in the current crate
55

6-
fn foo(_: bool) {}
7-
fn bar(_: &str) {}
6+
fn foo(_: bool) {} //~ NOTE function defined here
7+
fn bar(_: &str) {} //~ NOTE function defined here
88

99
fn main() {
1010
foo(true);
1111
//~^ ERROR mismatched types [E0308]
12+
//~| NOTE expected `bool`, found a different `bool`
13+
//~| NOTE arguments to this function are incorrect
14+
//~| NOTE `bool` and `bool` have similar names, but are actually distinct types
15+
//~| NOTE one `bool` is a primitive defined by the language
1216
bar("hello");
1317
//~^ ERROR mismatched types [E0308]
18+
//~| NOTE expected `str`, found a different `str`
19+
//~| NOTE arguments to this function are incorrect
20+
//~| NOTE `str` and `str` have similar names, but are actually distinct types
21+
//~| NOTE one `str` is a primitive defined by the language
1422
}

‎tests/ui/mismatched_types/similar_paths_primitive.stderr

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ LL | foo(true);
66
| |
77
| arguments to this function are incorrect
88
|
9-
= note: bool and `bool` have similar names, but are actually distinct types
10-
= note: bool is a primitive defined by the language
11-
note: `bool` is defined in the current crate
9+
= note: `bool` and `bool` have similar names, but are actually distinct types
10+
= note: one `bool` is a primitive defined by the language
11+
note: the other `bool` is defined in the current crate
1212
--> $DIR/similar_paths_primitive.rs:3:1
1313
|
1414
LL | struct bool;
@@ -20,16 +20,16 @@ LL | fn foo(_: bool) {}
2020
| ^^^ -------
2121

2222
error[E0308]: mismatched types
23-
--> $DIR/similar_paths_primitive.rs:12:9
23+
--> $DIR/similar_paths_primitive.rs:16:9
2424
|
2525
LL | bar("hello");
2626
| --- ^^^^^^^ expected `str`, found a different `str`
2727
| |
2828
| arguments to this function are incorrect
2929
|
30-
= note: str and `str` have similar names, but are actually distinct types
31-
= note: str is a primitive defined by the language
32-
note: `str` is defined in the current crate
30+
= note: `str` and `str` have similar names, but are actually distinct types
31+
= note: one `str` is a primitive defined by the language
32+
note: the other `str` is defined in the current crate
3333
--> $DIR/similar_paths_primitive.rs:4:1
3434
|
3535
LL | struct str;

‎tests/ui/type/auxiliary/crate_a1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
pub struct Foo;
22

3-
pub trait Bar{}
3+
pub trait Bar {}
44

55
pub fn bar() -> Box<Bar> {
66
unimplemented!()

‎tests/ui/type/auxiliary/crate_a2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
pub struct Foo;
22

3-
pub trait Bar{}
3+
pub trait Bar {}
44

55
pub fn bar() -> Box<Bar> {
66
unimplemented!()

‎tests/ui/type/type-mismatch-same-crate-name.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,32 @@
33

44
// This tests the extra note reported when a type error deals with
55
// seemingly identical types.
6-
// The main use case of this error is when there are two crates
7-
// (generally different versions of the same crate) with the same name
8-
// causing a type mismatch. Here, we simulate that error using block-scoped
9-
// aliased `extern crate` declarations.
6+
// The main use case of this error is when there are two crates imported
7+
// with the same name, causing a type mismatch. Here, we simulate that error
8+
// using block-scoped aliased `extern crate` declarations.
9+
// This is *not* the same case as two different crate versions in the
10+
// dependency tree. That is tested in `tests/run-make/crate-loading/`.
1011

1112
fn main() {
1213
let foo2 = {extern crate crate_a2 as a; a::Foo};
14+
//~^ NOTE one type comes from crate `crate_a2` used here, which is renamed locally to `a`
15+
//~| NOTE one trait comes from crate `crate_a2` used here, which is renamed locally to `a`
1316
let bar2 = {extern crate crate_a2 as a; a::bar()};
1417
{
1518
extern crate crate_a1 as a;
19+
//~^ NOTE one type comes from crate `crate_a1` used here, which is renamed locally to `a`
20+
//~| NOTE one trait comes from crate `crate_a1` used here, which is renamed locally to `a`
1621
a::try_foo(foo2);
1722
//~^ ERROR mismatched types
18-
//~| perhaps two different versions of crate `crate_a1`
19-
//~| expected `main::a::Foo`, found a different `main::a::Foo`
23+
//~| NOTE expected `main::a::Foo`, found a different `main::a::Foo`
24+
//~| NOTE arguments to this function are incorrect
25+
//~| NOTE two types coming from two different crates are different types even if they look the same
26+
//~| NOTE function defined here
2027
a::try_bar(bar2);
2128
//~^ ERROR mismatched types
22-
//~| perhaps two different versions of crate `crate_a1`
23-
//~| expected trait `main::a::Bar`
24-
//~| expected struct `Box<(dyn main::a::Bar + 'static)>`
25-
//~| found struct `Box<dyn main::a::Bar>`
29+
//~| NOTE expected trait `main::a::Bar`, found a different trait `main::a::Bar`
30+
//~| NOTE arguments to this function are incorrect
31+
//~| NOTE two types coming from two different crates are different types even if they look the same
32+
//~| NOTE function defined here
2633
}
2734
}

‎tests/ui/type/type-mismatch-same-crate-name.stderr

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,61 @@
11
error[E0308]: mismatched types
2-
--> $DIR/type-mismatch-same-crate-name.rs:16:20
2+
--> $DIR/type-mismatch-same-crate-name.rs:21:20
33
|
44
LL | a::try_foo(foo2);
55
| ---------- ^^^^ expected `main::a::Foo`, found a different `main::a::Foo`
66
| |
77
| arguments to this function are incorrect
88
|
9-
= note: `main::a::Foo` and `main::a::Foo` have similar names, but are actually distinct types
10-
note: `main::a::Foo` is defined in crate `crate_a2`
9+
note: two types coming from two different crates are different types even if they look the same
1110
--> $DIR/auxiliary/crate_a2.rs:1:1
1211
|
1312
LL | pub struct Foo;
14-
| ^^^^^^^^^^^^^^
15-
note: `main::a::Foo` is defined in crate `crate_a1`
16-
--> $DIR/auxiliary/crate_a1.rs:1:1
13+
| ^^^^^^^^^^^^^^ this is the found type `crate_a2::Foo`
14+
|
15+
::: $DIR/auxiliary/crate_a1.rs:1:1
1716
|
1817
LL | pub struct Foo;
19-
| ^^^^^^^^^^^^^^
20-
= note: perhaps two different versions of crate `crate_a1` are being used?
18+
| ^^^^^^^^^^^^^^ this is the expected type `crate_a1::Foo`
19+
|
20+
::: $DIR/type-mismatch-same-crate-name.rs:13:17
21+
|
22+
LL | let foo2 = {extern crate crate_a2 as a; a::Foo};
23+
| --------------------------- one type comes from crate `crate_a2` used here, which is renamed locally to `a`
24+
...
25+
LL | extern crate crate_a1 as a;
26+
| --------------------------- one type comes from crate `crate_a1` used here, which is renamed locally to `a`
2127
note: function defined here
2228
--> $DIR/auxiliary/crate_a1.rs:10:8
2329
|
2430
LL | pub fn try_foo(x: Foo){}
2531
| ^^^^^^^
2632

2733
error[E0308]: mismatched types
28-
--> $DIR/type-mismatch-same-crate-name.rs:20:20
34+
--> $DIR/type-mismatch-same-crate-name.rs:27:20
2935
|
3036
LL | a::try_bar(bar2);
3137
| ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar`
3238
| |
3339
| arguments to this function are incorrect
3440
|
35-
= note: expected struct `Box<(dyn main::a::Bar + 'static)>`
36-
found struct `Box<dyn main::a::Bar>`
37-
= note: perhaps two different versions of crate `crate_a1` are being used?
41+
note: two types coming from two different crates are different types even if they look the same
42+
--> $DIR/auxiliary/crate_a2.rs:3:1
43+
|
44+
LL | pub trait Bar {}
45+
| ^^^^^^^^^^^^^ this is the found trait `crate_a2::Bar`
46+
|
47+
::: $DIR/auxiliary/crate_a1.rs:3:1
48+
|
49+
LL | pub trait Bar {}
50+
| ^^^^^^^^^^^^^ this is the expected trait `crate_a1::Bar`
51+
|
52+
::: $DIR/type-mismatch-same-crate-name.rs:13:17
53+
|
54+
LL | let foo2 = {extern crate crate_a2 as a; a::Foo};
55+
| --------------------------- one trait comes from crate `crate_a2` used here, which is renamed locally to `a`
56+
...
57+
LL | extern crate crate_a1 as a;
58+
| --------------------------- one trait comes from crate `crate_a1` used here, which is renamed locally to `a`
3859
note: function defined here
3960
--> $DIR/auxiliary/crate_a1.rs:11:8
4061
|

0 commit comments

Comments
 (0)
This repository has been archived.