diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index aacd2f511a3c3..020c8370b85e7 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -4085,7 +4085,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err: &mut Diag<'_>, item_def_id: DefId, hir_id: hir::HirId, - rcvr_ty: Option>, + rcvr_ty: Option>, ) -> bool { let hir_id = self.tcx.parent_hir_id(hir_id); let Some(traits) = self.tcx.in_scope_traits(hir_id) else { return false }; @@ -4096,49 +4096,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !self.tcx.is_trait(trait_def_id) { return false; } - let krate = self.tcx.crate_name(trait_def_id.krate); - let name = self.tcx.item_name(trait_def_id); - let candidates: Vec<_> = traits - .iter() - .filter(|c| { - c.def_id.krate != trait_def_id.krate - && self.tcx.crate_name(c.def_id.krate) == krate - && self.tcx.item_name(c.def_id) == name - }) - .map(|c| (c.def_id, c.import_ids.get(0).cloned())) - .collect(); - if candidates.is_empty() { + let hir::Node::Expr(rcvr) = self.tcx.hir_node(hir_id) else { return false; - } - let item_span = self.tcx.def_span(item_def_id); - let msg = format!( - "there are multiple different versions of crate `{krate}` in the dependency graph", - ); - let trait_span = self.tcx.def_span(trait_def_id); - let mut multi_span: MultiSpan = trait_span.into(); - multi_span.push_span_label(trait_span, "this is the trait that is needed".to_string()); - let descr = self.tcx.associated_item(item_def_id).descr(); - let rcvr_ty = - rcvr_ty.map(|t| format!("`{t}`")).unwrap_or_else(|| "the receiver".to_string()); - multi_span - .push_span_label(item_span, format!("the {descr} is available for {rcvr_ty} here")); - for (def_id, import_def_id) in candidates { - if let Some(import_def_id) = import_def_id { - multi_span.push_span_label( - self.tcx.def_span(import_def_id), - format!( - "`{name}` imported here doesn't correspond to the right version of crate \ - `{krate}`", - ), - ); - } - multi_span.push_span_label( - self.tcx.def_span(def_id), - "this is the trait that was imported".to_string(), - ); - } - err.span_note(multi_span, msg); - true + }; + let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, rcvr_ty.into_iter()); + let trait_pred = ty::Binder::dummy(ty::TraitPredicate { + trait_ref, + polarity: ty::PredicatePolarity::Positive, + }); + let obligation = Obligation::new(self.tcx, self.misc(rcvr.span), self.param_env, trait_ref); + self.err_ctxt().note_different_trait_with_same_name(err, &obligation, trait_pred) } /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else` 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 e18e294635b52..b280a6ec55af7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -51,11 +51,8 @@ use std::path::PathBuf; use std::{cmp, fmt, iter}; use rustc_abi::ExternAbi; -use rustc_ast::join_path_syms; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; -use rustc_errors::{ - Applicability, Diag, DiagStyledString, IntoDiagArg, MultiSpan, StringPart, pluralize, -}; +use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -66,15 +63,12 @@ use rustc_middle::bug; use rustc_middle::dep_graph::DepContext; use rustc_middle::traits::PatternOriginExpr; use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt}; -use rustc_middle::ty::print::{ - PrintError, PrintTraitRefExt as _, WrapBinderMode, with_forced_trimmed_paths, -}; +use rustc_middle::ty::print::{PrintTraitRefExt as _, WrapBinderMode, with_forced_trimmed_paths}; use rustc_middle::ty::{ self, List, ParamEnv, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; -use rustc_span::def_id::LOCAL_CRATE; -use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Pos, Span, Symbol, sym}; +use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Pos, Span, sym}; use tracing::{debug, instrument}; use crate::error_reporting::TypeErrCtxt; @@ -216,201 +210,6 @@ 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>) -> 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; - use ty::print::Printer; - - struct ConflictingPathPrinter<'tcx> { - tcx: TyCtxt<'tcx>, - segments: Vec, - } - - impl<'tcx> Printer<'tcx> for ConflictingPathPrinter<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { - self.tcx - } - - fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> { - unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs` - } - - fn print_type(&mut self, _ty: Ty<'tcx>) -> Result<(), PrintError> { - unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs` - } - - fn print_dyn_existential( - &mut self, - _predicates: &'tcx ty::List>, - ) -> Result<(), PrintError> { - unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs` - } - - fn print_const(&mut self, _ct: ty::Const<'tcx>) -> Result<(), PrintError> { - unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs` - } - - fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> { - self.segments = vec![self.tcx.crate_name(cnum)]; - Ok(()) - } - - fn print_path_with_qualified( - &mut self, - _self_ty: Ty<'tcx>, - _trait_ref: Option>, - ) -> Result<(), PrintError> { - Err(fmt::Error) - } - - fn print_path_with_impl( - &mut self, - _print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, - _self_ty: Ty<'tcx>, - _trait_ref: Option>, - ) -> Result<(), PrintError> { - Err(fmt::Error) - } - - fn print_path_with_simple( - &mut self, - print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, - disambiguated_data: &DisambiguatedDefPathData, - ) -> Result<(), PrintError> { - print_prefix(self)?; - self.segments.push(disambiguated_data.as_sym(true)); - Ok(()) - } - - fn print_path_with_generic_args( - &mut self, - print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, - _args: &[GenericArg<'tcx>], - ) -> Result<(), PrintError> { - print_prefix(self) - } - } - - 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}]; - if did1.krate != did2.krate { - let abs_path = |def_id| { - let mut p = ConflictingPathPrinter { tcx: self.tcx, segments: vec![] }; - p.print_def_path(def_id, &[]).map(|_| p.segments) - }; - - // 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 = expected_str == found_str || expected_abs == found_abs; - if same_path { - // 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 { - (join_path_syms(&expected_abs), join_path_syms(&found_abs)) - } else { - (expected_str, found_str) - }; - - // 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!( - "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!( - "two types coming from two different crates are different types even \ - if they look the same", - ) - }; - 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) => { // if they are both "path types", there's a chance of ambiguity @@ -418,11 +217,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) = (exp_found.expected.kind(), exp_found.found.kind()) { - return report_path_match(err, exp_adt.did(), found_adt.did(), "type"); + return self.check_same_definition_different_crate( + err, + exp_adt.did(), + [found_adt.did()].into_iter(), + |did| vec![self.tcx.def_span(did)], + "type", + ); } } TypeError::Traits(ref exp_found) => { - return report_path_match(err, exp_found.expected, exp_found.found, "trait"); + return self.check_same_definition_different_crate( + err, + exp_found.expected, + [exp_found.found].into_iter(), + |did| vec![self.tcx.def_span(did)], + "trait", + ); } _ => (), // FIXME(#22750) handle traits and stuff } 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 373819d96f4a9..f7e904705cc9e 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 @@ -1,3 +1,4 @@ +// ignore-tidy-filelength use core::ops::ControlFlow; use std::borrow::Cow; use std::path::PathBuf; @@ -467,7 +468,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span, leaf_trait_predicate, ); - self.note_trait_version_mismatch(&mut err, leaf_trait_predicate); + self.note_different_trait_with_same_name(&mut err, &obligation, leaf_trait_predicate); self.note_adt_version_mismatch(&mut err, leaf_trait_predicate); self.suggest_remove_await(&obligation, &mut err); self.suggest_derive(&obligation, &mut err, leaf_trait_predicate); @@ -1949,115 +1950,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { impl_candidates }; - // We'll check for the case where the reason for the mismatch is that the trait comes from - // one crate version and the type comes from another crate version, even though they both - // are from the same crate. - let trait_def_id = trait_pred.def_id(); - let trait_name = self.tcx.item_name(trait_def_id); - let crate_name = self.tcx.crate_name(trait_def_id.krate); - if let Some(other_trait_def_id) = self.tcx.all_traits_including_private().find(|def_id| { - trait_name == self.tcx.item_name(trait_def_id) - && trait_def_id.krate != def_id.krate - && crate_name == self.tcx.crate_name(def_id.krate) - }) { - // We've found two different traits with the same name, same crate name, but - // different crate `DefId`. We highlight the traits. - - let found_type = - if let ty::Adt(def, _) = trait_pred.self_ty().skip_binder().peel_refs().kind() { - Some(def.did()) - } else { - None - }; - let candidates = if impl_candidates.is_empty() { - alternative_candidates(trait_def_id) - } else { - impl_candidates.into_iter().map(|cand| cand.trait_ref).collect() - }; - let mut span: MultiSpan = self.tcx.def_span(trait_def_id).into(); - span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait"); - for (sp, label) in [trait_def_id, other_trait_def_id] - .iter() - // The current crate-version might depend on another version of the same crate - // (Think "semver-trick"). Do not call `extern_crate` in that case for the local - // crate as that doesn't make sense and ICEs (#133563). - .filter(|def_id| !def_id.is_local()) - .filter_map(|def_id| self.tcx.extern_crate(def_id.krate)) - .map(|data| { - let dependency = if data.dependency_of == LOCAL_CRATE { - "direct dependency of the current crate".to_string() - } else { - let dep = self.tcx.crate_name(data.dependency_of); - format!("dependency of crate `{dep}`") - }; - ( - data.span, - format!("one version of crate `{crate_name}` used here, as a {dependency}"), - ) - }) - { - span.push_span_label(sp, label); - } - let mut points_at_type = false; - if let Some(found_type) = found_type { - span.push_span_label( - self.tcx.def_span(found_type), - "this type doesn't implement the required trait", - ); - for trait_ref in candidates { - if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind() - && let candidate_def_id = def.did() - && let Some(name) = self.tcx.opt_item_name(candidate_def_id) - && let Some(found) = self.tcx.opt_item_name(found_type) - && name == found - && candidate_def_id.krate != found_type.krate - && self.tcx.crate_name(candidate_def_id.krate) - == self.tcx.crate_name(found_type.krate) - { - // A candidate was found of an item with the same name, from two separate - // versions of the same crate, let's clarify. - let candidate_span = self.tcx.def_span(candidate_def_id); - span.push_span_label( - candidate_span, - "this type implements the required trait", - ); - points_at_type = true; - } - } - } - span.push_span_label(self.tcx.def_span(other_trait_def_id), "this is the found trait"); - err.highlighted_span_note( - span, - vec![ - StringPart::normal("there are ".to_string()), - StringPart::highlighted("multiple different versions".to_string()), - StringPart::normal(" of crate `".to_string()), - StringPart::highlighted(format!("{crate_name}")), - StringPart::normal("` in the dependency graph".to_string()), - ], - ); - if points_at_type { - // We only clarify that the same type from different crate versions are not the - // same when we *find* the same type coming from different crate versions, otherwise - // it could be that it was a type provided by a different crate than the one that - // provides the trait, and mentioning this adds verbosity without clarification. - err.highlighted_note(vec![ - StringPart::normal( - "two types coming from two different versions of the same crate are \ - different types " - .to_string(), - ), - StringPart::highlighted("even if they look the same".to_string()), - ]); - } - err.highlighted_help(vec![ - StringPart::normal("you can use `".to_string()), - StringPart::highlighted("cargo tree".to_string()), - StringPart::normal("` to explore your dependency tree".to_string()), - ]); - return true; - } - if let [single] = &impl_candidates { // If we have a single implementation, try to unify it with the trait ref // that failed. This should uncover a better hint for what *is* implemented. @@ -2422,10 +2314,81 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait - /// with the same path as `trait_ref`, a help message about - /// a probable version mismatch is added to `err` - fn note_trait_version_mismatch( + fn get_extern_crate_renamed_symbol(&self, trait_def_id: DefId) -> Option { + if !trait_def_id.is_local() + && let Some(data) = self.tcx.extern_crate(trait_def_id.krate) + && let rustc_session::cstore::ExternCrateSource::Extern(def_id) = data.src + { + self.tcx.opt_item_name(def_id) + } else { + None + } + } + + pub fn check_same_definition_different_crate( + &self, + err: &mut Diag<'_>, + expected_did: DefId, + found_dids: impl Iterator, + get_impls: F, + ty: &str, + ) -> bool + where + F: Fn(DefId) -> Vec, + { + let krate = self.tcx.crate_name(expected_did.krate); + let name = self.tcx.item_name(expected_did); + let locally_renamed_krate = self + .get_extern_crate_renamed_symbol(expected_did) + .map_or(None, |s| if s != krate { Some(s) } else { None }); + let definitions_with_same_path: UnordSet<_> = found_dids + .filter(|def_id| { + def_id.krate != expected_did.krate + && (locally_renamed_krate == self.get_extern_crate_renamed_symbol(*def_id) + || self.tcx.crate_name(def_id.krate) == krate) + && self.tcx.item_name(def_id) == name + }) + .map(|def_id| (self.tcx.def_path_str(def_id), def_id)) + .collect(); + + let definitions_with_same_path = + definitions_with_same_path.into_items().into_sorted_stable_ord_by_key(|(p, _)| p); + let mut suggested = false; + let mut trait_is_impl = false; + + if !definitions_with_same_path.is_empty() { + let mut span: MultiSpan = self.tcx.def_span(expected_did).into(); + span.push_span_label( + self.tcx.def_span(expected_did), + format!("this is the expected {ty}"), + ); + suggested = true; + for (_, definition_with_same_path) in &definitions_with_same_path { + let definitions_impls = get_impls(*definition_with_same_path); + if definitions_impls.is_empty() { + continue; + } + + for candidate_span in definitions_impls { + span.push_span_label(candidate_span, format!("this is the found {ty}")); + trait_is_impl = true; + } + } + if !trait_is_impl { + for (_, def_id) in definitions_with_same_path { + span.push_span_label( + self.tcx.def_span(def_id), + format!("this is the {ty} that was imported"), + ); + } + } + self.note_two_crate_versions(expected_did, span, err); + err.help("you can use `cargo tree` to explore your dependency tree"); + } + suggested + } + + fn check_same_trait_different_version( &self, err: &mut Diag<'_>, trait_pred: ty::PolyTraitPredicate<'tcx>, @@ -2436,46 +2399,28 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_def_id, trait_pred.skip_binder().self_ty(), |impl_def_id| { - trait_impls.push(impl_def_id); + let impl_trait_header = self.tcx.impl_trait_header(impl_def_id); + trait_impls + .push(self.tcx.def_span(impl_trait_header.trait_ref.skip_binder().def_id)); }, ); trait_impls }; - - let required_trait_path = self.tcx.def_path_str(trait_pred.def_id()); - let traits_with_same_path: UnordSet<_> = self - .tcx - .visible_traits() - .filter(|trait_def_id| *trait_def_id != trait_pred.def_id()) - .map(|trait_def_id| (self.tcx.def_path_str(trait_def_id), trait_def_id)) - .filter(|(p, _)| *p == required_trait_path) - .collect(); - - let traits_with_same_path = - traits_with_same_path.into_items().into_sorted_stable_ord_by_key(|(p, _)| p); - let mut suggested = false; - for (_, trait_with_same_path) in traits_with_same_path { - let trait_impls = get_trait_impls(trait_with_same_path); - if trait_impls.is_empty() { - continue; - } - let impl_spans: Vec<_> = - trait_impls.iter().map(|impl_def_id| self.tcx.def_span(*impl_def_id)).collect(); - err.span_help( - impl_spans, - format!("trait impl{} with same name found", pluralize!(trait_impls.len())), - ); - self.note_two_crate_versions(trait_with_same_path, err); - suggested = true; - } - suggested + self.check_same_definition_different_crate( + err, + trait_pred.def_id(), + self.tcx.visible_traits(), + get_trait_impls, + "trait", + ) } - fn note_two_crate_versions(&self, did: DefId, err: &mut Diag<'_>) { + fn note_two_crate_versions(&self, did: DefId, sp: impl Into, err: &mut Diag<'_>) { let crate_name = self.tcx.crate_name(did.krate); - let crate_msg = - format!("perhaps two different versions of crate `{crate_name}` are being used?"); - err.note(crate_msg); + let crate_msg = format!( + "there are multiple different versions of crate `{crate_name}` in the dependency graph" + ); + err.span_note(sp, crate_msg); } fn note_adt_version_mismatch( @@ -2536,8 +2481,76 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { for (similar_item, _) in similar_items { err.span_help(self.tcx.def_span(similar_item), "item with same name found"); - self.note_two_crate_versions(similar_item, err); + self.note_two_crate_versions(similar_item, MultiSpan::new(), err); + } + } + + fn check_same_name_different_path( + &self, + err: &mut Diag<'_>, + obligation: &PredicateObligation<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) -> bool { + let mut suggested = false; + let trait_def_id = trait_pred.def_id(); + let trait_has_same_params = |other_trait_def_id: DefId| -> bool { + let trait_generics = self.tcx.generics_of(trait_def_id); + let other_trait_generics = self.tcx.generics_of(other_trait_def_id); + + if trait_generics.count() != other_trait_generics.count() { + return false; + } + trait_generics.own_params.iter().zip(other_trait_generics.own_params.iter()).all( + |(a, b)| { + (matches!(a.kind, ty::GenericParamDefKind::Type { .. }) + && matches!(b.kind, ty::GenericParamDefKind::Type { .. })) + || (matches!(a.kind, ty::GenericParamDefKind::Lifetime,) + && matches!(b.kind, ty::GenericParamDefKind::Lifetime)) + || (matches!(a.kind, ty::GenericParamDefKind::Const { .. }) + && matches!(b.kind, ty::GenericParamDefKind::Const { .. })) + }, + ) + }; + let trait_name = self.tcx.item_name(trait_def_id); + if let Some(other_trait_def_id) = self.tcx.all_traits_including_private().find(|def_id| { + trait_def_id != *def_id + && trait_name == self.tcx.item_name(def_id) + && trait_has_same_params(*def_id) + && self.predicate_must_hold_modulo_regions(&Obligation::new( + self.tcx, + obligation.cause.clone(), + obligation.param_env, + trait_pred.map_bound(|tr| ty::TraitPredicate { + trait_ref: ty::TraitRef::new(self.tcx, *def_id, tr.trait_ref.args), + ..tr + }), + )) + }) { + err.note(format!( + "`{}` implements similarly named `{}`, but not `{}`", + trait_pred.self_ty(), + self.tcx.def_path_str(other_trait_def_id), + trait_pred.print_modifiers_and_trait_path() + )); + suggested = true; + } + suggested + } + + /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait + /// with the same path as `trait_ref`, a help message about a multiple different + /// versions of the same crate is added to `err`. Otherwise if it implements another + /// trait with the same name, a note message about a similarly named trait is added to `err`. + pub fn note_different_trait_with_same_name( + &self, + err: &mut Diag<'_>, + obligation: &PredicateObligation<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) -> bool { + if self.check_same_trait_different_version(err, trait_pred) { + return true; } + self.check_same_name_different_path(err, obligation, trait_pred) } /// Add a `::` prefix when comparing paths so that paths with just one item diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index ded5969e83c5c..338913accdcf3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -1,6 +1,6 @@ pub mod ambiguity; pub mod call_kind; -mod fulfillment_errors; +pub mod fulfillment_errors; pub mod on_unimplemented; pub mod on_unimplemented_condition; pub mod on_unimplemented_format; diff --git a/tests/incremental/circular-dependencies.rs b/tests/incremental/circular-dependencies.rs index c7b5b931fbbec..15e21089c9042 100644 --- a/tests/incremental/circular-dependencies.rs +++ b/tests/incremental/circular-dependencies.rs @@ -6,12 +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 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` +//[cfail2]~^ NOTE there are multiple different versions of crate `circular_dependencies` in the dependency graph +//[cfail2]~| NOTE there are multiple different versions of crate `circular_dependencies` in the dependency graph +//[cfail2]~| NOTE this is the expected type +//[cfail2]~| NOTE this is the expected type +//[cfail2]~| NOTE this is the found type +//[cfail2]~| NOTE this is the found type pub fn consume_foo(_: Foo) {} //[cfail2]~^ NOTE function defined here @@ -27,8 +27,6 @@ fn test() { //[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo` //[cfail2]~| NOTE arguments to this function are incorrect //[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] 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 9433a0ba00e80..15445bdce3c39 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 @@ -7,22 +7,15 @@ error[E0277]: the trait bound `foo::Struct: Trait` is not satisfied note: there are multiple different versions of crate `foo` in the dependency graph --> foo-current.rs:7:1 | - 4 | extern crate foo; - | ----------------- 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 7 | pub trait Trait {} - | ^^^^^^^^^^^^^^^ this is the required trait + | ^^^^^^^^^^^^^^^ this is the expected trait | ::: foo-prev.rs:X:Y | - 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 + = help: the trait `Trait` is implemented for `Struct` note: required by a bound in `check_trait` --> foo-current.rs:10:19 | diff --git a/tests/run-make/crate-loading/multiple-dep-versions.stderr b/tests/run-make/crate-loading/multiple-dep-versions.stderr index dea08bb96c979..00788196c0923 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions.stderr +++ b/tests/run-make/crate-loading/multiple-dep-versions.stderr @@ -9,26 +9,15 @@ LL | do_something(Type); note: there are multiple different versions of crate `dependency` in the dependency graph --> replaced | -LL | pub struct Type(pub i32); - | --------------- this type implements the required trait LL | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the required trait - | - ::: 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 + | ^^^^^^^^^^^^^^^ this is the expected trait | ::: replaced | -LL | pub struct Type; - | --------------- this type doesn't implement the required trait LL | 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 + = help: the trait `Trait` is implemented for `dependency::Type` note: required by a bound in `do_something` --> replaced | @@ -45,19 +34,13 @@ note: there are multiple different versions of crate `dependency` in the depende --> replaced | LL | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the trait that is needed -LL | fn foo(&self); - | -------------- the method is available for `dep_2_reexport::Type` here - | - ::: replaced - | -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` + | ^^^^^^^^^^^^^^^ this is the expected trait | ::: replaced | LL | pub trait Trait { | --------------- this is the trait that was imported + = help: you can use `cargo tree` to explore your dependency tree error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope --> replaced @@ -69,20 +52,13 @@ note: there are multiple different versions of crate `dependency` in the depende --> replaced | LL | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the trait that is needed -LL | fn foo(&self); -LL | fn bar(); - | --------- the associated function is available for `dep_2_reexport::Type` here - | - ::: replaced - | -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` + | ^^^^^^^^^^^^^^^ this is the expected trait | ::: replaced | LL | pub trait Trait { | --------------- this is the trait that was imported + = help: you can use `cargo tree` to explore your dependency tree error[E0277]: the trait bound `OtherType: Trait` is not satisfied --> replaced @@ -96,25 +72,14 @@ note: there are multiple different versions of crate `dependency` in the depende --> replaced | LL | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the required trait - | - ::: 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 - | - ::: replaced - | -LL | pub struct OtherType; - | -------------------- this type doesn't implement the required trait + | ^^^^^^^^^^^^^^^ this is the expected trait | ::: replaced | LL | pub trait Trait { | --------------- this is the found trait = help: you can use `cargo tree` to explore your dependency tree + = help: the trait `Trait` is implemented for `dependency::Type` note: required by a bound in `do_something` --> replaced | @@ -129,23 +94,16 @@ LL | do_something_type(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 +note: there are multiple different versions of crate `dependency` in the dependency graph --> replaced | LL | pub struct Type(pub i32); - | ^^^^^^^^^^^^^^^ this is the expected type `dependency::Type` + | ^^^^^^^^^^^^^^^ this is the expected 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 + | --------------- this is the found type = help: you can use `cargo tree` to explore your dependency tree note: function defined here --> replaced @@ -161,23 +119,16 @@ LL | do_something_trait(Box::new(Type) as Box); | | | 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 +note: there are multiple different versions of crate `dependency` in the dependency graph --> replaced | LL | pub trait Trait2 {} - | ^^^^^^^^^^^^^^^^ this is the expected trait `dependency::Trait2` + | ^^^^^^^^^^^^^^^^ this is the expected trait | ::: 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 + | ---------------- this is the found trait = help: you can use `cargo tree` to explore your dependency tree note: function defined here --> replaced diff --git a/tests/run-make/duplicate-dependency/main.stderr b/tests/run-make/duplicate-dependency/main.stderr index 36d54988788f4..7c43dc261e7b6 100644 --- a/tests/run-make/duplicate-dependency/main.stderr +++ b/tests/run-make/duplicate-dependency/main.stderr @@ -11,7 +11,7 @@ help: item with same name found | LL | pub struct Foo; | ^^^^^^^^^^^^^^ - = note: perhaps two different versions of crate `foo` are being used? + = note: there are multiple different versions of crate `foo` in the dependency graph = note: required for `Bar` to implement `Into` note: required by a bound in `into_foo` --> $DIR/re-export-foo.rs:3:25 diff --git a/tests/ui/traits/bound/same-crate-name.rs b/tests/ui/traits/bound/same-crate-name.rs index 395b963031a55..acd4894612872 100644 --- a/tests/ui/traits/bound/same-crate-name.rs +++ b/tests/ui/traits/bound/same-crate-name.rs @@ -32,13 +32,15 @@ fn main() { extern crate crate_a1 as a; a::try_foo(foo); //~^ ERROR E0277 - //~| HELP trait impl with same name found - //~| NOTE perhaps two different versions of crate `crate_a2` + //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph + //~| HELP you can use `cargo tree` to explore your dependency tree // We don't want to see the "version mismatch" help message here // because `implements_no_traits` has no impl for `Foo` a::try_foo(implements_no_traits); //~^ ERROR E0277 + //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph + //~| HELP you can use `cargo tree` to explore your dependency tree // We don't want to see the "version mismatch" help message here // because `other_variant_implements_mismatched_trait` @@ -46,6 +48,8 @@ fn main() { // only for its `` variant. a::try_foo(other_variant_implements_mismatched_trait); //~^ ERROR E0277 + //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph + //~| HELP you can use `cargo tree` to explore your dependency tree // We don't want to see the "version mismatch" help message here // because `ImplementsTraitForUsize` only has @@ -53,5 +57,7 @@ fn main() { a::try_foo(other_variant_implements_correct_trait); //~^ ERROR E0277 //~| HELP the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` + //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph + //~| HELP you can use `cargo tree` to explore your dependency tree } } diff --git a/tests/ui/traits/bound/same-crate-name.stderr b/tests/ui/traits/bound/same-crate-name.stderr index 71a8159fd8906..c2f19242420b7 100644 --- a/tests/ui/traits/bound/same-crate-name.stderr +++ b/tests/ui/traits/bound/same-crate-name.stderr @@ -6,12 +6,17 @@ LL | a::try_foo(foo); | | | required by a bound introduced by this call | -help: trait impl with same name found - --> $DIR/auxiliary/crate_a2.rs:5:1 +note: there are multiple different versions of crate `crate_a1` in the dependency graph + --> $DIR/auxiliary/crate_a1.rs:1:1 | -LL | impl Bar for Foo {} - | ^^^^^^^^^^^^^^^^ - = note: perhaps two different versions of crate `crate_a2` are being used? +LL | pub trait Bar {} + | ^^^^^^^^^^^^^ this is the expected trait + | + ::: $DIR/auxiliary/crate_a2.rs:3:1 + | +LL | pub trait Bar {} + | ------------- this is the found trait + = help: you can use `cargo tree` to explore your dependency tree = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 @@ -27,6 +32,17 @@ LL | a::try_foo(implements_no_traits); | | | required by a bound introduced by this call | +note: there are multiple different versions of crate `crate_a1` in the dependency graph + --> $DIR/auxiliary/crate_a1.rs:1:1 + | +LL | pub trait Bar {} + | ^^^^^^^^^^^^^ this is the expected trait + | + ::: $DIR/auxiliary/crate_a2.rs:3:1 + | +LL | pub trait Bar {} + | ------------- this is the trait that was imported + = help: you can use `cargo tree` to explore your dependency tree = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 @@ -35,19 +51,24 @@ LL | pub fn try_foo(x: impl Bar) {} | ^^^ required by this bound in `try_foo` error[E0277]: the trait bound `ImplementsWrongTraitConditionally: main::a::Bar` is not satisfied - --> $DIR/same-crate-name.rs:47:20 + --> $DIR/same-crate-name.rs:49:20 | LL | a::try_foo(other_variant_implements_mismatched_trait); | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally` | | | required by a bound introduced by this call | -help: trait impl with same name found - --> $DIR/auxiliary/crate_a2.rs:13:1 +note: there are multiple different versions of crate `crate_a1` in the dependency graph + --> $DIR/auxiliary/crate_a1.rs:1:1 | -LL | impl Bar for ImplementsWrongTraitConditionally {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: perhaps two different versions of crate `crate_a2` are being used? +LL | pub trait Bar {} + | ^^^^^^^^^^^^^ this is the expected trait + | + ::: $DIR/auxiliary/crate_a2.rs:3:1 + | +LL | pub trait Bar {} + | ------------- this is the found trait + = help: you can use `cargo tree` to explore your dependency tree = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 @@ -56,13 +77,24 @@ LL | pub fn try_foo(x: impl Bar) {} | ^^^ required by this bound in `try_foo` error[E0277]: the trait bound `ImplementsTraitForUsize: main::a::Bar` is not satisfied - --> $DIR/same-crate-name.rs:53:20 + --> $DIR/same-crate-name.rs:57:20 | LL | a::try_foo(other_variant_implements_correct_trait); | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize` | | | required by a bound introduced by this call | +note: there are multiple different versions of crate `crate_a1` in the dependency graph + --> $DIR/auxiliary/crate_a1.rs:1:1 + | +LL | pub trait Bar {} + | ^^^^^^^^^^^^^ this is the expected trait + | + ::: $DIR/auxiliary/crate_a2.rs:3:1 + | +LL | pub trait Bar {} + | ------------- this is the trait that was imported + = help: you can use `cargo tree` to explore your dependency tree = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 diff --git a/tests/ui/traits/similarly_named_trait.rs b/tests/ui/traits/similarly_named_trait.rs new file mode 100644 index 0000000000000..1e46ed88ba022 --- /dev/null +++ b/tests/ui/traits/similarly_named_trait.rs @@ -0,0 +1,28 @@ +trait Trait {} //~ HELP this trait has no implementations, consider adding one +trait TraitWithParam {} //~ HELP this trait has no implementations, consider adding one + +mod m { + pub trait Trait {} + pub trait TraitWithParam {} + pub struct St; //~ HELP the trait `Trait` is not implemented for `St` + //~| HELP the trait `TraitWithParam` is not implemented for `St` + impl Trait for St {} + impl TraitWithParam for St {} +} + +fn func(_: T) {} //~ NOTE required by a bound in `func` +//~^ NOTE required by this bound in `func` + +fn func2> (_: T) {} //~ NOTE required by a bound in `func2` +//~^ NOTE required by this bound in `func2` + +fn main() { + func(m::St); //~ ERROR the trait bound `St: Trait` is not satisfied + //~^ NOTE unsatisfied trait bound + //~| NOTE required by a bound introduced by this call + //~| NOTE `St` implements similarly named `m::Trait`, but not `Trait` + func2(m::St); //~ ERROR the trait bound `St: TraitWithParam` is not satisfied + //~^ NOTE unsatisfied trait bound + //~| NOTE required by a bound introduced by this call + //~| NOTE `St` implements similarly named `m::TraitWithParam`, but not `TraitWithParam` +} diff --git a/tests/ui/traits/similarly_named_trait.stderr b/tests/ui/traits/similarly_named_trait.stderr new file mode 100644 index 0000000000000..e6966283b48a7 --- /dev/null +++ b/tests/ui/traits/similarly_named_trait.stderr @@ -0,0 +1,53 @@ +error[E0277]: the trait bound `St: Trait` is not satisfied + --> $DIR/similarly_named_trait.rs:20:10 + | +LL | func(m::St); + | ---- ^^^^^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | +help: the trait `Trait` is not implemented for `St` + --> $DIR/similarly_named_trait.rs:7:5 + | +LL | pub struct St; + | ^^^^^^^^^^^^^ + = note: `St` implements similarly named `m::Trait`, but not `Trait` +help: this trait has no implementations, consider adding one + --> $DIR/similarly_named_trait.rs:1:1 + | +LL | trait Trait {} + | ^^^^^^^^^^^ +note: required by a bound in `func` + --> $DIR/similarly_named_trait.rs:13:12 + | +LL | fn func(_: T) {} + | ^^^^^ required by this bound in `func` + +error[E0277]: the trait bound `St: TraitWithParam` is not satisfied + --> $DIR/similarly_named_trait.rs:24:11 + | +LL | func2(m::St); + | ----- ^^^^^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | +help: the trait `TraitWithParam` is not implemented for `St` + --> $DIR/similarly_named_trait.rs:7:5 + | +LL | pub struct St; + | ^^^^^^^^^^^^^ + = note: `St` implements similarly named `m::TraitWithParam`, but not `TraitWithParam` +help: this trait has no implementations, consider adding one + --> $DIR/similarly_named_trait.rs:2:1 + | +LL | trait TraitWithParam {} + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `func2` + --> $DIR/similarly_named_trait.rs:16:13 + | +LL | fn func2> (_: T) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `func2` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type/type-mismatch-same-crate-name.rs b/tests/ui/type/type-mismatch-same-crate-name.rs index e88960364a251..df6d7aba8fd69 100644 --- a/tests/ui/type/type-mismatch-same-crate-name.rs +++ b/tests/ui/type/type-mismatch-same-crate-name.rs @@ -11,24 +11,22 @@ 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 //~| 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 there are multiple different versions of crate `crate_a1` in the dependency graph //~| NOTE function defined here + //~| HELP you can use `cargo tree` to explore your dependency tree a::try_bar(bar2); //~^ ERROR mismatched types //~| 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 there are multiple different versions of crate `crate_a1` in the dependency graph //~| NOTE function defined here + //~| HELP you can use `cargo tree` to explore your dependency tree } } diff --git a/tests/ui/type/type-mismatch-same-crate-name.stderr b/tests/ui/type/type-mismatch-same-crate-name.stderr index 8fafbfaa93425..2913b994e9529 100644 --- a/tests/ui/type/type-mismatch-same-crate-name.stderr +++ b/tests/ui/type/type-mismatch-same-crate-name.stderr @@ -1,29 +1,22 @@ error[E0308]: mismatched types - --> $DIR/type-mismatch-same-crate-name.rs:21:20 + --> $DIR/type-mismatch-same-crate-name.rs:17: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 +note: there are multiple different versions of crate `crate_a1` in the dependency graph + --> $DIR/auxiliary/crate_a1.rs:1:1 | LL | pub struct Foo; - | ^^^^^^^^^^^^^^ this is the found type `crate_a2::Foo` + | ^^^^^^^^^^^^^^ this is the expected type | - ::: $DIR/auxiliary/crate_a1.rs:1:1 + ::: $DIR/auxiliary/crate_a2.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` 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` + | -------------- this is the found type + = help: you can use `cargo tree` to explore your dependency tree note: function defined here --> $DIR/auxiliary/crate_a1.rs:10:8 | @@ -31,31 +24,24 @@ LL | pub fn try_foo(x: Foo){} | ^^^^^^^ error[E0308]: mismatched types - --> $DIR/type-mismatch-same-crate-name.rs:27:20 + --> $DIR/type-mismatch-same-crate-name.rs:24: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 +note: there are multiple different versions of crate `crate_a1` in the dependency graph + --> $DIR/auxiliary/crate_a1.rs:3:1 | LL | pub trait Bar {} - | ^^^^^^^^^^^^^ this is the found trait `crate_a2::Bar` + | ^^^^^^^^^^^^^ this is the expected trait | - ::: $DIR/auxiliary/crate_a1.rs:3:1 + ::: $DIR/auxiliary/crate_a2.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` + | ------------- this is the found trait + = help: you can use `cargo tree` to explore your dependency tree note: function defined here --> $DIR/auxiliary/crate_a1.rs:11:8 | diff --git a/tests/ui/union/issue-81199.stderr b/tests/ui/union/issue-81199.stderr index 7deba88fc803c..dbc4a0ab55346 100644 --- a/tests/ui/union/issue-81199.stderr +++ b/tests/ui/union/issue-81199.stderr @@ -16,6 +16,7 @@ error[E0277]: the trait bound `T: Pointee` is not satisfied LL | components: PtrComponents, | ^^^^^^^^^^^^^^^^ the trait `Pointee` is not implemented for `T` | + = note: `T` implements similarly named `std::ptr::Pointee`, but not `Pointee` note: required by a bound in `PtrComponents` --> $DIR/issue-81199.rs:11:25 |