diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
index 467054e318b..61e3334862b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
@@ -31,7 +31,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         // about the original obligation only.
         let code = match cause.code() {
             ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code,
-            _ => cause.code(),
+            code => code,
         };
         let ObligationCauseCode::MatchImpl(parent, impl_def_id) = code else {
             return None;
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 36bbccf0a80..3ed7836074b 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -257,7 +257,7 @@ pub enum ObligationCauseCode<'tcx> {
 
     BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
 
-    ImplDerivedObligation(DerivedObligationCause<'tcx>),
+    ImplDerivedObligation(Box<ImplDerivedObligationCause<'tcx>>),
 
     DerivedObligation(DerivedObligationCause<'tcx>),
 
@@ -396,16 +396,29 @@ pub enum WellFormedLoc {
     },
 }
 
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
+pub struct ImplDerivedObligationCause<'tcx> {
+    pub derived: DerivedObligationCause<'tcx>,
+    pub impl_def_id: DefId,
+    pub span: Span,
+}
+
 impl ObligationCauseCode<'_> {
     // Return the base obligation, ignoring derived obligations.
     pub fn peel_derives(&self) -> &Self {
         let mut base_cause = self;
-        while let BuiltinDerivedObligation(DerivedObligationCause { parent_code, .. })
-        | ImplDerivedObligation(DerivedObligationCause { parent_code, .. })
-        | DerivedObligation(DerivedObligationCause { parent_code, .. })
-        | FunctionArgumentObligation { parent_code, .. } = base_cause
-        {
-            base_cause = &parent_code;
+        loop {
+            match base_cause {
+                BuiltinDerivedObligation(DerivedObligationCause { parent_code, .. })
+                | DerivedObligation(DerivedObligationCause { parent_code, .. })
+                | FunctionArgumentObligation { parent_code, .. } => {
+                    base_cause = &parent_code;
+                }
+                ImplDerivedObligation(obligation_cause) => {
+                    base_cause = &*obligation_cause.derived.parent_code;
+                }
+                _ => break,
+            }
         }
         base_cause
     }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index b617067e66d..d65b390af34 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -507,8 +507,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         let body_id = obligation.cause.body_id;
         let span = obligation.cause.span;
         let real_trait_pred = match &*code {
-            ObligationCauseCode::ImplDerivedObligation(cause)
-            | ObligationCauseCode::DerivedObligation(cause)
+            ObligationCauseCode::ImplDerivedObligation(cause) => cause.derived.parent_trait_pred,
+            ObligationCauseCode::DerivedObligation(cause)
             | ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_pred,
             _ => trait_pred,
         };
@@ -790,8 +790,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             return false;
         };
 
-        if let ObligationCauseCode::ImplDerivedObligation(obligation) = code {
-            try_borrowing(obligation.parent_trait_pred, &[])
+        if let ObligationCauseCode::ImplDerivedObligation(cause) = &*code {
+            try_borrowing(cause.derived.parent_trait_pred, &[])
         } else if let ObligationCauseCode::BindingObligation(_, _)
         | ObligationCauseCode::ItemObligation(_) = code
         {
@@ -1433,13 +1433,43 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
                     next_code = Some(parent_code.as_ref());
                 }
+                ObligationCauseCode::ImplDerivedObligation(cause) => {
+                    let ty = cause.derived.parent_trait_pred.skip_binder().self_ty();
+                    debug!(
+                        "maybe_note_obligation_cause_for_async_await: ImplDerived \
+                         parent_trait_ref={:?} self_ty.kind={:?}",
+                        cause.derived.parent_trait_pred,
+                        ty.kind()
+                    );
+
+                    match *ty.kind() {
+                        ty::Generator(did, ..) => {
+                            generator = generator.or(Some(did));
+                            outer_generator = Some(did);
+                        }
+                        ty::GeneratorWitness(..) => {}
+                        ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
+                            // By introducing a tuple of upvar types into the chain of obligations
+                            // of a generator, the first non-generator item is now the tuple itself,
+                            // we shall ignore this.
+
+                            seen_upvar_tys_infer_tuple = true;
+                        }
+                        _ if generator.is_none() => {
+                            trait_ref = Some(cause.derived.parent_trait_pred.skip_binder());
+                            target_ty = Some(ty);
+                        }
+                        _ => {}
+                    }
+
+                    next_code = Some(cause.derived.parent_code.as_ref());
+                }
                 ObligationCauseCode::DerivedObligation(derived_obligation)
-                | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
-                | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
+                | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) => {
                     let ty = derived_obligation.parent_trait_pred.skip_binder().self_ty();
                     debug!(
                         "maybe_note_obligation_cause_for_async_await: \
-                            parent_trait_ref={:?} self_ty.kind={:?}",
+                         parent_trait_ref={:?} self_ty.kind={:?}",
                         derived_obligation.parent_trait_pred,
                         ty.kind()
                     );
@@ -2166,7 +2196,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 }
             }
             ObligationCauseCode::ImplDerivedObligation(ref data) => {
-                let mut parent_trait_pred = self.resolve_vars_if_possible(data.parent_trait_pred);
+                let mut parent_trait_pred =
+                    self.resolve_vars_if_possible(data.derived.parent_trait_pred);
                 parent_trait_pred.remap_constness_diag(param_env);
                 let parent_def_id = parent_trait_pred.def_id();
                 let msg = format!(
@@ -2174,51 +2205,63 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     parent_trait_pred.print_modifiers_and_trait_path(),
                     parent_trait_pred.skip_binder().self_ty()
                 );
-                let mut candidates = vec![];
-                self.tcx.for_each_relevant_impl(
-                    parent_def_id,
-                    parent_trait_pred.self_ty().skip_binder(),
-                    |impl_def_id| match self.tcx.hir().get_if_local(impl_def_id) {
-                        Some(Node::Item(hir::Item {
-                            kind: hir::ItemKind::Impl(hir::Impl { .. }),
-                            ..
-                        })) => {
-                            candidates.push(impl_def_id);
+                let mut is_auto_trait = false;
+                match self.tcx.hir().get_if_local(data.impl_def_id) {
+                    Some(Node::Item(hir::Item {
+                        kind: hir::ItemKind::Trait(is_auto, ..),
+                        ident,
+                        ..
+                    })) => {
+                        // FIXME: we should do something else so that it works even on crate foreign
+                        // auto traits.
+                        is_auto_trait = matches!(is_auto, hir::IsAuto::Yes);
+                        err.span_note(ident.span, &msg)
+                    }
+                    Some(Node::Item(hir::Item {
+                        kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
+                        ..
+                    })) => {
+                        let mut spans = Vec::with_capacity(2);
+                        if let Some(trait_ref) = of_trait {
+                            spans.push(trait_ref.path.span);
                         }
-                        _ => {}
-                    },
-                );
-                match &candidates[..] {
-                    [def_id] => match self.tcx.hir().get_if_local(*def_id) {
-                        Some(Node::Item(hir::Item {
-                            kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
-                            ..
-                        })) => {
-                            let mut spans = Vec::with_capacity(2);
-                            if let Some(trait_ref) = of_trait {
-                                spans.push(trait_ref.path.span);
-                            }
-                            spans.push(self_ty.span);
-                            err.span_note(spans, &msg)
-                        }
-                        _ => err.note(&msg),
-                    },
+                        spans.push(self_ty.span);
+                        err.span_note(spans, &msg)
+                    }
                     _ => err.note(&msg),
                 };
 
                 let mut parent_predicate = parent_trait_pred.to_predicate(tcx);
-                let mut data = data;
+                let mut data = &data.derived;
                 let mut count = 0;
                 seen_requirements.insert(parent_def_id);
+                if is_auto_trait {
+                    // We don't want to point at the ADT saying "required because it appears within
+                    // the type `X`", like we would otherwise do in test `supertrait-auto-trait.rs`.
+                    while let ObligationCauseCode::BuiltinDerivedObligation(derived) =
+                        &*data.parent_code
+                    {
+                        let child_trait_ref =
+                            self.resolve_vars_if_possible(derived.parent_trait_pred);
+                        let child_def_id = child_trait_ref.def_id();
+                        if seen_requirements.insert(child_def_id) {
+                            break;
+                        }
+                        data = derived;
+                        parent_predicate = child_trait_ref.to_predicate(tcx);
+                        parent_trait_pred = child_trait_ref;
+                    }
+                }
                 while let ObligationCauseCode::ImplDerivedObligation(child) = &*data.parent_code {
                     // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`.
-                    let child_trait_pred = self.resolve_vars_if_possible(child.parent_trait_pred);
+                    let child_trait_pred =
+                        self.resolve_vars_if_possible(child.derived.parent_trait_pred);
                     let child_def_id = child_trait_pred.def_id();
                     if seen_requirements.insert(child_def_id) {
                         break;
                     }
                     count += 1;
-                    data = child;
+                    data = &child.derived;
                     parent_predicate = child_trait_pred.to_predicate(tcx);
                     parent_trait_pred = child_trait_pred;
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index df760a166e8..9c871eea1cd 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -18,24 +18,17 @@ use rustc_span::def_id::DefId;
 
 use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
 use crate::traits::select::TraitObligationExt;
-use crate::traits::util;
-use crate::traits::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
-use crate::traits::ImplSource;
-use crate::traits::Normalized;
-use crate::traits::OutputTypeParameterMismatch;
-use crate::traits::Selection;
-use crate::traits::TraitNotObjectSafe;
-use crate::traits::VtblSegment;
-use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation};
+use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def};
 use crate::traits::{
-    ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
-    ImplSourceConstDestructData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
-    ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
-    ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
+    BuiltinDerivedObligation, DerivedObligationCause, ImplDerivedObligation,
+    ImplDerivedObligationCause, ImplSource, ImplSourceAutoImplData, ImplSourceBuiltinData,
+    ImplSourceClosureData, ImplSourceConstDestructData, ImplSourceDiscriminantKindData,
+    ImplSourceFnPointerData, ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData,
+    ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized,
+    ObjectCastObligation, Obligation, ObligationCause, OutputTypeParameterMismatch,
+    PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, TraitObligation,
+    Unimplemented, VtblSegment,
 };
-use crate::traits::{ObjectCastObligation, PredicateObligation, TraitObligation};
-use crate::traits::{Obligation, ObligationCause};
-use crate::traits::{SelectionError, Unimplemented};
 
 use super::BuiltinImplConditions;
 use super::SelectionCandidate::{self, *};
@@ -321,6 +314,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         debug!(?nested, "vtable_auto_impl");
         ensure_sufficient_stack(|| {
             let cause = obligation.derived_cause(BuiltinDerivedObligation);
+
+            let trait_obligations: Vec<PredicateObligation<'_>> =
+                self.infcx.commit_unconditionally(|_| {
+                    let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
+                    let trait_ref = self.infcx.replace_bound_vars_with_placeholders(poly_trait_ref);
+                    self.impl_or_trait_obligations(
+                        &cause,
+                        obligation.recursion_depth + 1,
+                        obligation.param_env,
+                        trait_def_id,
+                        &trait_ref.substs,
+                        obligation.predicate,
+                    )
+                });
+
             let mut obligations = self.collect_predicates_for_types(
                 obligation.param_env,
                 cause,
@@ -329,20 +337,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 nested,
             );
 
-            let trait_obligations: Vec<PredicateObligation<'_>> =
-                self.infcx.commit_unconditionally(|_| {
-                    let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
-                    let trait_ref = self.infcx.replace_bound_vars_with_placeholders(poly_trait_ref);
-                    let cause = obligation.derived_cause(ImplDerivedObligation);
-                    self.impl_or_trait_obligations(
-                        cause,
-                        obligation.recursion_depth + 1,
-                        obligation.param_env,
-                        trait_def_id,
-                        &trait_ref.substs,
-                    )
-                });
-
             // Adds the predicates from the trait.  Note that this contains a `Self: Trait`
             // predicate as usual.  It won't have any effect since auto traits are coinductive.
             obligations.extend(trait_obligations);
@@ -365,14 +359,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         self.infcx.commit_unconditionally(|_| {
             let substs = self.rematch_impl(impl_def_id, obligation);
             debug!(?substs, "impl substs");
-            let cause = obligation.derived_cause(ImplDerivedObligation);
             ensure_sufficient_stack(|| {
                 self.vtable_impl(
                     impl_def_id,
                     substs,
-                    cause,
+                    &obligation.cause,
                     obligation.recursion_depth + 1,
                     obligation.param_env,
+                    obligation.predicate,
                 )
             })
         })
@@ -382,9 +376,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         impl_def_id: DefId,
         substs: Normalized<'tcx, SubstsRef<'tcx>>,
-        cause: ObligationCause<'tcx>,
+        cause: &ObligationCause<'tcx>,
         recursion_depth: usize,
         param_env: ty::ParamEnv<'tcx>,
+        parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
     ) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
         debug!(?impl_def_id, ?substs, ?recursion_depth, "vtable_impl");
 
@@ -394,6 +389,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             param_env,
             impl_def_id,
             &substs.value,
+            parent_trait_pred,
         );
 
         debug!(?impl_obligations, "vtable_impl");
@@ -566,11 +562,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let substs = trait_ref.substs;
 
             let trait_obligations = self.impl_or_trait_obligations(
-                obligation.cause.clone(),
+                &obligation.cause,
                 obligation.recursion_depth,
                 obligation.param_env,
                 trait_def_id,
                 &substs,
+                obligation.predicate,
             );
 
             debug!(?trait_def_id, ?trait_obligations, "trait alias obligations");
@@ -1073,14 +1070,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 });
                 let substs = self.rematch_impl(impl_def_id, &new_obligation);
                 debug!(?substs, "impl substs");
-                let cause = obligation.derived_cause(ImplDerivedObligation);
+
+                let derived = DerivedObligationCause {
+                    parent_trait_pred: obligation.predicate,
+                    parent_code: obligation.cause.clone_code(),
+                };
+                let derived_code = ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
+                    derived,
+                    impl_def_id,
+                    span: obligation.cause.span,
+                }));
+
+                let cause = ObligationCause::new(
+                    obligation.cause.span,
+                    obligation.cause.body_id,
+                    derived_code,
+                );
                 ensure_sufficient_stack(|| {
                     self.vtable_impl(
                         impl_def_id,
                         substs,
-                        cause,
+                        &cause,
                         new_obligation.recursion_depth + 1,
                         new_obligation.param_env,
+                        obligation.predicate,
                     )
                 })
             });
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 4135fbca060..3a5bca49296 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -13,15 +13,11 @@ use super::project::ProjectionTyObligation;
 use super::util;
 use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
 use super::wf;
-use super::DerivedObligationCause;
-use super::Normalized;
-use super::Obligation;
-use super::ObligationCauseCode;
-use super::Selection;
-use super::SelectionResult;
-use super::TraitQueryMode;
-use super::{ErrorReporting, Overflow, SelectionError};
-use super::{ObligationCause, PredicateObligation, TraitObligation};
+use super::{
+    DerivedObligationCause, ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause,
+    Normalized, Obligation, ObligationCause, ObligationCauseCode, Overflow, PredicateObligation,
+    Selection, SelectionError, SelectionResult, TraitObligation, TraitQueryMode,
+};
 
 use crate::infer::{InferCtxt, InferOk, TypeFreshener};
 use crate::traits::error_reporting::InferCtxtExt;
@@ -2333,11 +2329,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     #[tracing::instrument(level = "debug", skip(self, cause, param_env))]
     fn impl_or_trait_obligations(
         &mut self,
-        cause: ObligationCause<'tcx>,
+        cause: &ObligationCause<'tcx>,
         recursion_depth: usize,
         param_env: ty::ParamEnv<'tcx>,
         def_id: DefId,           // of impl or trait
         substs: SubstsRef<'tcx>, // for impl or trait
+        parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
     ) -> Vec<PredicateObligation<'tcx>> {
         let tcx = self.tcx();
 
@@ -2359,8 +2356,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         debug!(?predicates);
         assert_eq!(predicates.parent, None);
         let mut obligations = Vec::with_capacity(predicates.predicates.len());
-        for (predicate, _) in predicates.predicates {
-            debug!(?predicate);
+        let parent_code = cause.clone_code();
+        for (predicate, span) in predicates.predicates {
+            let span = *span;
+            let derived =
+                DerivedObligationCause { parent_trait_pred, parent_code: parent_code.clone() };
+            let code = ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
+                derived,
+                impl_def_id: def_id,
+                span,
+            }));
+            let cause = ObligationCause::new(cause.span, cause.body_id, code);
             let predicate = normalize_with_depth_to(
                 self,
                 param_env,
@@ -2369,12 +2375,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 predicate.subst(tcx, substs),
                 &mut obligations,
             );
-            obligations.push(Obligation {
-                cause: cause.clone(),
-                recursion_depth,
-                param_env,
-                predicate,
-            });
+            obligations.push(Obligation { cause, recursion_depth, param_env, predicate });
         }
 
         obligations
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index f5477f7103c..a22c9210a9c 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -227,8 +227,14 @@ fn compare_predicate_entailment<'tcx>(
                 traits::normalize(&mut selcx, param_env, normalize_cause, predicate);
 
             inh.register_predicates(obligations);
-            let mut cause = cause.clone();
-            cause.span = span;
+            let cause = ObligationCause::new(
+                span,
+                impl_m_hir_id,
+                ObligationCauseCode::CompareImplMethodObligation {
+                    impl_item_def_id: impl_m.def_id,
+                    trait_item_def_id: trait_m.def_id,
+                },
+            );
             inh.register_predicate(traits::Obligation::new(cause, param_env, predicate));
         }
 
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index d336573c254..b7b45929e14 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -1087,8 +1087,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let mut result_code = code.clone();
                 loop {
                     let parent = match &*code {
+                        ObligationCauseCode::ImplDerivedObligation(c) => {
+                            c.derived.parent_code.clone()
+                        }
                         ObligationCauseCode::BuiltinDerivedObligation(c)
-                        | ObligationCauseCode::ImplDerivedObligation(c)
                         | ObligationCauseCode::DerivedObligation(c) => c.parent_code.clone(),
                         _ => break,
                     };
@@ -1098,10 +1100,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(error.obligation.cause.clone_code()) {
                 ObligationCauseCode::BuiltinDerivedObligation(code) |
-                ObligationCauseCode::ImplDerivedObligation(code) |
                 ObligationCauseCode::DerivedObligation(code) => {
                     code.parent_trait_pred.self_ty().skip_binder().into()
                 }
+                ObligationCauseCode::ImplDerivedObligation(code) => {
+                    code.derived.parent_trait_pred.self_ty().skip_binder().into()
+                }
                 _ if let ty::PredicateKind::Trait(predicate) =
                     error.obligation.predicate.kind().skip_binder() => {
                         predicate.self_ty().into()
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs
index 4e1645adca5..704866c2cc2 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -1521,6 +1521,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             let selcx = &mut traits::SelectionContext::new(self);
             let cause = traits::ObligationCause::misc(self.span, self.body_id);
 
+            let mut parent_pred = None;
+
             // If so, impls may carry other conditions (e.g., where
             // clauses) that must be considered. Make sure that those
             // match as well (or at least may match, sometimes we
@@ -1584,6 +1586,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     }
                     let predicate =
                         ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx);
+                    parent_pred = Some(predicate);
                     let obligation = traits::Obligation::new(cause, self.param_env, predicate);
                     if !self.predicate_may_hold(&obligation) {
                         result = ProbeResult::NoMatch;
@@ -1639,7 +1642,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 let o = self.resolve_vars_if_possible(o);
                 if !self.predicate_may_hold(&o) {
                     result = ProbeResult::NoMatch;
-                    possibly_unsatisfied_predicates.push((o.predicate, None, Some(o.cause)));
+                    possibly_unsatisfied_predicates.push((o.predicate, parent_pred, Some(o.cause)));
                 }
             }
 
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index bf7db8221a2..9c3f2da5644 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -16,9 +16,8 @@ use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::with_crate_prefix;
 use rustc_middle::ty::ToPolyTraitRef;
 use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
-use rustc_span::lev_distance;
 use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::{source_map, FileName, MultiSpan, Span};
+use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, MultiSpan, Span};
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
@@ -723,102 +722,190 @@ 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<MultiSpan, _> = Default::default();
-                    for (data, p, parent_p) in unsatisfied_predicates
+                    for (data, p, parent_p, impl_def_id, cause_span) 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(ref data) => {
-                                Some((data, p, parent))
+                                Some((&data.derived, p, parent, data.impl_def_id, data.span))
                             }
                             _ => None,
                         })
                     {
                         let parent_trait_ref = data.parent_trait_pred;
-                        let parent_def_id = parent_trait_ref.def_id();
                         let path = parent_trait_ref.print_modifiers_and_trait_path();
                         let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
-                        let mut candidates = vec![];
-                        self.tcx.for_each_relevant_impl(
-                            parent_def_id,
-                            parent_trait_ref.self_ty().skip_binder(),
-                            |impl_def_id| match self.tcx.hir().get_if_local(impl_def_id) {
-                                Some(Node::Item(hir::Item {
-                                    kind: hir::ItemKind::Impl(hir::Impl { .. }),
-                                    ..
-                                })) => {
-                                    candidates.push(impl_def_id);
+                        let unsatisfied_msg = "unsatisfied trait bound introduced here".to_string();
+                        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.
+                            Some(Node::Item(hir::Item {
+                                kind: hir::ItemKind::Trait(..),
+                                ident,
+                                ..
+                            })) if matches!(
+                                ident.span.ctxt().outer_expn_data().kind,
+                                ExpnKind::Macro(MacroKind::Derive, _)
+                            ) =>
+                            {
+                                let span = ident.span.ctxt().outer_expn_data().call_site;
+                                let mut spans: MultiSpan = span.into();
+                                spans.push_span_label(span, derive_msg.to_string());
+                                let entry = spanned_predicates.entry(spans);
+                                entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
+                            }
+
+                            Some(Node::Item(hir::Item {
+                                kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
+                                ..
+                            })) if matches!(
+                                self_ty.span.ctxt().outer_expn_data().kind,
+                                ExpnKind::Macro(MacroKind::Derive, _)
+                            ) || matches!(
+                                of_trait.as_ref().map(|t| t
+                                    .path
+                                    .span
+                                    .ctxt()
+                                    .outer_expn_data()
+                                    .kind),
+                                Some(ExpnKind::Macro(MacroKind::Derive, _))
+                            ) =>
+                            {
+                                let span = self_ty.span.ctxt().outer_expn_data().call_site;
+                                let mut spans: MultiSpan = span.into();
+                                spans.push_span_label(span, derive_msg.to_string());
+                                let entry = spanned_predicates.entry(spans.into());
+                                entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
+                            }
+
+                            // Unmet obligation coming from a `trait`.
+                            Some(Node::Item(hir::Item {
+                                kind: hir::ItemKind::Trait(..),
+                                ident,
+                                span: item_span,
+                                ..
+                            })) if !matches!(
+                                ident.span.ctxt().outer_expn_data().kind,
+                                ExpnKind::Macro(MacroKind::Derive, _)
+                            ) =>
+                            {
+                                if let Some(pred) = parent_p {
+                                    // Done to add the "doesn't satisfy" `span_label`.
+                                    let _ = format_pred(*pred);
                                 }
-                                _ => {}
-                            },
-                        );
-                        if let [def_id] = &candidates[..] {
-                            match self.tcx.hir().get_if_local(*def_id) {
-                                Some(Node::Item(hir::Item {
-                                    kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
-                                    ..
-                                })) => {
-                                    if let Some(pred) = parent_p {
-                                        // Done to add the "doesn't satisfy" `span_label`.
-                                        let _ = format_pred(*pred);
-                                    }
-                                    skip_list.insert(p);
+                                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
+                                } else {
+                                    ident.span.into()
+                                };
+                                spans.push_span_label(ident.span, "in this trait".to_string());
+                                let entry = spanned_predicates.entry(spans.into());
+                                entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
+                            }
+
+                            // Unmet obligation coming from an `impl`.
+                            Some(Node::Item(hir::Item {
+                                kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
+                                span: item_span,
+                                ..
+                            })) if !matches!(
+                                self_ty.span.ctxt().outer_expn_data().kind,
+                                ExpnKind::Macro(MacroKind::Derive, _)
+                            ) && !matches!(
+                                of_trait.as_ref().map(|t| t
+                                    .path
+                                    .span
+                                    .ctxt()
+                                    .outer_expn_data()
+                                    .kind),
+                                Some(ExpnKind::Macro(MacroKind::Derive, _))
+                            ) =>
+                            {
+                                if let Some(pred) = parent_p {
+                                    // Done to add the "doesn't satisfy" `span_label`.
+                                    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
+                                } else {
                                     let mut spans = Vec::with_capacity(2);
                                     if let Some(trait_ref) = of_trait {
                                         spans.push(trait_ref.path.span);
                                     }
                                     spans.push(self_ty.span);
-                                    let entry = spanned_predicates.entry(spans.into());
-                                    entry
-                                        .or_insert_with(|| (path, tr_self_ty, Vec::new()))
-                                        .2
-                                        .push(p);
+                                    spans.into()
+                                };
+                                if let Some(trait_ref) = of_trait {
+                                    spans.push_span_label(trait_ref.path.span, String::new());
                                 }
-                                _ => {}
+                                spans.push_span_label(self_ty.span, String::new());
+
+                                let entry = spanned_predicates.entry(spans.into());
+                                entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
                             }
+                            _ => {}
                         }
                     }
-                    for (span, (path, self_ty, preds)) in spanned_predicates {
-                        err.span_note(
-                            span,
-                            &format!(
-                                "the following trait bounds were not satisfied because of the \
-                                 requirements of the implementation of `{}` for `{}`:\n{}",
-                                path,
-                                self_ty,
-                                preds
-                                    .into_iter()
-                                    // .map(|pred| format!("{:?}", pred))
-                                    .filter_map(|pred| format_pred(*pred))
-                                    .map(|(p, _)| format!("`{}`", p))
-                                    .collect::<Vec<_>>()
-                                    .join("\n"),
-                            ),
-                        );
+                    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))
+                            .map(|(p, _)| format!("`{}`", p))
+                            .collect();
+                        preds.sort();
+                        preds.dedup();
+                        let msg = if let [pred] = &preds[..] {
+                            format!("trait bound {} was not satisfied", pred)
+                        } else {
+                            format!(
+                                "the following trait bounds were not satisfied:\n{}",
+                                preds.join("\n"),
+                            )
+                        };
+                        err.span_note(span, &msg);
+                        unsatisfied_bounds = true;
                     }
 
                     // The requirements that didn't have an `impl` span to show.
                     let mut bound_list = unsatisfied_predicates
                         .iter()
-                        .filter(|(pred, _, _parent_pred)| !skip_list.contains(&pred))
                         .filter_map(|(pred, parent_pred, _cause)| {
                             format_pred(*pred).map(|(p, self_ty)| {
                                 collect_type_param_suggestions(self_ty, *pred, &p);
-                                match parent_pred {
-                                    None => format!("`{}`", &p),
-                                    Some(parent_pred) => match format_pred(*parent_pred) {
+                                (
+                                    match parent_pred {
                                         None => format!("`{}`", &p),
-                                        Some((parent_p, _)) => {
-                                            collect_type_param_suggestions(
-                                                self_ty,
-                                                *parent_pred,
-                                                &p,
-                                            );
-                                            format!("`{}`\nwhich is required by `{}`", p, parent_p)
-                                        }
+                                        Some(parent_pred) => match format_pred(*parent_pred) {
+                                            None => format!("`{}`", &p),
+                                            Some((parent_p, _)) => {
+                                                collect_type_param_suggestions(
+                                                    self_ty,
+                                                    *parent_pred,
+                                                    &p,
+                                                );
+                                                format!(
+                                                    "`{}`\nwhich is required by `{}`",
+                                                    p, parent_p
+                                                )
+                                            }
+                                        },
                                     },
-                                }
+                                    *pred,
+                                )
                             })
                         })
+                        .filter(|(_, pred)| !skip_list.contains(&pred))
+                        .map(|(t, _)| t)
                         .enumerate()
                         .collect::<Vec<(usize, String)>>();
 
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 5d4dfd3caef..d0c4726bb0a 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -58,6 +58,7 @@ This API is completely unstable and subject to change.
 #![allow(rustc::potential_query_instability)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(bool_to_option)]
+#![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(crate_visibility_modifier)]
 #![feature(hash_drain_filter)]
diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
index 45a906a3947..72dd9c153ab 100644
--- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr
+++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
@@ -13,16 +13,17 @@ LL | struct NotClone;
 LL |     Bar::<NotClone> { x: 1 }.clone();
    |                              ^^^^^ method cannot be called on `Bar<NotClone>` due to unsatisfied trait bounds
    |
-note: the following trait bounds were not satisfied because of the requirements of the implementation of `Clone` for `_`:
-      `NotClone: Clone`
+note: trait bound `NotClone: Clone` was not satisfied
   --> $DIR/derive-assoc-type-not-impl.rs:6:10
    |
 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<NotClone>: 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`
-   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `NotClone` with `#[derive(Clone)]`
    |
 LL | #[derive(Clone)]
diff --git a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs
index 8b6f7c41a7c..655abd18da1 100644
--- a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs
+++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs
@@ -12,7 +12,10 @@ trait M {
 }
 
 impl<T: X<Y<i32> = i32>> M for T {}
-//~^ NOTE the following trait bounds were not satisfied
+//~^ NOTE trait bound `<S as X>::Y<i32> = i32` was not satisfied
+//~| NOTE unsatisfied trait bound introduced here
+//~| NOTE
+//~| NOTE
 
 struct S;
 //~^ NOTE method `f` not found for this
diff --git a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr
index 3eeb9540e73..9eeebd80afe 100644
--- a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr
+++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr
@@ -1,5 +1,5 @@
 error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied
-  --> $DIR/method-unsatified-assoc-type-predicate.rs:27:7
+  --> $DIR/method-unsatified-assoc-type-predicate.rs:30:7
    |
 LL | struct S;
    | ---------
@@ -11,12 +11,13 @@ LL | struct S;
 LL |     a.f();
    |       ^ method cannot be called on `S` due to unsatisfied trait bounds
    |
-note: the following trait bounds were not satisfied because of the requirements of the implementation of `M` for `_`:
-      `<S as X>::Y<i32> = i32`
-  --> $DIR/method-unsatified-assoc-type-predicate.rs:14:26
+note: trait bound `<S as X>::Y<i32> = i32` was not satisfied
+  --> $DIR/method-unsatified-assoc-type-predicate.rs:14:11
    |
 LL | impl<T: X<Y<i32> = i32>> M for T {}
-   |                          ^     ^
+   |           ^^^^^^^^^^^^   -     -
+   |           |
+   |           unsatisfied trait bound introduced here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr
index a2ab1f1856d..7ffe2f4cd7e 100644
--- a/src/test/ui/hrtb/issue-30786.migrate.stderr
+++ b/src/test/ui/hrtb/issue-30786.migrate.stderr
@@ -10,14 +10,14 @@ LL | pub struct Map<S, F> {
 LL |     let filter = map.filterx(|x: &_| true);
    |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>` due to unsatisfied trait bounds
    |
-note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+note: the following trait bounds were not satisfied:
       `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
       `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
-  --> $DIR/issue-30786.rs:105:9
+      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+  --> $DIR/issue-30786.rs:105:50
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
-   |         ^^^^^^^^^     ^
+   |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
 
 error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied
   --> $DIR/issue-30786.rs:140:24
@@ -31,14 +31,14 @@ LL | pub struct Filter<S, F> {
 LL |     let count = filter.countx();
    |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>` due to unsatisfied trait bounds
    |
-note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+note: the following trait bounds were not satisfied:
       `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
       `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
-  --> $DIR/issue-30786.rs:105:9
+      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+  --> $DIR/issue-30786.rs:105:50
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
-   |         ^^^^^^^^^     ^
+   |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr
index a2ab1f1856d..7ffe2f4cd7e 100644
--- a/src/test/ui/hrtb/issue-30786.nll.stderr
+++ b/src/test/ui/hrtb/issue-30786.nll.stderr
@@ -10,14 +10,14 @@ LL | pub struct Map<S, F> {
 LL |     let filter = map.filterx(|x: &_| true);
    |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>` due to unsatisfied trait bounds
    |
-note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+note: the following trait bounds were not satisfied:
       `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
       `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
-  --> $DIR/issue-30786.rs:105:9
+      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+  --> $DIR/issue-30786.rs:105:50
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
-   |         ^^^^^^^^^     ^
+   |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
 
 error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied
   --> $DIR/issue-30786.rs:140:24
@@ -31,14 +31,14 @@ LL | pub struct Filter<S, F> {
 LL |     let count = filter.countx();
    |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>` due to unsatisfied trait bounds
    |
-note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+note: the following trait bounds were not satisfied:
       `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
       `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
-  --> $DIR/issue-30786.rs:105:9
+      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+  --> $DIR/issue-30786.rs:105:50
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
-   |         ^^^^^^^^^     ^
+   |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr b/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr
index 2f0fd692a44..f3c6b39e62e 100644
--- a/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr
+++ b/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr
@@ -7,11 +7,20 @@ LL | struct Foo<T> {
 LL |         self.foo();
    |              ^^^ method cannot be called on `&Foo<T>` due to unsatisfied trait bounds
    |
-   = note: the following trait bounds were not satisfied:
-           `T: Default`
-           which is required by `Foo<T>: Bar`
-           `T: Bar`
-           which is required by `Foo<T>: Bar`
+note: trait bound `T: Default` was not satisfied
+  --> $DIR/missing-trait-bounds-for-method-call.rs:10:9
+   |
+LL | impl<T: Default + Bar> Bar for Foo<T> {}
+   |         ^^^^^^^        ---     ------
+   |         |
+   |         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<T: Default + Bar> Bar for Foo<T> {}
+   |                   ^^^  ---     ------
+   |                   |
+   |                   unsatisfied trait bound introduced here
 help: consider restricting the type parameters to satisfy the trait bounds
    |
 LL | struct Foo<T> where T: Bar, T: Default {
@@ -26,9 +35,13 @@ LL | struct Fin<T> where T: Bar {
 LL |         self.foo();
    |              ^^^ method cannot be called on `&Fin<T>` due to unsatisfied trait bounds
    |
-   = note: the following trait bounds were not satisfied:
-           `T: Default`
-           which is required by `Fin<T>: Bar`
+note: trait bound `T: Default` was not satisfied
+  --> $DIR/missing-trait-bounds-for-method-call.rs:23:9
+   |
+LL | impl<T: Default + Bar> Bar for Fin<T> {}
+   |         ^^^^^^^        ---     ------
+   |         |
+   |         unsatisfied trait bound introduced here
 help: consider restricting the type parameter to satisfy the trait bound
    |
 LL | struct Fin<T> where T: Bar, T: Default {
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
index fedb1ffdea9..9dbaffd4c15 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
@@ -54,6 +54,12 @@ LL |         const _: () = check($exp);
 LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
    |
+note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
+  --> $DIR/const-drop-fail.rs:28:25
+   |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+   |                         ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: 1 redundant requirement hidden
    = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
 note: required by a bound in `check`
   --> $DIR/const-drop-fail.rs:34:19
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
index fedb1ffdea9..9dbaffd4c15 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
@@ -54,6 +54,12 @@ LL |         const _: () = check($exp);
 LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
    |
+note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
+  --> $DIR/const-drop-fail.rs:28:25
+   |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+   |                         ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: 1 redundant requirement hidden
    = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
 note: required by a bound in `check`
   --> $DIR/const-drop-fail.rs:34:19
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
index 81e2a9a1ffc..9894ecc64b5 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -20,8 +20,7 @@ LL | struct MyStruct;
 LL |     println!("{}", MyStruct.foo_one());
    |                             ^^^^^^^ method cannot be called on `MyStruct` due to unsatisfied trait bounds
    |
-note: the following trait bounds were not satisfied because of the requirements of the implementation of `Foo` for `_`:
-      `MyStruct: Foo`
+note: trait bound `MyStruct: Foo` was not satisfied
   --> $DIR/specialization-trait-not-implemented.rs:14:17
    |
 LL | default impl<T> Foo for T {
diff --git a/src/test/ui/traits/alias/cross-crate.stderr b/src/test/ui/traits/alias/cross-crate.stderr
index 3c3b6e56690..d0d00c97e83 100644
--- a/src/test/ui/traits/alias/cross-crate.stderr
+++ b/src/test/ui/traits/alias/cross-crate.stderr
@@ -5,6 +5,7 @@ LL |     use_alias::<Rc<u32>>();
    |                 ^^^^^^^ `Rc<u32>` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `Rc<u32>`
+   = note: required because of the requirements on the impl of `SendSync` for `Rc<u32>`
 note: required by a bound in `use_alias`
   --> $DIR/cross-crate.rs:10:17
    |
@@ -18,6 +19,7 @@ LL |     use_alias::<Rc<u32>>();
    |                 ^^^^^^^ `Rc<u32>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `Rc<u32>`
+   = note: required because of the requirements on the impl of `SendSync` for `Rc<u32>`
 note: required by a bound in `use_alias`
   --> $DIR/cross-crate.rs:10:17
    |
diff --git a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
index 8405d7ddc7a..9ceeea4872f 100644
--- a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
+++ b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
@@ -14,7 +14,11 @@ LL |     let (a, b) = copy(NoClone);
    |                  |
    |                  required by a bound introduced by this call
    |
-   = note: required because of the requirements on the impl of `Magic` for `NoClone`
+note: required because of the requirements on the impl of `Magic` for `NoClone`
+  --> $DIR/supertrait-auto-trait.rs:8:12
+   |
+LL | auto trait Magic: Copy {}
+   |            ^^^^^
 note: required by a bound in `copy`
   --> $DIR/supertrait-auto-trait.rs:10:12
    |
diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr
index e8e65fe5d1d..de0bc7830b7 100644
--- a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr
+++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr
@@ -13,6 +13,11 @@ LL | struct CloneNoCopy;
 LL |     let w = u.clone();
    |               ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
    |
+note: trait bound `CloneNoCopy: Copy` was not satisfied
+  --> $DIR/union-derive-clone.rs:28:10
+   |
+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<CloneNoCopy>: Clone`
diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr
index e8e65fe5d1d..de0bc7830b7 100644
--- a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr
+++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr
@@ -13,6 +13,11 @@ LL | struct CloneNoCopy;
 LL |     let w = u.clone();
    |               ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
    |
+note: trait bound `CloneNoCopy: Copy` was not satisfied
+  --> $DIR/union-derive-clone.rs:28:10
+   |
+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<CloneNoCopy>: Clone`
diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.stderr b/src/test/ui/wf/hir-wf-check-erase-regions.stderr
index aef6db0a40b..0d9b9627562 100644
--- a/src/test/ui/wf/hir-wf-check-erase-regions.stderr
+++ b/src/test/ui/wf/hir-wf-check-erase-regions.stderr
@@ -5,11 +5,7 @@ LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&T`
-note: required because of the requirements on the impl of `IntoIterator` for `&T`
-  --> $DIR/hir-wf-check-erase-regions.rs:6:29
-   |
-LL | impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
-   |                             ^^^^^^^^^^^^     ^^^^^^^^^^^^^^^
+   = note: required because of the requirements on the impl of `IntoIterator` for `&T`
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
    |
@@ -23,11 +19,7 @@ LL |     fn into_iter(self) -> Self::IntoIter {
    |                           ^^^^^^^^^^^^^^ `&T` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&T`
-note: required because of the requirements on the impl of `IntoIterator` for `&T`
-  --> $DIR/hir-wf-check-erase-regions.rs:6:29
-   |
-LL | impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
-   |                             ^^^^^^^^^^^^     ^^^^^^^^^^^^^^^
+   = note: required because of the requirements on the impl of `IntoIterator` for `&T`
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
    |