about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs26
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs69
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs18
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs27
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs12
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs10
-rw-r--r--compiler/rustc_middle/src/ty/error.rs8
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs40
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs9
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs42
-rw-r--r--src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs2
-rw-r--r--src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr2
-rw-r--r--src/test/ui/generic-associated-types/generic-associated-types-where.stderr4
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds.rs4
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds.stderr34
-rw-r--r--src/test/ui/generic-associated-types/issue-47206-where-clause.stderr4
-rw-r--r--src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs2
-rw-r--r--src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr9
-rw-r--r--src/test/ui/nll/trait-associated-constant.rs2
-rw-r--r--src/test/ui/nll/trait-associated-constant.stderr2
22 files changed, 126 insertions, 208 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 4e87ec86658..e06af1fac06 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1883,7 +1883,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             exp_span, exp_found.expected, exp_found.found,
         );
 
-        if let ObligationCauseCode::CompareImplMethodObligation { .. } = cause.code() {
+        if let ObligationCauseCode::CompareImplItemObligation { .. } = cause.code() {
             return;
         }
 
@@ -2351,7 +2351,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             GenericKind::Projection(ref p) => format!("the associated type `{}`", p),
         };
 
-        if let Some(SubregionOrigin::CompareImplMethodObligation {
+        if let Some(SubregionOrigin::CompareImplItemObligation {
             span,
             impl_item_def_id,
             trait_item_def_id,
@@ -2788,8 +2788,15 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
         use self::FailureCode::*;
         use crate::traits::ObligationCauseCode::*;
         match self.code() {
-            CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"),
-            CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
+            CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => {
+                Error0308("method not compatible with trait")
+            }
+            CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => {
+                Error0308("type not compatible with trait")
+            }
+            CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => {
+                Error0308("const not compatible with trait")
+            }
             MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
                 Error0308(match source {
                     hir::MatchSource::TryDesugar => "`?` operator has incompatible types",
@@ -2823,8 +2830,15 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
     fn as_requirement_str(&self) -> &'static str {
         use crate::traits::ObligationCauseCode::*;
         match self.code() {
-            CompareImplMethodObligation { .. } => "method type is compatible with trait",
-            CompareImplTypeObligation { .. } => "associated type is compatible with trait",
+            CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => {
+                "method type is compatible with trait"
+            }
+            CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => {
+                "associated type is compatible with trait"
+            }
+            CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => {
+                "const is compatible with trait"
+            }
             ExprAssignable => "expression is assignable",
             IfExpression { .. } => "`if` and `else` have incompatible types",
             IfExpressionWithNoElse => "`if` missing an `else` returns `()`",
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index 91bf9695dfc..da465a76429 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -2,17 +2,17 @@
 
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
-use crate::infer::{SubregionOrigin, Subtype};
-use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
+use crate::infer::Subtype;
+use crate::traits::ObligationCauseCode::CompareImplItemObligation;
 use rustc_errors::{ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::print::RegionHighlightMode;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
-use rustc_span::{Span, Symbol};
+use rustc_span::Span;
 
 use std::ops::ControlFlow;
 
@@ -22,38 +22,22 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let error = self.error.as_ref()?;
         debug!("try_report_impl_not_conforming_to_trait {:?}", error);
         if let RegionResolutionError::SubSupConflict(
-                _, var_origin, sub_origin, _sub, sup_origin, _sup, _,
+                _,
+                var_origin,
+                sub_origin,
+                _sub,
+                sup_origin,
+                _sup,
+                _,
             ) = error.clone()
-            && let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin)
-            && let (
-                sub_expected_found @ Some((sub_expected, sub_found)),
-                sup_expected_found @ Some(_),
-                CompareImplMethodObligation { trait_item_def_id, .. },
-            ) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code())
+            && let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin)
+            && let sub_expected_found @ Some((sub_expected, sub_found)) = sub_trace.values.ty()
+            && let sup_expected_found @ Some(_) = sup_trace.values.ty()
+            && let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code()
             && sup_expected_found == sub_expected_found
         {
-            let guar = self.emit_err(
-                var_origin.span(),
-                sub_expected,
-                sub_found,
-                *trait_item_def_id,
-            );
-            return Some(guar);
-        }
-        if let RegionResolutionError::ConcreteFailure(origin, _, _)
-            | RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
-            && let SubregionOrigin::CompareImplTypeObligation {
-                span,
-                impl_item_def_id,
-                trait_item_def_id,
-            } = origin
-        {
-            let guar = self.emit_associated_type_err(
-                span,
-                self.infcx.tcx.item_name(impl_item_def_id.to_def_id()),
-                impl_item_def_id,
-                trait_item_def_id,
-            );
+            let guar =
+                self.emit_err(var_origin.span(), sub_expected, sub_found, *trait_item_def_id);
             return Some(guar);
         }
         None
@@ -147,25 +131,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         }
         err.emit()
     }
-
-    fn emit_associated_type_err(
-        &self,
-        span: Span,
-        item_name: Symbol,
-        impl_item_def_id: LocalDefId,
-        trait_item_def_id: DefId,
-    ) -> ErrorGuaranteed {
-        let impl_sp = self.tcx().def_span(impl_item_def_id);
-        let trait_sp = self.tcx().def_span(trait_item_def_id);
-        let mut err = self
-            .tcx()
-            .sess
-            .struct_span_err(span, &format!("`impl` associated type signature for `{}` doesn't match `trait` associated type signature", item_name));
-        err.span_label(impl_sp, "found");
-        err.span_label(trait_sp, "expected");
-
-        err.emit()
-    }
 }
 
 struct TypeParamSpanVisitor<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index b6d41bedd56..c1940c5c082 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -86,13 +86,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     "...so that the declared lifetime parameter bounds are satisfied",
                 );
             }
-            infer::CompareImplMethodObligation { span, .. } => {
-                label_or_note(
-                    span,
-                    "...so that the definition in impl matches the definition from the trait",
-                );
-            }
-            infer::CompareImplTypeObligation { span, .. } => {
+            infer::CompareImplItemObligation { span, .. } => {
                 label_or_note(
                     span,
                     "...so that the definition in impl matches the definition from the trait",
@@ -329,15 +323,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 );
                 err
             }
-            infer::CompareImplMethodObligation { span, impl_item_def_id, trait_item_def_id } => {
-                self.report_extra_impl_obligation(
-                    span,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                    &format!("`{}: {}`", sup, sub),
-                )
-            }
-            infer::CompareImplTypeObligation { span, impl_item_def_id, trait_item_def_id } => self
+            infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self
                 .report_extra_impl_obligation(
                     span,
                     impl_item_def_id,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 85692e109be..5e7c0661728 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -405,15 +405,7 @@ pub enum SubregionOrigin<'tcx> {
 
     /// Comparing the signature and requirements of an impl method against
     /// the containing trait.
-    CompareImplMethodObligation {
-        span: Span,
-        impl_item_def_id: LocalDefId,
-        trait_item_def_id: DefId,
-    },
-
-    /// Comparing the signature and requirements of an impl associated type
-    /// against the containing trait
-    CompareImplTypeObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId },
+    CompareImplItemObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId },
 
     /// Checking that the bounds of a trait's associated type hold for a given impl
     CheckAssociatedTypeBounds {
@@ -1945,8 +1937,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
             ReborrowUpvar(a, _) => a,
             DataBorrowed(_, a) => a,
             ReferenceOutlivesReferent(_, a) => a,
-            CompareImplMethodObligation { span, .. } => span,
-            CompareImplTypeObligation { span, .. } => span,
+            CompareImplItemObligation { span, .. } => span,
             CheckAssociatedTypeBounds { ref parent, .. } => parent.span(),
         }
     }
@@ -1960,19 +1951,11 @@ impl<'tcx> SubregionOrigin<'tcx> {
                 SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span)
             }
 
-            traits::ObligationCauseCode::CompareImplMethodObligation {
-                impl_item_def_id,
-                trait_item_def_id,
-            } => SubregionOrigin::CompareImplMethodObligation {
-                span: cause.span,
-                impl_item_def_id,
-                trait_item_def_id,
-            },
-
-            traits::ObligationCauseCode::CompareImplTypeObligation {
+            traits::ObligationCauseCode::CompareImplItemObligation {
                 impl_item_def_id,
                 trait_item_def_id,
-            } => SubregionOrigin::CompareImplTypeObligation {
+                kind: _,
+            } => SubregionOrigin::CompareImplItemObligation {
                 span: cause.span,
                 impl_item_def_id,
                 trait_item_def_id,
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index c55971557fa..72b848c3ee2 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -311,18 +311,10 @@ pub enum ObligationCauseCode<'tcx> {
     },
 
     /// Error derived when matching traits/impls; see ObligationCause for more details
-    CompareImplConstObligation,
-
-    /// Error derived when matching traits/impls; see ObligationCause for more details
-    CompareImplMethodObligation {
-        impl_item_def_id: LocalDefId,
-        trait_item_def_id: DefId,
-    },
-
-    /// Error derived when matching traits/impls; see ObligationCause for more details
-    CompareImplTypeObligation {
+    CompareImplItemObligation {
         impl_item_def_id: LocalDefId,
         trait_item_def_id: DefId,
+        kind: ty::AssocKind,
     },
 
     /// Checking that the bounds of a trait's associated type hold for a given impl
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index 2c93af50667..eb732148e3e 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -105,6 +105,16 @@ impl AssocKind {
     }
 }
 
+impl std::fmt::Display for AssocKind {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            AssocKind::Fn => write!(f, "method"),
+            AssocKind::Const => write!(f, "associated const"),
+            AssocKind::Type => write!(f, "associated type"),
+        }
+    }
+}
+
 /// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name.
 ///
 /// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 49a518b101d..91246051316 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -660,12 +660,8 @@ impl<T> Trait<T> for X {
                     | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }),
             )
         );
-        let impl_comparison = matches!(
-            cause_code,
-            ObligationCauseCode::CompareImplMethodObligation { .. }
-                | ObligationCauseCode::CompareImplTypeObligation { .. }
-                | ObligationCauseCode::CompareImplConstObligation
-        );
+        let impl_comparison =
+            matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
         let assoc = self.associated_item(proj_ty.item_def_id);
         if !callable_scope || impl_comparison {
             // We do not want to suggest calling functions when the reason of the
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 1f1f80ed618..7660a2f3af6 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -224,6 +224,7 @@ TrivialTypeTraversalAndLiftImpls! {
     // general `Region`.
     crate::ty::BoundRegionKind,
     crate::ty::AssocItem,
+    crate::ty::AssocKind,
     crate::ty::Placeholder<crate::ty::BoundRegionKind>,
     crate::ty::ClosureKind,
     crate::ty::FreeRegion,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 2f92a77a795..41c5087c43d 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -301,13 +301,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         span = obligation.cause.span;
                     }
                 }
-                if let ObligationCauseCode::CompareImplMethodObligation {
-                    impl_item_def_id,
-                    trait_item_def_id,
-                }
-                | ObligationCauseCode::CompareImplTypeObligation {
+                if let ObligationCauseCode::CompareImplItemObligation {
                     impl_item_def_id,
                     trait_item_def_id,
+                    kind: _,
                 } = *obligation.cause.code()
                 {
                     self.report_extra_impl_obligation(
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 7ab85e7fa66..89d7c050c40 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2682,11 +2682,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     )
                 });
             }
-            ObligationCauseCode::CompareImplMethodObligation { trait_item_def_id, .. } => {
+            ObligationCauseCode::CompareImplItemObligation { trait_item_def_id, kind, .. } => {
                 let item_name = self.tcx.item_name(trait_item_def_id);
                 let msg = format!(
-                    "the requirement `{}` appears on the impl method `{}` but not on the \
-                     corresponding trait method",
+                    "the requirement `{}` appears on the `impl`'s {kind} `{}` but not on the \
+                     corresponding trait's {kind}",
                     predicate, item_name,
                 );
                 let sp = self
@@ -2697,7 +2697,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 let mut assoc_span: MultiSpan = sp.into();
                 assoc_span.push_span_label(
                     sp,
-                    format!("this trait method doesn't have the requirement `{}`", predicate),
+                    format!("this trait's {kind} doesn't have the requirement `{}`", predicate),
                 );
                 if let Some(ident) = self
                     .tcx
@@ -2708,38 +2708,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 }
                 err.span_note(assoc_span, &msg);
             }
-            ObligationCauseCode::CompareImplTypeObligation { trait_item_def_id, .. } => {
-                let item_name = self.tcx.item_name(trait_item_def_id);
-                let msg = format!(
-                    "the requirement `{}` appears on the associated impl type `{}` but not on the \
-                     corresponding associated trait type",
-                    predicate, item_name,
-                );
-                let sp = self.tcx.def_span(trait_item_def_id);
-                let mut assoc_span: MultiSpan = sp.into();
-                assoc_span.push_span_label(
-                    sp,
-                    format!(
-                        "this trait associated type doesn't have the requirement `{}`",
-                        predicate,
-                    ),
-                );
-                if let Some(ident) = self
-                    .tcx
-                    .opt_associated_item(trait_item_def_id)
-                    .and_then(|i| self.tcx.opt_item_ident(i.container.id()))
-                {
-                    assoc_span.push_span_label(ident.span, "in this trait");
-                }
-                err.span_note(assoc_span, &msg);
-            }
-            ObligationCauseCode::CompareImplConstObligation => {
-                err.note(&format!(
-                    "the requirement `{}` appears on the associated impl constant \
-                     but not on the corresponding associated trait constant",
-                    predicate
-                ));
-            }
             ObligationCauseCode::TrivialBound => {
                 err.help("see issue #48214");
                 if tcx.sess.opts.unstable_features.is_nightly_build() {
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 7111812f0b0..04f2eb459cf 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -1150,17 +1150,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             .expect("missing associated type");
 
         if !assoc_item.vis.is_accessible_from(def_scope, tcx) {
-            let kind = match assoc_item.kind {
-                ty::AssocKind::Type => "type",
-                ty::AssocKind::Const => "const",
-                _ => unreachable!(),
-            };
             tcx.sess
                 .struct_span_err(
                     binding.span,
-                    &format!("associated {kind} `{}` is private", binding.item_name),
+                    &format!("{} `{}` is private", assoc_item.kind, binding.item_name),
                 )
-                .span_label(binding.span, &format!("private associated {kind}"))
+                .span_label(binding.span, &format!("private {}", assoc_item.kind))
                 .emit();
         }
         tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None);
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 1a9354f5d20..af77efc3c2d 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -90,9 +90,10 @@ fn compare_predicate_entailment<'tcx>(
     let mut cause = ObligationCause::new(
         impl_m_span,
         impl_m_hir_id,
-        ObligationCauseCode::CompareImplMethodObligation {
+        ObligationCauseCode::CompareImplItemObligation {
             impl_item_def_id: impl_m.def_id.expect_local(),
             trait_item_def_id: trait_m.def_id,
+            kind: impl_m.kind,
         },
     );
 
@@ -223,9 +224,10 @@ fn compare_predicate_entailment<'tcx>(
             let cause = ObligationCause::new(
                 span,
                 impl_m_hir_id,
-                ObligationCauseCode::CompareImplMethodObligation {
+                ObligationCauseCode::CompareImplItemObligation {
                     impl_item_def_id: impl_m.def_id.expect_local(),
                     trait_item_def_id: trait_m.def_id,
+                    kind: impl_m.kind,
                 },
             );
             ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
@@ -1079,7 +1081,11 @@ pub(crate) fn compare_const_impl<'tcx>(
         let mut cause = ObligationCause::new(
             impl_c_span,
             impl_c_hir_id,
-            ObligationCauseCode::CompareImplConstObligation,
+            ObligationCauseCode::CompareImplItemObligation {
+                impl_item_def_id: impl_c.def_id.expect_local(),
+                trait_item_def_id: trait_c.def_id,
+                kind: impl_c.kind,
+            },
         );
 
         // There is no "body" here, so just pass dummy id.
@@ -1212,15 +1218,6 @@ fn compare_type_predicate_entailment<'tcx>(
     // `ObligationCause` (and the `FnCtxt`). This is what
     // `regionck_item` expects.
     let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
-    let cause = ObligationCause::new(
-        impl_ty_span,
-        impl_ty_hir_id,
-        ObligationCauseCode::CompareImplTypeObligation {
-            impl_item_def_id: impl_ty.def_id.expect_local(),
-            trait_item_def_id: trait_ty.def_id,
-        },
-    );
-
     debug!("compare_type_predicate_entailment: trait_to_impl_substs={:?}", trait_to_impl_substs);
 
     // The predicates declared by the impl definition, the trait and the
@@ -1239,7 +1236,7 @@ fn compare_type_predicate_entailment<'tcx>(
         Reveal::UserFacing,
         hir::Constness::NotConst,
     );
-    let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause.clone());
+    let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
     tcx.infer_ctxt().enter(|infcx| {
         let ocx = ObligationCtxt::new(&infcx);
 
@@ -1247,12 +1244,25 @@ fn compare_type_predicate_entailment<'tcx>(
 
         let mut selcx = traits::SelectionContext::new(&infcx);
 
-        for predicate in impl_ty_own_bounds.predicates {
+        assert_eq!(impl_ty_own_bounds.predicates.len(), impl_ty_own_bounds.spans.len());
+        for (span, predicate) in
+            std::iter::zip(impl_ty_own_bounds.spans, impl_ty_own_bounds.predicates)
+        {
+            let cause = ObligationCause::misc(span, impl_ty_hir_id);
             let traits::Normalized { value: predicate, obligations } =
-                traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate);
+                traits::normalize(&mut selcx, param_env, cause, predicate);
 
+            let cause = ObligationCause::new(
+                span,
+                impl_ty_hir_id,
+                ObligationCauseCode::CompareImplItemObligation {
+                    impl_item_def_id: impl_ty.def_id.expect_local(),
+                    trait_item_def_id: trait_ty.def_id,
+                    kind: impl_ty.kind,
+                },
+            );
             ocx.register_obligations(obligations);
-            ocx.register_obligation(traits::Obligation::new(cause.clone(), param_env, predicate));
+            ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
         }
 
         // Check that all obligations are satisfied by the implementation's
diff --git a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs
index 08260ec8f4d..63bac96135b 100644
--- a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs
+++ b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs
@@ -5,7 +5,7 @@ trait Foo {
 
 impl<'a> Foo for &'a () {
     const NAME: &'a str = "unit";
-    //~^ ERROR mismatched types [E0308]
+    //~^ ERROR const not compatible with trait
 }
 
 fn main() {}
diff --git a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
index f71fb2ee18a..de1d9589e99 100644
--- a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
+++ b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
@@ -1,4 +1,4 @@
-error[E0308]: mismatched types
+error[E0308]: const not compatible with trait
   --> $DIR/associated-const-impl-wrong-lifetime.rs:7:5
    |
 LL |     const NAME: &'a str = "unit";
diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr
index c7ebb9880f7..e866b3bab79 100644
--- a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr
+++ b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr
@@ -11,13 +11,13 @@ LL |     type Assoc2<T: std::fmt::Display> = Vec<T>;
    |                  +++++++++++++++++++
 
 error[E0276]: impl has stricter requirements than trait
-  --> $DIR/generic-associated-types-where.rs:22:5
+  --> $DIR/generic-associated-types-where.rs:22:38
    |
 LL |     type Assoc3<T>;
    |     -------------- definition of `Assoc3` from trait
 ...
 LL |     type Assoc3<T> = Vec<T> where T: Iterator;
-   |     ^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
+   |                                      ^^^^^^^^ impl has extra requirement `T: Iterator`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs
index bb5992c88f0..ec1d171c044 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.rs
+++ b/src/test/ui/generic-associated-types/impl_bounds.rs
@@ -13,9 +13,9 @@ struct Fooy<T>(T);
 
 impl<T> Foo for Fooy<T> {
     type A<'a> = (&'a ()) where Self: 'static;
-    //~^ ERROR `impl` associated type
+    //~^ ERROR impl has stricter requirements than trait
     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
-    //~^ ERROR `impl` associated type
+    //~^ ERROR impl has stricter requirements than trait
     //~| ERROR lifetime bound not satisfied
     type C = String where Self: Copy;
     //~^ ERROR the trait bound `T: Copy` is not satisfied
diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr
index 6aa52b179a3..ce79c635add 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.stderr
+++ b/src/test/ui/generic-associated-types/impl_bounds.stderr
@@ -1,20 +1,20 @@
-error: `impl` associated type signature for `A` doesn't match `trait` associated type signature
-  --> $DIR/impl_bounds.rs:15:5
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/impl_bounds.rs:15:39
    |
 LL |     type A<'a> where Self: 'a;
-   |     ---------- expected
+   |     ---------- definition of `A` from trait
 ...
 LL |     type A<'a> = (&'a ()) where Self: 'static;
-   |     ^^^^^^^^^^ found
+   |                                       ^^^^^^^ impl has extra requirement `T: 'static`
 
-error: `impl` associated type signature for `B` doesn't match `trait` associated type signature
-  --> $DIR/impl_bounds.rs:17:5
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/impl_bounds.rs:17:48
    |
 LL |     type B<'a, 'b> where 'a: 'b;
-   |     -------------- expected
+   |     -------------- definition of `B` from trait
 ...
 LL |     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
-   |     ^^^^^^^^^^^^^^ found
+   |                                                ^^ impl has extra requirement `'b: 'a`
 
 error[E0478]: lifetime bound not satisfied
   --> $DIR/impl_bounds.rs:17:22
@@ -37,24 +37,24 @@ LL |     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
    |                ^^
 
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/impl_bounds.rs:20:5
+  --> $DIR/impl_bounds.rs:20:33
    |
 LL |     type C = String where Self: Copy;
-   |     ^^^^^^ the trait `Copy` is not implemented for `T`
+   |                                 ^^^^ the trait `Copy` is not implemented for `T`
    |
 note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
   --> $DIR/impl_bounds.rs:11:10
    |
 LL | #[derive(Copy, Clone)]
    |          ^^^^
-note: the requirement `Fooy<T>: Copy` appears on the associated impl type `C` but not on the corresponding associated trait type
-  --> $DIR/impl_bounds.rs:7:5
+note: the requirement `Fooy<T>: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type
+  --> $DIR/impl_bounds.rs:7:10
    |
 LL | trait Foo {
    |       --- in this trait
 ...
 LL |     type C where Self: Clone;
-   |     ^^^^^^ this trait associated type doesn't have the requirement `Fooy<T>: Copy`
+   |          ^ this trait's associated type doesn't have the requirement `Fooy<T>: Copy`
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
@@ -72,14 +72,14 @@ note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
    |
 LL | #[derive(Copy, Clone)]
    |          ^^^^
-note: the requirement `Fooy<T>: Copy` appears on the impl method `d` but not on the corresponding trait method
+note: the requirement `Fooy<T>: Copy` appears on the `impl`'s method `d` but not on the corresponding trait's method
   --> $DIR/impl_bounds.rs:8:8
    |
 LL | trait Foo {
    |       --- in this trait
 ...
 LL |     fn d() where Self: Clone;
-   |        ^ this trait method doesn't have the requirement `Fooy<T>: Copy`
+   |        ^ this trait's method doesn't have the requirement `Fooy<T>: Copy`
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
@@ -88,5 +88,5 @@ LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0277, E0478.
-For more information about an error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0276, E0277, E0478.
+For more information about an error, try `rustc --explain E0276`.
diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr
index c560e2405d5..31948a878ed 100644
--- a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr
+++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr
@@ -1,11 +1,11 @@
 error[E0276]: impl has stricter requirements than trait
-  --> $DIR/issue-47206-where-clause.rs:12:5
+  --> $DIR/issue-47206-where-clause.rs:12:38
    |
 LL |     type Assoc3<T>;
    |     -------------- definition of `Assoc3` from trait
 ...
 LL |     type Assoc3<T> = Vec<T> where T: Iterator;
-   |     ^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
+   |                                      ^^^^^^^^ impl has extra requirement `T: Iterator`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs
index 5fb8f7a4773..8171dc0ae28 100644
--- a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs
+++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs
@@ -7,7 +7,7 @@ trait Foo {
 }
 impl Foo for () {
     type Assoc<'a, 'b> = () where 'a: 'b;
-    //~^ `impl` associated type
+    //~^ impl has stricter requirements than trait
 }
 
 fn main() {}
diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr
index 0256d2f20fc..edd1f9367d1 100644
--- a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr
+++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr
@@ -1,11 +1,12 @@
-error: `impl` associated type signature for `Assoc` doesn't match `trait` associated type signature
-  --> $DIR/missing-where-clause-on-trait.rs:9:5
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/missing-where-clause-on-trait.rs:9:39
    |
 LL |     type Assoc<'a, 'b>;
-   |     ------------------ expected
+   |     ------------------ definition of `Assoc` from trait
 ...
 LL |     type Assoc<'a, 'b> = () where 'a: 'b;
-   |     ^^^^^^^^^^^^^^^^^^ found
+   |                                       ^^ impl has extra requirement `'a: 'b`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0276`.
diff --git a/src/test/ui/nll/trait-associated-constant.rs b/src/test/ui/nll/trait-associated-constant.rs
index 31dc58185e9..e13ae80f918 100644
--- a/src/test/ui/nll/trait-associated-constant.rs
+++ b/src/test/ui/nll/trait-associated-constant.rs
@@ -19,7 +19,7 @@ struct FailStruct { }
 
 impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct {
     const AC: Option<&'c str> = None;
-    //~^ ERROR: mismatched types
+    //~^ ERROR: const not compatible with trait
 }
 
 struct OKStruct2 { }
diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr
index 000ebc71657..ae0ffd904e7 100644
--- a/src/test/ui/nll/trait-associated-constant.stderr
+++ b/src/test/ui/nll/trait-associated-constant.stderr
@@ -1,4 +1,4 @@
-error[E0308]: mismatched types
+error[E0308]: const not compatible with trait
   --> $DIR/trait-associated-constant.rs:21:5
    |
 LL |     const AC: Option<&'c str> = None;