diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 5d8383170f0dc..63067deb7b07b 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1556,7 +1556,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // Convert the bounds into obligations. let impl_obligations = traits::predicates_for_generics( - |_, _| cause.clone(), + |_idx, span| { + let misc = traits::ObligationCause::misc(span, self.body_id); + let parent_trait_pred = ty::Binder::dummy(ty::TraitPredicate { + trait_ref: ty::TraitRef::from_method(self.tcx, impl_def_id, substs), + constness: ty::BoundConstness::NotConst, + polarity: ty::ImplPolarity::Positive, + }); + misc.derived_cause(parent_trait_pred, |derived| { + traits::ImplDerivedObligation(Box::new( + traits::ImplDerivedObligationCause { + derived, + impl_def_id, + span, + }, + )) + }) + }, self.param_env, impl_bounds, ); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 62e80659486a8..8166eb8299041 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -101,6 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..))) } + #[instrument(level = "debug", skip(self))] pub fn report_method_error( &self, span: Span, @@ -586,22 +587,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Find all the requirements that come from a local `impl` block. let mut skip_list: FxHashSet<_> = Default::default(); - let mut spanned_predicates: FxHashMap = Default::default(); - for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates + let mut spanned_predicates = FxHashMap::default(); + for (p, parent_p, impl_def_id, cause) in unsatisfied_predicates .iter() .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c))) .filter_map(|(p, parent, c)| match c.code() { - ObligationCauseCode::ImplDerivedObligation(data) => { - Some((&data.derived, p, parent, data.impl_def_id, data)) + ObligationCauseCode::ImplDerivedObligation(data) + if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) => + { + Some((p, parent, data.impl_def_id, data)) } _ => None, }) { - let parent_trait_ref = data.parent_trait_pred; - let path = parent_trait_ref.print_modifiers_and_trait_path(); - let tr_self_ty = parent_trait_ref.skip_binder().self_ty(); - let unsatisfied_msg = "unsatisfied trait bound introduced here"; - let derive_msg = "unsatisfied trait bound introduced in this `derive` macro"; match self.tcx.hir().get_if_local(impl_def_id) { // Unmet obligation comes from a `derive` macro, point at it once to // avoid multiple span labels pointing at the same place. @@ -617,10 +615,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) => { let span = self_ty.span.ctxt().outer_expn_data().call_site; - let mut spans: MultiSpan = span.into(); - spans.push_span_label(span, derive_msg); - let entry = spanned_predicates.entry(spans); - entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); + let entry = spanned_predicates.entry(span); + let entry = entry.or_insert_with(|| { + (FxHashSet::default(), FxHashSet::default(), Vec::new()) + }); + entry.0.insert(span); + entry.1.insert(( + span, + "unsatisfied trait bound introduced in this `derive` macro", + )); + entry.2.push(p); + skip_list.insert(p); } // Unmet obligation coming from an `impl`. @@ -647,8 +652,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; err.span_suggestion_verbose( sp, - "consider relaxing the type parameter's implicit \ - `Sized` bound", + "consider relaxing the type parameter's implicit `Sized` bound", sugg, Applicability::MachineApplicable, ); @@ -659,25 +663,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let _ = format_pred(*pred); } skip_list.insert(p); - let mut spans = if cause.span != *item_span { - let mut spans: MultiSpan = cause.span.into(); - spans.push_span_label(cause.span, unsatisfied_msg); - spans + let entry = spanned_predicates.entry(self_ty.span); + let entry = entry.or_insert_with(|| { + (FxHashSet::default(), FxHashSet::default(), Vec::new()) + }); + entry.2.push(p); + if cause.span != *item_span { + entry.0.insert(cause.span); + entry.1.insert((cause.span, "unsatisfied trait bound introduced here")); } else { - let mut spans = Vec::with_capacity(2); if let Some(trait_ref) = of_trait { - spans.push(trait_ref.path.span); + entry.0.insert(trait_ref.path.span); } - spans.push(self_ty.span); - spans.into() + entry.0.insert(self_ty.span); }; if let Some(trait_ref) = of_trait { - spans.push_span_label(trait_ref.path.span, ""); + entry.1.insert((trait_ref.path.span, "")); } - spans.push_span_label(self_ty.span, ""); - - let entry = spanned_predicates.entry(spans); - entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); + entry.1.insert((self_ty.span, "")); } Some(Node::Item(hir::Item { kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..), @@ -694,11 +697,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect(); - spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span()); - for (span, (_path, _self_ty, preds)) in spanned_predicates { - let mut preds: Vec<_> = preds - .into_iter() - .filter_map(|pred| format_pred(*pred)) + spanned_predicates.sort_by_key(|(span, _)| *span); + for (_, (primary_spans, span_labels, predicates)) in spanned_predicates { + let mut preds: Vec<_> = predicates + .iter() + .filter_map(|pred| format_pred(**pred)) .map(|(p, _)| format!("`{}`", p)) .collect(); preds.sort(); @@ -708,6 +711,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),) }; + let mut span: MultiSpan = primary_spans.into_iter().collect::>().into(); + for (sp, label) in span_labels { + span.push_span_label(sp, label); + } err.span_note(span, &msg); unsatisfied_bounds = true; } diff --git a/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr index c3e2f8e1646f1..eb4ff8305dac8 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr @@ -15,8 +15,14 @@ LL | struct Foo {} LL | Foo::foo(); | ^^^ function or associated item cannot be called on `Foo<_>` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `[u8; _]: Bar<[(); _]>` +note: trait bound `[u8; _]: Bar<[(); _]>` was not satisfied + --> $DIR/issue-69654.rs:11:14 + | +LL | impl Foo + | ------ +LL | where +LL | [u8; N]: Bar<[(); N]>, + | ^^^^^^^^^^^^ unsatisfied trait bound introduced here error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr index a08c9912527c7..6aa8ee13b790f 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -23,8 +23,17 @@ LL | let dst = Inline::::new(0); | = note: doesn't satisfy `dyn Debug: Sized` | - = note: the following trait bounds were not satisfied: - `dyn Debug: Sized` +note: trait bound `dyn Debug: Sized` was not satisfied + --> $DIR/issue-80742.rs:20:6 + | +LL | impl Inline + | ^ --------- + | | + | unsatisfied trait bound introduced here +help: consider relaxing the type parameter's implicit `Sized` bound + | +LL | impl Inline + | ++++++++ error[E0080]: evaluation of `Inline::::{constant#0}` failed --> $SRC_DIR/core/src/mem/mod.rs:LL:COL diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index c4fddcf5f2468..91b334b412bc9 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -18,9 +18,6 @@ note: trait bound `NotClone: Clone` was not satisfied | LL | #[derive(Clone)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro - = note: the following trait bounds were not satisfied: - `NotClone: Clone` - which is required by `Bar: Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `Clone` diff --git a/tests/ui/derives/issue-91492.stderr b/tests/ui/derives/issue-91492.stderr index fbd48336d9126..cee30ac50a6a2 100644 --- a/tests/ui/derives/issue-91492.stderr +++ b/tests/ui/derives/issue-91492.stderr @@ -42,8 +42,13 @@ LL | struct Object(T, A); LL | foo.use_clone(); | ^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `NoDerives: Clone` +note: trait bound `NoDerives: Clone` was not satisfied + --> $DIR/issue-91492.rs:18:9 + | +LL | impl Object { + | ^^^^^ ------------ + | | + | unsatisfied trait bound introduced here help: consider annotating `NoDerives` with `#[derive(Clone)]` | LL | #[derive(Clone)] diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr index 12be269565da1..bf0bb3fbdf8f7 100644 --- a/tests/ui/derives/issue-91550.stderr +++ b/tests/ui/derives/issue-91550.stderr @@ -30,8 +30,13 @@ LL | struct Object(T); LL | foo.use_eq(); | ^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `NoDerives: Eq` +note: trait bound `NoDerives: Eq` was not satisfied + --> $DIR/issue-91550.rs:15:9 + | +LL | impl Object { + | ^^ --------- + | | + | unsatisfied trait bound introduced here help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]` | LL | #[derive(Eq, PartialEq)] @@ -49,8 +54,13 @@ LL | struct Object(T); LL | foo.use_ord(); | ^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `NoDerives: Ord` +note: trait bound `NoDerives: Ord` was not satisfied + --> $DIR/issue-91550.rs:18:9 + | +LL | impl Object { + | ^^^ --------- + | | + | unsatisfied trait bound introduced here help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | LL | #[derive(Eq, Ord, PartialEq, PartialOrd)] @@ -71,9 +81,16 @@ LL | struct Object(T); LL | foo.use_ord_and_partial_ord(); | ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `NoDerives: Ord` - `NoDerives: PartialOrd` +note: the following trait bounds were not satisfied: + `NoDerives: Ord` + `NoDerives: PartialOrd` + --> $DIR/issue-91550.rs:21:9 + | +LL | impl Object { + | ^^^ ^^^^^^^^^^ --------- + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | LL | #[derive(Eq, Ord, PartialEq, PartialOrd)] diff --git a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs index 36974b3df5e64..83655341d6a24 100644 --- a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs +++ b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs @@ -11,7 +11,7 @@ trait M { impl = i32>> M for T {} //~^ NOTE trait bound `::Y = i32` was not satisfied -//~| NOTE unsatisfied trait bound introduced here +//~| NOTE //~| NOTE //~| NOTE diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr index bc342dc46893b..d872291c87054 100644 --- a/tests/ui/impl-trait/issues/issue-62742.stderr +++ b/tests/ui/impl-trait/issues/issue-62742.stderr @@ -23,8 +23,13 @@ LL | pub struct RawImpl(PhantomData); LL | pub struct SafeImpl>(PhantomData<(A, T)>); | ----------------------------------------- function or associated item `foo` not found for this struct | - = note: the following trait bounds were not satisfied: - `RawImpl<()>: Raw<()>` +note: trait bound `RawImpl<()>: Raw<()>` was not satisfied + --> $DIR/issue-62742.rs:28:20 + | +LL | impl> SafeImpl { + | ^^^^^^ -------------- + | | + | unsatisfied trait bound introduced here note: the trait `Raw` must be implemented --> $DIR/issue-62742.rs:12:1 | diff --git a/tests/ui/methods/method-not-found-generic-arg-elision.stderr b/tests/ui/methods/method-not-found-generic-arg-elision.stderr index 8846efba871b9..f3db56d1d5391 100644 --- a/tests/ui/methods/method-not-found-generic-arg-elision.stderr +++ b/tests/ui/methods/method-not-found-generic-arg-elision.stderr @@ -88,9 +88,16 @@ LL | struct Struct { LL | s.method(); | ^^^^^^ method cannot be called on `Struct` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `f64: Eq` - `f64: Ord` +note: the following trait bounds were not satisfied: + `f64: Eq` + `f64: Ord` + --> $DIR/method-not-found-generic-arg-elision.rs:74:36 + | +LL | impl Struct { + | ^^ ^^^ --------- + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here error: aborting due to 9 previous errors diff --git a/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr b/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr index 9e94aa2c7b3b9..968e285af7ff8 100644 --- a/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr +++ b/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr @@ -7,20 +7,16 @@ LL | struct Foo { LL | self.foo(); | ^^^ method cannot be called on `&Foo` due to unsatisfied trait bounds | -note: trait bound `T: Default` was not satisfied +note: the following trait bounds were not satisfied: + `T: Bar` + `T: Default` --> $DIR/missing-trait-bounds-for-method-call.rs:10:9 | LL | impl Bar for Foo {} - | ^^^^^^^ --- ------ - | | + | ^^^^^^^ ^^^ --- ------ + | | | + | | unsatisfied trait bound introduced here | unsatisfied trait bound introduced here -note: trait bound `T: Bar` was not satisfied - --> $DIR/missing-trait-bounds-for-method-call.rs:10:19 - | -LL | impl Bar for Foo {} - | ^^^ --- ------ - | | - | unsatisfied trait bound introduced here help: consider restricting the type parameters to satisfy the trait bounds | LL | struct Foo where T: Bar, T: Default { diff --git a/tests/ui/suggestions/derive-trait-for-method-call.stderr b/tests/ui/suggestions/derive-trait-for-method-call.stderr index 14e8a2675dd18..924b26a8c75fd 100644 --- a/tests/ui/suggestions/derive-trait-for-method-call.stderr +++ b/tests/ui/suggestions/derive-trait-for-method-call.stderr @@ -16,10 +16,18 @@ LL | struct Foo (X, Y); LL | let y = x.test(); | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `Enum: Clone` - `Enum: Default` - `CloneEnum: Default` +note: the following trait bounds were not satisfied: + `CloneEnum: Default` + `Enum: Clone` + `Enum: Default` + --> $DIR/derive-trait-for-method-call.rs:20:9 + | +LL | impl Foo { + | ^^^^^ ^^^^^^^ ^^^^^^^ --------- + | | | | + | | | unsatisfied trait bound introduced here + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here note: the trait `Default` must be implemented --> $SRC_DIR/core/src/default.rs:LL:COL help: consider annotating `Enum` with `#[derive(Clone)]` @@ -45,10 +53,18 @@ LL | struct Foo (X, Y); LL | let y = x.test(); | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `Struct: Clone` - `Struct: Default` - `CloneStruct: Default` +note: the following trait bounds were not satisfied: + `CloneStruct: Default` + `Struct: Clone` + `Struct: Default` + --> $DIR/derive-trait-for-method-call.rs:20:9 + | +LL | impl Foo { + | ^^^^^ ^^^^^^^ ^^^^^^^ --------- + | | | | + | | | unsatisfied trait bound introduced here + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here help: consider annotating `CloneStruct` with `#[derive(Default)]` | LL | #[derive(Default)] @@ -73,9 +89,16 @@ LL | let y = x.test(); | = note: doesn't satisfy `Vec: Clone` | - = note: the following trait bounds were not satisfied: - `Vec: Clone` - `Instant: Default` +note: the following trait bounds were not satisfied: + `Instant: Default` + `Vec: Clone` + --> $DIR/derive-trait-for-method-call.rs:20:9 + | +LL | impl Foo { + | ^^^^^ ^^^^^^^ --------- + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here error: aborting due to 3 previous errors diff --git a/tests/ui/union/union-derive-clone.mirunsafeck.stderr b/tests/ui/union/union-derive-clone.mirunsafeck.stderr index 65ff72fe474b1..b80e8b988adb1 100644 --- a/tests/ui/union/union-derive-clone.mirunsafeck.stderr +++ b/tests/ui/union/union-derive-clone.mirunsafeck.stderr @@ -32,9 +32,6 @@ note: trait bound `CloneNoCopy: Copy` was not satisfied | LL | #[derive(Clone, Copy)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro - = note: the following trait bounds were not satisfied: - `CloneNoCopy: Copy` - which is required by `U5: Clone` help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` | LL | #[derive(Clone, Copy)] diff --git a/tests/ui/union/union-derive-clone.thirunsafeck.stderr b/tests/ui/union/union-derive-clone.thirunsafeck.stderr index 65ff72fe474b1..b80e8b988adb1 100644 --- a/tests/ui/union/union-derive-clone.thirunsafeck.stderr +++ b/tests/ui/union/union-derive-clone.thirunsafeck.stderr @@ -32,9 +32,6 @@ note: trait bound `CloneNoCopy: Copy` was not satisfied | LL | #[derive(Clone, Copy)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro - = note: the following trait bounds were not satisfied: - `CloneNoCopy: Copy` - which is required by `U5: Clone` help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` | LL | #[derive(Clone, Copy)]