diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 44602e6289940..7f85a2ad839bf 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -4089,7 +4089,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 }; @@ -4100,49 +4100,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/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 4305d4160ebf5..a1eace22fcbc8 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 @@ -467,7 +467,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 +1949,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 +2313,7 @@ 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 check_same_trait_different_version( &self, err: &mut Diag<'_>, trait_pred: ty::PolyTraitPredicate<'tcx>, @@ -2442,40 +2330,69 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_impls }; + let krate = self.tcx.crate_name(trait_pred.def_id().krate); + let name = self.tcx.item_name(trait_pred.def_id()); 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()) + .filter(|trait_def_id| { + trait_def_id.krate != trait_pred.def_id().krate + && (self.tcx.def_path_str(trait_def_id) == required_trait_path + || self.tcx.crate_name(trait_def_id.krate) == krate + && self.tcx.item_name(trait_def_id) == name) + }) .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())), + let mut trait_is_impl = false; + + if !traits_with_same_path.is_empty() { + let mut span: MultiSpan = self.tcx.def_span(trait_pred.def_id()).into(); + span.push_span_label( + self.tcx.def_span(trait_pred.def_id()), + "this is the required trait", ); - self.note_two_crate_versions(trait_with_same_path, err); suggested = true; + 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; + } + + for candidate_def_id in trait_impls { + let Some(impl_trait_header) = self.tcx.impl_trait_header(candidate_def_id) + else { + continue; + }; + let candidate_span = + self.tcx.def_span(impl_trait_header.trait_ref.skip_binder().def_id); + span.push_span_label(candidate_span, "this is the implemented trait"); + trait_is_impl = true; + } + } + if !trait_is_impl { + for (_, def_id) in traits_with_same_path { + span.push_span_label( + self.tcx.def_span(def_id), + "this is the trait that was imported", + ); + } + } + self.note_two_crate_versions(trait_pred.def_id(), span, err); } suggested } - 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 +2453,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 9052031ce4fd8..e2b99a0c76f63 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/run-make/crate-loading-crate-depends-on-itself/foo.stderr b/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr index 9433a0ba00e80..18ab39ecd587b 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,14 @@ 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 | ::: 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 + | --------------- this is the implemented trait + = 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..b631ec6016511 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions.stderr +++ b/tests/run-make/crate-loading/multiple-dep-versions.stderr @@ -9,26 +9,14 @@ 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 - | - ::: 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 + | --------------- this is the implemented trait + = help: the trait `Trait` is implemented for `dependency::Type` note: required by a bound in `do_something` --> replaced | @@ -45,14 +33,7 @@ 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 required trait | ::: replaced | @@ -69,15 +50,7 @@ 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 required trait | ::: replaced | @@ -100,21 +73,9 @@ LL | pub trait 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 - | - ::: replaced - | LL | pub trait Trait { - | --------------- this is the found trait - = help: you can use `cargo tree` to explore your dependency tree + | --------------- this is the implemented trait + = help: the trait `Trait` is implemented for `dependency::Type` note: required by a bound in `do_something` --> 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..cdc8610b7eae3 100644 --- a/tests/ui/traits/bound/same-crate-name.rs +++ b/tests/ui/traits/bound/same-crate-name.rs @@ -32,13 +32,13 @@ 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 // 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 // We don't want to see the "version mismatch" help message here // because `other_variant_implements_mismatched_trait` @@ -46,6 +46,7 @@ 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 // We don't want to see the "version mismatch" help message here // because `ImplementsTraitForUsize` only has @@ -53,5 +54,6 @@ 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 } } diff --git a/tests/ui/traits/bound/same-crate-name.stderr b/tests/ui/traits/bound/same-crate-name.stderr index 71a8159fd8906..cafab863e9b02 100644 --- a/tests/ui/traits/bound/same-crate-name.stderr +++ b/tests/ui/traits/bound/same-crate-name.stderr @@ -6,12 +6,16 @@ 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 required trait + | + ::: $DIR/auxiliary/crate_a2.rs:3:1 + | +LL | pub trait Bar {} + | ------------- this is the implemented trait = 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 @@ -20,13 +24,23 @@ LL | pub fn try_foo(x: impl Bar) {} | ^^^ required by this bound in `try_foo` error[E0277]: the trait bound `DoesNotImplementTrait: main::a::Bar` is not satisfied - --> $DIR/same-crate-name.rs:40:20 + --> $DIR/same-crate-name.rs:39:20 | LL | a::try_foo(implements_no_traits); | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait` | | | 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 required trait + | + ::: $DIR/auxiliary/crate_a2.rs:3:1 + | +LL | pub trait Bar {} + | ------------- this is the trait that was imported = 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 @@ -42,12 +56,16 @@ LL | a::try_foo(other_variant_implements_mismatched_trait); | | | 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 required trait + | + ::: $DIR/auxiliary/crate_a2.rs:3:1 + | +LL | pub trait Bar {} + | ------------- this is the implemented trait = 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 +74,23 @@ 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:54: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 required trait + | + ::: $DIR/auxiliary/crate_a2.rs:3:1 + | +LL | pub trait Bar {} + | ------------- this is the trait that was imported = 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/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 |