diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 8ba7969207e8a..f856a8d7abbe7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -52,7 +52,9 @@ use std::{cmp, fmt, iter}; use rustc_abi::ExternAbi; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; -use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize}; +use rustc_errors::{ + Applicability, Diag, DiagStyledString, IntoDiagArg, MultiSpan, StringPart, pluralize, +}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -67,6 +69,7 @@ use rustc_middle::ty::{ self, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; +use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{BytePos, DesugaringKind, Pos, Span, sym}; use tracing::{debug, instrument}; @@ -211,7 +214,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } /// Adds a note if the types come from similarly named crates - fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) { + fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) -> bool { + // FIXME(estebank): unify with `report_similar_impl_candidates`. The message is similar, + // even if the logic needed to detect the case is very different. use hir::def_id::CrateNum; use rustc_hir::definitions::DisambiguatedDefPathData; use ty::GenericArg; @@ -285,7 +290,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - let report_path_match = |err: &mut Diag<'_>, did1: DefId, did2: DefId| { + let report_path_match = |err: &mut Diag<'_>, did1: DefId, did2: DefId, ty: &str| -> bool { // Only report definitions from different crates. If both definitions // are from a local module we could have false positives, e.g. // let _ = [{struct Foo; Foo}, {struct Foo; Foo}]; @@ -297,24 +302,112 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // We compare strings because DefPath can be different // for imported and non-imported crates + let expected_str = self.tcx.def_path_str(did1); + let found_str = self.tcx.def_path_str(did2); + let Ok(expected_abs) = abs_path(did1) else { return false }; + let Ok(found_abs) = abs_path(did2) else { return false }; let same_path = || -> Result<_, PrintError> { - Ok(self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2) - || abs_path(did1)? == abs_path(did2)?) + Ok(expected_str == found_str || expected_abs == found_abs) + }; + // We want to use as unique a type path as possible. If both types are "locally + // known" by the same name, we use the "absolute path" which uses the original + // crate name instead. + let (expected, found) = if expected_str == found_str { + (expected_abs.join("::"), found_abs.join("::")) + } else { + (expected_str.clone(), found_str.clone()) }; if same_path().unwrap_or(false) { - let crate_name = self.tcx.crate_name(did1.krate); - let msg = if did1.is_local() || did2.is_local() { + // We've displayed "expected `a::b`, found `a::b`". We add context to + // differentiate the different cases where that might happen. + let expected_crate_name = self.tcx.crate_name(did1.krate); + let found_crate_name = self.tcx.crate_name(did2.krate); + let same_crate = expected_crate_name == found_crate_name; + let expected_sp = self.tcx.def_span(did1); + let found_sp = self.tcx.def_span(did2); + + let both_direct_dependencies = if !did1.is_local() + && !did2.is_local() + && let Some(data1) = self.tcx.extern_crate(did1.krate) + && let Some(data2) = self.tcx.extern_crate(did2.krate) + && data1.dependency_of == LOCAL_CRATE + && data2.dependency_of == LOCAL_CRATE + { + // If both crates are directly depended on, we don't want to mention that + // in the final message, as it is redundant wording. + // We skip the case of semver trick, where one version of the local crate + // depends on another version of itself by checking that both crates at play + // are not the current one. + true + } else { + false + }; + + let mut span: MultiSpan = vec![expected_sp, found_sp].into(); + span.push_span_label( + self.tcx.def_span(did1), + format!("this is the expected {ty} `{expected}`"), + ); + span.push_span_label( + self.tcx.def_span(did2), + format!("this is the found {ty} `{found}`"), + ); + for def_id in [did1, did2] { + let crate_name = self.tcx.crate_name(def_id.krate); + if !def_id.is_local() + && let Some(data) = self.tcx.extern_crate(def_id.krate) + { + let descr = if same_crate { + "one version of".to_string() + } else { + format!("one {ty} comes from") + }; + let dependency = if both_direct_dependencies { + if let rustc_session::cstore::ExternCrateSource::Extern(def_id) = + data.src + && let Some(name) = self.tcx.opt_item_name(def_id) + { + format!(", which is renamed locally to `{name}`") + } else { + String::new() + } + } else if data.dependency_of == LOCAL_CRATE { + ", as a direct dependency of the current crate".to_string() + } else { + let dep = self.tcx.crate_name(data.dependency_of); + format!(", as a dependency of crate `{dep}`") + }; + span.push_span_label( + data.span, + format!("{descr} crate `{crate_name}` used here{dependency}"), + ); + } + } + let msg = if (did1.is_local() || did2.is_local()) && same_crate { + format!( + "the crate `{expected_crate_name}` is compiled multiple times, \ + possibly with different configurations", + ) + } else if same_crate { format!( - "the crate `{crate_name}` is compiled multiple times, possibly with different configurations" + "two different versions of crate `{expected_crate_name}` are being \ + used; two types coming from two different versions of the same crate \ + are different types even if they look the same", ) } else { format!( - "perhaps two different versions of crate `{crate_name}` are being used?" + "two types coming from two different crates are different types even \ + if they look the same", ) }; - err.note(msg); + err.span_note(span, msg); + if same_crate { + err.help("you can use `cargo tree` to explore your dependency tree"); + } + return true; } } + false }; match terr { TypeError::Sorts(ref exp_found) => { @@ -323,14 +416,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) = (exp_found.expected.kind(), exp_found.found.kind()) { - report_path_match(err, exp_adt.did(), found_adt.did()); + return report_path_match(err, exp_adt.did(), found_adt.did(), "type"); } } TypeError::Traits(ref exp_found) => { - report_path_match(err, exp_found.expected, exp_found.found); + return report_path_match(err, exp_found.expected, exp_found.found, "trait"); } _ => (), // FIXME(#22750) handle traits and stuff } + false } fn note_error_origin( @@ -1409,6 +1503,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { label_or_note(span, terr.to_string(self.tcx)); } + if self.check_and_note_conflicting_crates(diag, terr) { + return; + } + if let Some((expected, found, path)) = expected_found { let (expected_label, found_label, exp_found) = match exp_found { Mismatch::Variable(ef) => ( @@ -1470,15 +1568,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |prim: Ty<'tcx>, shadow: Ty<'tcx>, defid: DefId, diag: &mut Diag<'_>| { let name = shadow.sort_string(self.tcx); diag.note(format!( - "{prim} and {name} have similar names, but are actually distinct types" + "`{prim}` and {name} have similar names, but are actually distinct types" + )); + diag.note(format!( + "one `{prim}` is a primitive defined by the language", )); - diag.note(format!("{prim} is a primitive defined by the language")); let def_span = self.tcx.def_span(defid); let msg = if defid.is_local() { - format!("{name} is defined in the current crate") + format!("the other {name} is defined in the current crate") } else { let crate_name = self.tcx.crate_name(defid.krate); - format!("{name} is defined in crate `{crate_name}`") + format!("the other {name} is defined in crate `{crate_name}`") }; diag.span_note(def_span, msg); }; @@ -1666,8 +1766,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - self.check_and_note_conflicting_crates(diag, terr); - self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id()); if let Some(exp_found) = exp_found && let exp_found = TypeError::Sorts(exp_found) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 90b1825362908..4fb02f609438e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1745,9 +1745,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; ( data.span, - format!( - "one version of crate `{crate_name}` is used here, as a {dependency}" - ), + format!("one version of crate `{crate_name}` used here, as a {dependency}"), ) }) { diff --git a/tests/incremental/circular-dependencies.rs b/tests/incremental/circular-dependencies.rs index 320edad3fde9f..c7b5b931fbbec 100644 --- a/tests/incremental/circular-dependencies.rs +++ b/tests/incremental/circular-dependencies.rs @@ -6,10 +6,12 @@ //@ [cfail2] compile-flags: --test --extern aux={{build-base}}/circular-dependencies/auxiliary/libcircular_dependencies_aux.rmeta -L dependency={{build-base}}/circular-dependencies pub struct Foo; -//[cfail2]~^ NOTE `Foo` is defined in the current crate -//[cfail2]~| NOTE `Foo` is defined in the current crate -//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies` -//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies` +//[cfail2]~^ NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations +//[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations +//[cfail2]~| NOTE this is the expected type `Foo` +//[cfail2]~| NOTE this is the expected type `circular_dependencies::Foo` +//[cfail2]~| NOTE this is the found type `Foo` +//[cfail2]~| NOTE this is the found type `circular_dependencies::Foo` pub fn consume_foo(_: Foo) {} //[cfail2]~^ NOTE function defined here @@ -24,14 +26,12 @@ fn test() { //[cfail2]~^ ERROR mismatched types [E0308] //[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo` //[cfail2]~| NOTE arguments to this function are incorrect - //[cfail2]~| NOTE `Foo` and `circular_dependencies::Foo` have similar names, but are actually distinct types - //[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations //[cfail2]~| NOTE function defined here + //[cfail2]~| NOTE one version of crate `circular_dependencies` used here, as a dependency of crate `circular_dependencies_aux` + //[cfail2]~| NOTE one version of crate `circular_dependencies` used here, as a dependency of crate `circular_dependencies_aux` consume_foo(aux::produce_foo()); //[cfail2]~^ ERROR mismatched types [E0308] //[cfail2]~| NOTE expected `Foo`, found `circular_dependencies::Foo` //[cfail2]~| NOTE arguments to this function are incorrect - //[cfail2]~| NOTE `circular_dependencies::Foo` and `Foo` have similar names, but are actually distinct types - //[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations } diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr b/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr index 36379429530bc..7f131153540bb 100644 --- a/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr +++ b/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr @@ -8,7 +8,7 @@ note: there are multiple different versions of crate `foo` in the dependency gra --> foo-current.rs:7:1 | 4 | extern crate foo; - | ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate + | ----------------- one version of crate `foo` used here, as a direct dependency of the current crate 5 | 6 | pub struct Struct; | ----------------- this type implements the required trait diff --git a/tests/run-make/crate-loading/multiple-dep-versions-1.rs b/tests/run-make/crate-loading/multiple-dep-versions-1.rs index d81462504dd57..bfeabccf5c146 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-1.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions-1.rs @@ -5,8 +5,11 @@ pub trait Trait { fn foo(&self); fn bar(); } +pub trait Trait2 {} impl Trait for Type { fn foo(&self) {} fn bar() {} } pub fn do_something(_: X) {} +pub fn do_something_type(_: Type) {} +pub fn do_something_trait(_: Box) {} diff --git a/tests/run-make/crate-loading/multiple-dep-versions-2.rs b/tests/run-make/crate-loading/multiple-dep-versions-2.rs index 0a566fe2c6051..682d1ff64b822 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-2.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions-2.rs @@ -5,8 +5,12 @@ pub trait Trait { fn foo(&self); fn bar(); } +pub trait Trait2 {} +impl Trait2 for Type {} impl Trait for Type { fn foo(&self) {} fn bar() {} } pub fn do_something(_: X) {} +pub fn do_something_type(_: Type) {} +pub fn do_something_trait(_: Box) {} diff --git a/tests/run-make/crate-loading/multiple-dep-versions-3.rs b/tests/run-make/crate-loading/multiple-dep-versions-3.rs index f5c4d1baa811a..07444511472fa 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-3.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions-3.rs @@ -2,7 +2,7 @@ #![crate_type = "rlib"] extern crate dependency; -pub use dependency::Type; +pub use dependency::{Trait2, Type, do_something_trait, do_something_type}; pub struct OtherType; impl dependency::Trait for OtherType { fn foo(&self) {} diff --git a/tests/run-make/crate-loading/multiple-dep-versions.rs b/tests/run-make/crate-loading/multiple-dep-versions.rs index c68a9e6489f54..3a4a20d38fc87 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions.rs @@ -1,11 +1,13 @@ extern crate dep_2_reexport; extern crate dependency; -use dep_2_reexport::{OtherType, Type}; -use dependency::{Trait, do_something}; +use dep_2_reexport::{OtherType, Trait2, Type}; +use dependency::{Trait, do_something, do_something_trait, do_something_type}; fn main() { do_something(Type); Type.foo(); Type::bar(); do_something(OtherType); + do_something_type(Type); + do_something_trait(Box::new(Type) as Box); } diff --git a/tests/run-make/crate-loading/multiple-dep-versions.stderr b/tests/run-make/crate-loading/multiple-dep-versions.stderr index 5888aad8f37bc..6e1d6111b5810 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions.stderr +++ b/tests/run-make/crate-loading/multiple-dep-versions.stderr @@ -17,9 +17,9 @@ LL | pub trait Trait { ::: replaced | LL | extern crate dep_2_reexport; - | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` + | ---------------------------- one version of crate `dependency` 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 + | ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate | ::: replaced | @@ -51,7 +51,7 @@ LL | fn foo(&self); | ::: replaced | -LL | use dependency::{Trait, do_something}; +LL | use dependency::{Trait, do_something, do_something_trait, do_something_type}; | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency` | ::: replaced @@ -76,7 +76,7 @@ LL | fn bar(); | ::: replaced | -LL | use dependency::{Trait, do_something}; +LL | use dependency::{Trait, do_something, do_something_trait, do_something_type}; | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency` | ::: replaced @@ -101,9 +101,9 @@ LL | pub trait Trait { ::: replaced | LL | extern crate dep_2_reexport; - | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` + | ---------------------------- one version of crate `dependency` 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 + | ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate | ::: replaced | @@ -121,7 +121,71 @@ note: required by a bound in `do_something` LL | pub fn do_something(_: X) {} | ^^^^^ required by this bound in `do_something` -error: aborting due to 4 previous errors +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` used here, as a dependency of crate `foo` +LL | extern crate dependency; + | ------------------------ one version of crate `dependency` 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); + | ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` used here, as a dependency of crate `foo` +LL | extern crate dependency; + | ------------------------ one version of crate `dependency` 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) {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0277, E0599. +Some errors have detailed explanations: E0277, E0308, E0599. For more information about an error, try `rustc --explain E0277`. \ No newline at end of file diff --git a/tests/ui/mismatched_types/similar_paths_primitive.rs b/tests/ui/mismatched_types/similar_paths_primitive.rs index 98890a15d98b1..a58fe68b86381 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.rs +++ b/tests/ui/mismatched_types/similar_paths_primitive.rs @@ -1,14 +1,22 @@ #![allow(non_camel_case_types)] -struct bool; -struct str; +struct bool; //~ NOTE the other `bool` is defined in the current crate +struct str; //~ NOTE the other `str` is defined in the current crate -fn foo(_: bool) {} -fn bar(_: &str) {} +fn foo(_: bool) {} //~ NOTE function defined here +fn bar(_: &str) {} //~ NOTE function defined here fn main() { foo(true); //~^ ERROR mismatched types [E0308] + //~| NOTE expected `bool`, found a different `bool` + //~| NOTE arguments to this function are incorrect + //~| NOTE `bool` and `bool` have similar names, but are actually distinct types + //~| NOTE one `bool` is a primitive defined by the language bar("hello"); //~^ ERROR mismatched types [E0308] + //~| NOTE expected `str`, found a different `str` + //~| NOTE arguments to this function are incorrect + //~| NOTE `str` and `str` have similar names, but are actually distinct types + //~| NOTE one `str` is a primitive defined by the language } diff --git a/tests/ui/mismatched_types/similar_paths_primitive.stderr b/tests/ui/mismatched_types/similar_paths_primitive.stderr index 0530bf5863e69..cf26234dba857 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.stderr +++ b/tests/ui/mismatched_types/similar_paths_primitive.stderr @@ -6,9 +6,9 @@ LL | foo(true); | | | arguments to this function are incorrect | - = note: bool and `bool` have similar names, but are actually distinct types - = note: bool is a primitive defined by the language -note: `bool` is defined in the current crate + = note: `bool` and `bool` have similar names, but are actually distinct types + = note: one `bool` is a primitive defined by the language +note: the other `bool` is defined in the current crate --> $DIR/similar_paths_primitive.rs:3:1 | LL | struct bool; @@ -20,16 +20,16 @@ LL | fn foo(_: bool) {} | ^^^ ------- error[E0308]: mismatched types - --> $DIR/similar_paths_primitive.rs:12:9 + --> $DIR/similar_paths_primitive.rs:16:9 | LL | bar("hello"); | --- ^^^^^^^ expected `str`, found a different `str` | | | arguments to this function are incorrect | - = note: str and `str` have similar names, but are actually distinct types - = note: str is a primitive defined by the language -note: `str` is defined in the current crate + = note: `str` and `str` have similar names, but are actually distinct types + = note: one `str` is a primitive defined by the language +note: the other `str` is defined in the current crate --> $DIR/similar_paths_primitive.rs:4:1 | LL | struct str; diff --git a/tests/ui/type/auxiliary/crate_a1.rs b/tests/ui/type/auxiliary/crate_a1.rs index e2e18500541ef..616493193fd6c 100644 --- a/tests/ui/type/auxiliary/crate_a1.rs +++ b/tests/ui/type/auxiliary/crate_a1.rs @@ -1,6 +1,6 @@ pub struct Foo; -pub trait Bar{} +pub trait Bar {} pub fn bar() -> Box { unimplemented!() diff --git a/tests/ui/type/auxiliary/crate_a2.rs b/tests/ui/type/auxiliary/crate_a2.rs index d16a4ac10e0c4..57a7685b77c4f 100644 --- a/tests/ui/type/auxiliary/crate_a2.rs +++ b/tests/ui/type/auxiliary/crate_a2.rs @@ -1,6 +1,6 @@ pub struct Foo; -pub trait Bar{} +pub trait Bar {} pub fn bar() -> Box { unimplemented!() diff --git a/tests/ui/type/type-mismatch-same-crate-name.rs b/tests/ui/type/type-mismatch-same-crate-name.rs index da76616523826..e88960364a251 100644 --- a/tests/ui/type/type-mismatch-same-crate-name.rs +++ b/tests/ui/type/type-mismatch-same-crate-name.rs @@ -3,25 +3,32 @@ // This tests the extra note reported when a type error deals with // seemingly identical types. -// The main use case of this error is when there are two crates -// (generally different versions of the same crate) with the same name -// causing a type mismatch. Here, we simulate that error using block-scoped -// aliased `extern crate` declarations. +// The main use case of this error is when there are two crates imported +// with the same name, causing a type mismatch. Here, we simulate that error +// using block-scoped aliased `extern crate` declarations. +// This is *not* the same case as two different crate versions in the +// dependency tree. That is tested in `tests/run-make/crate-loading/`. fn main() { let foo2 = {extern crate crate_a2 as a; a::Foo}; + //~^ NOTE one type comes from crate `crate_a2` used here, which is renamed locally to `a` + //~| NOTE one trait comes from crate `crate_a2` used here, which is renamed locally to `a` let bar2 = {extern crate crate_a2 as a; a::bar()}; { extern crate crate_a1 as a; + //~^ NOTE one type comes from crate `crate_a1` used here, which is renamed locally to `a` + //~| NOTE one trait comes from crate `crate_a1` used here, which is renamed locally to `a` a::try_foo(foo2); //~^ ERROR mismatched types - //~| perhaps two different versions of crate `crate_a1` - //~| expected `main::a::Foo`, found a different `main::a::Foo` + //~| NOTE expected `main::a::Foo`, found a different `main::a::Foo` + //~| NOTE arguments to this function are incorrect + //~| NOTE two types coming from two different crates are different types even if they look the same + //~| NOTE function defined here a::try_bar(bar2); //~^ ERROR mismatched types - //~| perhaps two different versions of crate `crate_a1` - //~| expected trait `main::a::Bar` - //~| expected struct `Box<(dyn main::a::Bar + 'static)>` - //~| found struct `Box` + //~| NOTE expected trait `main::a::Bar`, found a different trait `main::a::Bar` + //~| NOTE arguments to this function are incorrect + //~| NOTE two types coming from two different crates are different types even if they look the same + //~| NOTE function defined here } } diff --git a/tests/ui/type/type-mismatch-same-crate-name.stderr b/tests/ui/type/type-mismatch-same-crate-name.stderr index 504812f5867a6..7b791549f5632 100644 --- a/tests/ui/type/type-mismatch-same-crate-name.stderr +++ b/tests/ui/type/type-mismatch-same-crate-name.stderr @@ -1,23 +1,29 @@ error[E0308]: mismatched types - --> $DIR/type-mismatch-same-crate-name.rs:16:20 + --> $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: `main::a::Foo` and `main::a::Foo` have similar names, but are actually distinct types -note: `main::a::Foo` is defined in crate `crate_a2` +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; - | ^^^^^^^^^^^^^^ -note: `main::a::Foo` is defined in crate `crate_a1` - --> $DIR/auxiliary/crate_a1.rs:1:1 + | ^^^^^^^^^^^^^^ this is the found type `crate_a2::Foo` + | + ::: $DIR/auxiliary/crate_a1.rs:1:1 | LL | pub struct Foo; - | ^^^^^^^^^^^^^^ - = note: perhaps two different versions of crate `crate_a1` are being used? + | ^^^^^^^^^^^^^^ 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` used here, which is renamed locally to `a` +... +LL | extern crate crate_a1 as a; + | --------------------------- one type comes from crate `crate_a1` used here, which is renamed locally to `a` note: function defined here --> $DIR/auxiliary/crate_a1.rs:10:8 | @@ -25,16 +31,31 @@ LL | pub fn try_foo(x: Foo){} | ^^^^^^^ error[E0308]: mismatched types - --> $DIR/type-mismatch-same-crate-name.rs:20:20 + --> $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: expected struct `Box<(dyn main::a::Bar + 'static)>` - found struct `Box` - = note: perhaps two different versions of crate `crate_a1` are being used? +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` used here, which is renamed locally to `a` +... +LL | extern crate crate_a1 as a; + | --------------------------- one trait comes from crate `crate_a1` used here, which is renamed locally to `a` note: function defined here --> $DIR/auxiliary/crate_a1.rs:11:8 |