diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index f9dd649ab9f82..d676ce59cfe3f 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -1,10 +1,7 @@
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::ErrorGuaranteed;
-use rustc_hir::OpaqueTyOrigin;
-use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _};
-use rustc_infer::traits::{Obligation, ObligationCause};
 use rustc_macros::extension;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{
@@ -12,7 +9,6 @@ use rustc_middle::ty::{
     TypingMode,
 };
 use rustc_span::Span;
-use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::ObligationCtxt;
 use tracing::{debug, instrument};
 
@@ -303,91 +299,7 @@ impl<'tcx> InferCtxt<'tcx> {
             return Ty::new_error(self.tcx, e);
         }
 
-        // `definition_ty` does not live in of the current inference context,
-        // so lets make sure that we don't accidentally misuse our current `infcx`.
-        match check_opaque_type_well_formed(
-            self.tcx,
-            self.next_trait_solver(),
-            opaque_type_key.def_id,
-            instantiated_ty.span,
-            definition_ty,
-        ) {
-            Ok(hidden_ty) => hidden_ty,
-            Err(guar) => Ty::new_error(self.tcx, guar),
-        }
-    }
-}
-
-/// This logic duplicates most of `check_opaque_meets_bounds`.
-/// FIXME(oli-obk): Also do region checks here and then consider removing
-/// `check_opaque_meets_bounds` entirely.
-fn check_opaque_type_well_formed<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    next_trait_solver: bool,
-    def_id: LocalDefId,
-    definition_span: Span,
-    definition_ty: Ty<'tcx>,
-) -> Result<Ty<'tcx>, ErrorGuaranteed> {
-    // Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
-    // on stable and we'd break that.
-    let opaque_ty_hir = tcx.hir().expect_opaque_ty(def_id);
-    let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.origin else {
-        return Ok(definition_ty);
-    };
-    let param_env = tcx.param_env(def_id);
-
-    let mut parent_def_id = def_id;
-    while tcx.def_kind(parent_def_id) == DefKind::OpaqueTy {
-        parent_def_id = tcx.local_parent(parent_def_id);
-    }
-
-    // FIXME(#132279): This should eventually use the already defined hidden types
-    // instead. Alternatively we'll entirely remove this function given we also check
-    // the opaque in `check_opaque_meets_bounds` later.
-    let infcx = tcx
-        .infer_ctxt()
-        .with_next_trait_solver(next_trait_solver)
-        .build(TypingMode::analysis_in_body(tcx, parent_def_id));
-    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
-    let identity_args = GenericArgs::identity_for_item(tcx, def_id);
-
-    // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
-    // the bounds that the function supplies.
-    let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args);
-    ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty)
-        .map_err(|err| {
-            infcx
-                .err_ctxt()
-                .report_mismatched_types(
-                    &ObligationCause::misc(definition_span, def_id),
-                    param_env,
-                    opaque_ty,
-                    definition_ty,
-                    err,
-                )
-                .emit()
-        })?;
-
-    // Require the hidden type to be well-formed with only the generics of the opaque type.
-    // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
-    // hidden type is well formed even without those bounds.
-    let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
-        definition_ty.into(),
-    )));
-    ocx.register_obligation(Obligation::misc(tcx, definition_span, def_id, param_env, predicate));
-
-    // Check that all obligations are satisfied by the implementation's
-    // version.
-    let errors = ocx.select_all_or_error();
-
-    // This is fishy, but we check it again in `check_opaque_meets_bounds`.
-    // Remove once we can prepopulate with known hidden types.
-    let _ = infcx.take_opaque_types();
-
-    if errors.is_empty() {
-        Ok(definition_ty)
-    } else {
-        Err(infcx.err_ctxt().report_fulfillment_errors(errors))
+        definition_ty
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 50ea8018e7601..3080d8b351083 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -5,13 +5,14 @@ use rustc_abi::FieldIdx;
 use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_errors::MultiSpan;
 use rustc_errors::codes::*;
-use rustc_hir::Node;
 use rustc_hir::def::{CtorKind, DefKind};
+use rustc_hir::{Node, intravisit};
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
-use rustc_infer::traits::Obligation;
+use rustc_infer::traits::{Obligation, ObligationCauseCode};
 use rustc_lint_defs::builtin::{
     REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS,
 };
+use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::span_bug;
@@ -190,7 +191,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
 /// projections that would result in "inheriting lifetimes".
 fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir::OpaqueTy { origin, .. } = tcx.hir().expect_opaque_ty(def_id);
+    let hir::OpaqueTy { origin, .. } = *tcx.hir().expect_opaque_ty(def_id);
 
     // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
     // `async-std` (and `pub async fn` in general).
@@ -200,23 +201,20 @@ fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         return;
     }
 
-    let span = tcx.def_span(def_id);
-
     if tcx.type_of(def_id).instantiate_identity().references_error() {
         return;
     }
-    if check_opaque_for_cycles(tcx, def_id, span).is_err() {
+    if check_opaque_for_cycles(tcx, def_id).is_err() {
         return;
     }
 
-    let _ = check_opaque_meets_bounds(tcx, def_id, span, origin);
+    let _ = check_opaque_meets_bounds(tcx, def_id, origin);
 }
 
 /// Checks that an opaque type does not contain cycles.
 pub(super) fn check_opaque_for_cycles<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
-    span: Span,
 ) -> Result<(), ErrorGuaranteed> {
     let args = GenericArgs::identity_for_item(tcx, def_id);
 
@@ -233,7 +231,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
             .try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No)
             .is_err()
         {
-            let reported = opaque_type_cycle_error(tcx, def_id, span);
+            let reported = opaque_type_cycle_error(tcx, def_id);
             return Err(reported);
         }
 
@@ -267,10 +265,16 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
 fn check_opaque_meets_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
-    span: Span,
-    origin: &hir::OpaqueTyOrigin<LocalDefId>,
+    origin: hir::OpaqueTyOrigin<LocalDefId>,
 ) -> Result<(), ErrorGuaranteed> {
-    let defining_use_anchor = match *origin {
+    let (span, definition_def_id) =
+        if let Some((span, def_id)) = best_definition_site_of_opaque(tcx, def_id, origin) {
+            (span, Some(def_id))
+        } else {
+            (tcx.def_span(def_id), None)
+        };
+
+    let defining_use_anchor = match origin {
         hir::OpaqueTyOrigin::FnReturn { parent, .. }
         | hir::OpaqueTyOrigin::AsyncFn { parent, .. }
         | hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent,
@@ -281,7 +285,7 @@ fn check_opaque_meets_bounds<'tcx>(
     let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor));
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
-    let args = match *origin {
+    let args = match origin {
         hir::OpaqueTyOrigin::FnReturn { parent, .. }
         | hir::OpaqueTyOrigin::AsyncFn { parent, .. }
         | hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item(
@@ -306,8 +310,33 @@ fn check_opaque_meets_bounds<'tcx>(
         _ => re,
     });
 
-    let misc_cause = traits::ObligationCause::misc(span, def_id);
+    // HACK: We eagerly instantiate some bounds to report better errors for them...
+    // This isn't necessary for correctness, since we register these bounds when
+    // equating the opaque below, but we should clean this up in the new solver.
+    for (predicate, pred_span) in
+        tcx.explicit_item_bounds(def_id).iter_instantiated_copied(tcx, args)
+    {
+        let predicate = predicate.fold_with(&mut BottomUpFolder {
+            tcx,
+            ty_op: |ty| if ty == opaque_ty { hidden_ty } else { ty },
+            lt_op: |lt| lt,
+            ct_op: |ct| ct,
+        });
+
+        ocx.register_obligation(Obligation::new(
+            tcx,
+            ObligationCause::new(
+                span,
+                def_id,
+                ObligationCauseCode::OpaqueTypeBound(pred_span, definition_def_id),
+            ),
+            param_env,
+            predicate,
+        ));
+    }
 
+    let misc_cause = ObligationCause::misc(span, def_id);
+    // FIXME: We should just register the item bounds here, rather than equating.
     match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
         Ok(()) => {}
         Err(ty_err) => {
@@ -364,6 +393,97 @@ fn check_opaque_meets_bounds<'tcx>(
     }
 }
 
+fn best_definition_site_of_opaque<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    opaque_def_id: LocalDefId,
+    origin: hir::OpaqueTyOrigin<LocalDefId>,
+) -> Option<(Span, LocalDefId)> {
+    struct TaitConstraintLocator<'tcx> {
+        opaque_def_id: LocalDefId,
+        tcx: TyCtxt<'tcx>,
+    }
+    impl<'tcx> TaitConstraintLocator<'tcx> {
+        fn check(&self, item_def_id: LocalDefId) -> ControlFlow<(Span, LocalDefId)> {
+            if !self.tcx.has_typeck_results(item_def_id) {
+                return ControlFlow::Continue(());
+            }
+
+            if let Some(hidden_ty) =
+                self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id)
+            {
+                ControlFlow::Break((hidden_ty.span, item_def_id))
+            } else {
+                ControlFlow::Continue(())
+            }
+        }
+    }
+    impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
+        type NestedFilter = nested_filter::All;
+        type Result = ControlFlow<(Span, LocalDefId)>;
+        fn nested_visit_map(&mut self) -> Self::Map {
+            self.tcx.hir()
+        }
+        fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result {
+            if let hir::ExprKind::Closure(closure) = ex.kind {
+                self.check(closure.def_id)?;
+            }
+            intravisit::walk_expr(self, ex)
+        }
+        fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) -> Self::Result {
+            self.check(it.owner_id.def_id)?;
+            intravisit::walk_item(self, it)
+        }
+        fn visit_impl_item(&mut self, it: &'tcx hir::ImplItem<'tcx>) -> Self::Result {
+            self.check(it.owner_id.def_id)?;
+            intravisit::walk_impl_item(self, it)
+        }
+        fn visit_trait_item(&mut self, it: &'tcx hir::TraitItem<'tcx>) -> Self::Result {
+            self.check(it.owner_id.def_id)?;
+            intravisit::walk_trait_item(self, it)
+        }
+        fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) -> Self::Result {
+            intravisit::walk_foreign_item(self, it)
+        }
+    }
+
+    let mut locator = TaitConstraintLocator { tcx, opaque_def_id };
+    match origin {
+        hir::OpaqueTyOrigin::FnReturn { parent, .. }
+        | hir::OpaqueTyOrigin::AsyncFn { parent, .. } => locator.check(parent).break_value(),
+        hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty: true } => {
+            let impl_def_id = tcx.local_parent(parent);
+            for assoc in tcx.associated_items(impl_def_id).in_definition_order() {
+                match assoc.kind {
+                    ty::AssocKind::Const | ty::AssocKind::Fn => {
+                        if let ControlFlow::Break(span) = locator.check(assoc.def_id.expect_local())
+                        {
+                            return Some(span);
+                        }
+                    }
+                    ty::AssocKind::Type => {}
+                }
+            }
+
+            None
+        }
+        hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
+            let scope = tcx.hir().get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id));
+            let found = if scope == hir::CRATE_HIR_ID {
+                tcx.hir().walk_toplevel_module(&mut locator)
+            } else {
+                match tcx.hir_node(scope) {
+                    Node::Item(it) => locator.visit_item(it),
+                    Node::ImplItem(it) => locator.visit_impl_item(it),
+                    Node::TraitItem(it) => locator.visit_trait_item(it),
+                    Node::ForeignItem(it) => locator.visit_foreign_item(it),
+                    other => bug!("{:?} is not a valid scope for an opaque type item", other),
+                }
+            };
+            found.break_value()
+        }
+    }
+}
+
 fn sanity_check_found_hidden_type<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::OpaqueTypeKey<'tcx>,
@@ -1535,11 +1655,8 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
 ///
 /// If all the return expressions evaluate to `!`, then we explain that the error will go away
 /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
-fn opaque_type_cycle_error(
-    tcx: TyCtxt<'_>,
-    opaque_def_id: LocalDefId,
-    span: Span,
-) -> ErrorGuaranteed {
+fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorGuaranteed {
+    let span = tcx.def_span(opaque_def_id);
     let mut err = struct_span_code_err!(tcx.dcx(), span, E0720, "cannot resolve opaque type");
 
     let mut label = false;
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index e0e03a2922010..b1d5d688295d9 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -104,6 +104,7 @@ impl<'tcx> InferCtxt<'tcx> {
             infer::RelateParamBound(cause.span, sup_type, match cause.code().peel_derives() {
                 ObligationCauseCode::WhereClause(_, span)
                 | ObligationCauseCode::WhereClauseInExpr(_, span, ..)
+                | ObligationCauseCode::OpaqueTypeBound(span, _)
                     if !span.is_dummy() =>
                 {
                     Some(*span)
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 40e5ec4595982..09731d565b619 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -193,6 +193,11 @@ pub enum ObligationCauseCode<'tcx> {
     /// The span corresponds to the clause.
     WhereClause(DefId, Span),
 
+    /// Represents a bound for an opaque we are checking the well-formedness of.
+    /// The def-id corresponds to a specific definition site that we found the
+    /// hidden type from, if any.
+    OpaqueTypeBound(Span, Option<LocalDefId>),
+
     /// Like `WhereClause`, but also identifies the expression
     /// which requires the `where` clause to be proven, and also
     /// identifies the index of the predicate in the `predicates_of`
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 86fd4c230f636..a5e364d49f7cf 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -2953,6 +2953,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 // We hold the `DefId` of the item introducing the obligation, but displaying it
                 // doesn't add user usable information. It always point at an associated item.
             }
+            ObligationCauseCode::OpaqueTypeBound(span, definition_def_id) => {
+                err.span_note(span, "required by a bound in an opaque type");
+                if let Some(definition_def_id) = definition_def_id
+                    // If there are any stalled coroutine obligations, then this
+                    // error may be due to that, and not because the body has more
+                    // where-clauses.
+                    && self.tcx.typeck(definition_def_id).coroutine_stalled_predicates.is_empty()
+                {
+                    // FIXME(compiler-errors): We could probably point to something
+                    // specific here if we tried hard enough...
+                    err.span_note(
+                        tcx.def_span(definition_def_id),
+                        "this definition site has more where clauses than the opaque type",
+                    );
+                }
+            }
             ObligationCauseCode::Coercion { source, target } => {
                 let source =
                     tcx.short_ty_string(self.resolve_vars_if_possible(source), long_ty_file);
diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs
index a74bd9890ca11..2851637ae78fd 100644
--- a/tests/ui/async-await/issue-70935-complex-spans.rs
+++ b/tests/ui/async-await/issue-70935-complex-spans.rs
@@ -14,8 +14,8 @@ async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
 
 fn foo(x: NotSync) -> impl Future + Send {
     //~^ ERROR `*mut ()` cannot be shared between threads safely
-    //~| ERROR `*mut ()` cannot be shared between threads safely
     async move {
+    //~^ ERROR `*mut ()` cannot be shared between threads safely
         baz(|| async {
             foo(x.clone());
         }).await;
diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr
index c6b7e21b9dd2a..31d15c4592177 100644
--- a/tests/ui/async-await/issue-70935-complex-spans.stderr
+++ b/tests/ui/async-await/issue-70935-complex-spans.stderr
@@ -1,8 +1,13 @@
 error[E0277]: `*mut ()` cannot be shared between threads safely
-  --> $DIR/issue-70935-complex-spans.rs:15:23
+  --> $DIR/issue-70935-complex-spans.rs:17:5
    |
-LL | fn foo(x: NotSync) -> impl Future + Send {
-   |                       ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
+LL | /     async move {
+LL | |
+LL | |         baz(|| async {
+LL | |             foo(x.clone());
+LL | |         }).await;
+LL | |     }
+   | |_____^ `*mut ()` cannot be shared between threads safely
    |
    = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`
 note: required because it appears within the type `PhantomData<*mut ()>`
@@ -26,10 +31,15 @@ LL |   async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
 LL | | }
    | |_^
 note: required because it's used within this `async` block
-  --> $DIR/issue-70935-complex-spans.rs:18:5
+  --> $DIR/issue-70935-complex-spans.rs:17:5
    |
 LL |     async move {
    |     ^^^^^^^^^^
+note: required by a bound in an opaque type
+  --> $DIR/issue-70935-complex-spans.rs:15:37
+   |
+LL | fn foo(x: NotSync) -> impl Future + Send {
+   |                                     ^^^^
 
 error[E0277]: `*mut ()` cannot be shared between threads safely
   --> $DIR/issue-70935-complex-spans.rs:15:23
@@ -59,11 +69,10 @@ LL |   async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
 LL | | }
    | |_^
 note: required because it's used within this `async` block
-  --> $DIR/issue-70935-complex-spans.rs:18:5
+  --> $DIR/issue-70935-complex-spans.rs:17:5
    |
 LL |     async move {
    |     ^^^^^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr
index 75cba4b5f0276..34f8eb1e1635d 100644
--- a/tests/ui/pattern/usefulness/impl-trait.stderr
+++ b/tests/ui/pattern/usefulness/impl-trait.stderr
@@ -25,6 +25,20 @@ LL |             _ => {}
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
+error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty
+  --> $DIR/impl-trait.rs:23:11
+   |
+LL |     match return_never_rpit(x) {}
+   |           ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `impl Copy`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match return_never_rpit(x) {
+LL +         _ => todo!(),
+LL +     }
+   |
+
 error: unreachable pattern
   --> $DIR/impl-trait.rs:45:13
    |
@@ -93,6 +107,20 @@ LL |             _ => {}
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
+error[E0004]: non-exhaustive patterns: type `T` is non-empty
+  --> $DIR/impl-trait.rs:37:11
+   |
+LL |     match return_never_tait(x) {}
+   |           ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `T`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match return_never_tait(x) {
+LL +         _ => todo!(),
+LL +     }
+   |
+
 error: unreachable pattern
   --> $DIR/impl-trait.rs:105:9
    |
@@ -131,34 +159,6 @@ LL |             _ => {}
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
-error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty
-  --> $DIR/impl-trait.rs:23:11
-   |
-LL |     match return_never_rpit(x) {}
-   |           ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: the matched value is of type `impl Copy`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
-   |
-LL ~     match return_never_rpit(x) {
-LL +         _ => todo!(),
-LL +     }
-   |
-
-error[E0004]: non-exhaustive patterns: type `T` is non-empty
-  --> $DIR/impl-trait.rs:37:11
-   |
-LL |     match return_never_tait(x) {}
-   |           ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: the matched value is of type `T`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
-   |
-LL ~     match return_never_tait(x) {
-LL +         _ => todo!(),
-LL +     }
-   |
-
 error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr
index 0c937f9225380..8f887a6ac68f9 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr
@@ -4,6 +4,16 @@ error[E0277]: the trait bound `T: Clone` is not satisfied
 LL |         t
    |         ^ the trait `Clone` is not implemented for `T`
    |
+note: required by a bound in an opaque type
+  --> $DIR/bounds-are-checked-2.rs:7:26
+   |
+LL |     pub type X<T> = impl Clone;
+   |                          ^^^^^
+note: this definition site has more where clauses than the opaque type
+  --> $DIR/bounds-are-checked-2.rs:9:5
+   |
+LL |     fn f<T: Clone>(t: T) -> X<T> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider restricting type parameter `T`
    |
 LL |     pub type X<T: std::clone::Clone> = impl Clone;
diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs
index 430b444aae186..caa9b6d979aba 100644
--- a/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs
+++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs
@@ -12,20 +12,19 @@
 // requires `'a: 'b` bound
 mod test1 {
     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
-    //~^ ERROR lifetime bound not satisfied
 
     fn define<'a, 'b>() -> Opaque<'a, 'b>
     where
         'a: 'b,
     {
         || {}
+        //~^ ERROR lifetime bound not satisfied
     }
 }
 
 // Same as the above but through indirection `'x`
 mod test2 {
     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
-    //~^ ERROR cannot infer an appropriate lifetime
 
     fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
     where
@@ -33,6 +32,7 @@ mod test2 {
         'x: 'b,
     {
         || {}
+        //~^ ERROR cannot infer an appropriate lifetime
     }
 }
 
@@ -52,13 +52,13 @@ mod test2_fixed {
 // requires `T: 'static`
 mod test3 {
     type Opaque<T> = impl Sized;
-    //~^ ERROR the parameter type `T` may not live long enough
 
     fn define<T>() -> Opaque<T>
     where
         T: 'static,
     {
         || {}
+        //~^ ERROR the parameter type `T` may not live long enough
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr
index 3484485e3fd7f..04288112fa86d 100644
--- a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr
+++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr
@@ -1,8 +1,8 @@
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/closure_wf_outlives.rs:14:27
+  --> $DIR/closure_wf_outlives.rs:20:9
    |
-LL |     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
-   |                           ^^^^^^^^^^^^^^^^^^^^
+LL |         || {}
+   |         ^^^^^
    |
 note: lifetime parameter instantiated with the lifetime `'a` as defined here
   --> $DIR/closure_wf_outlives.rs:14:17
@@ -16,10 +16,10 @@ LL |     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
    |                     ^^
 
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
-  --> $DIR/closure_wf_outlives.rs:27:27
+  --> $DIR/closure_wf_outlives.rs:34:9
    |
-LL |     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
-   |                           ^^^^^^^^^^^^^^^^^^^^
+LL |         || {}
+   |         ^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
   --> $DIR/closure_wf_outlives.rs:27:17
@@ -27,32 +27,32 @@ note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
 LL |     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
    |                 ^^
 note: ...so that the declared lifetime parameter bounds are satisfied
-  --> $DIR/closure_wf_outlives.rs:27:27
+  --> $DIR/closure_wf_outlives.rs:34:9
    |
-LL |     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
-   |                           ^^^^^^^^^^^^^^^^^^^^
+LL |         || {}
+   |         ^^^^^
 note: but, the lifetime must be valid for the lifetime `'b` as defined here...
   --> $DIR/closure_wf_outlives.rs:27:21
    |
 LL |     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
    |                     ^^
 note: ...so that the declared lifetime parameter bounds are satisfied
-  --> $DIR/closure_wf_outlives.rs:27:27
+  --> $DIR/closure_wf_outlives.rs:34:9
    |
-LL |     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
-   |                           ^^^^^^^^^^^^^^^^^^^^
+LL |         || {}
+   |         ^^^^^
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/closure_wf_outlives.rs:54:22
+  --> $DIR/closure_wf_outlives.rs:60:9
    |
-LL |     type Opaque<T> = impl Sized;
-   |                      ^^^^^^^^^^
-   |                      |
-   |                      the parameter type `T` must be valid for the static lifetime...
-   |                      ...so that the type `T` will meet its required lifetime bounds...
+LL |         || {}
+   |         ^^^^^
+   |         |
+   |         the parameter type `T` must be valid for the static lifetime...
+   |         ...so that the type `T` will meet its required lifetime bounds...
    |
 note: ...that is required by this bound
-  --> $DIR/closure_wf_outlives.rs:59:12
+  --> $DIR/closure_wf_outlives.rs:58:12
    |
 LL |         T: 'static,
    |            ^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
index d2d6380b65a34..af6e6e1e66e8f 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
@@ -4,6 +4,16 @@ error[E0277]: `T` doesn't implement `Debug`
 LL |     t
    |     ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
+note: required by a bound in an opaque type
+  --> $DIR/generic_duplicate_param_use2.rs:8:23
+   |
+LL | type Two<T, U> = impl Debug;
+   |                       ^^^^^
+note: this definition site has more where clauses than the opaque type
+  --> $DIR/generic_duplicate_param_use2.rs:10:1
+   |
+LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider restricting type parameter `T`
    |
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
index e7a25fc724005..2074f12750f67 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
@@ -9,10 +9,9 @@ type Two<T, U> = impl Debug;
 
 fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
     t
-    //~^ ERROR `T` doesn't implement `Debug`
 }
 
 fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
     u
-    //~^ ERROR `U` doesn't implement `Debug`
+    //~^ ERROR concrete type differs
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
index 7bec3822071f3..9a10a4980d806 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
@@ -1,25 +1,14 @@
-error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use3.rs:11:5
-   |
-LL |     t
-   |     ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-help: consider restricting type parameter `T`
-   |
-LL | type Two<T: std::fmt::Debug, U> = impl Debug;
-   |           +++++++++++++++++
-
-error[E0277]: `U` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use3.rs:16:5
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/generic_duplicate_param_use3.rs:15:5
    |
 LL |     u
-   |     ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |     ^ expected `T`, got `U`
    |
-help: consider restricting type parameter `U`
+note: previous use here
+  --> $DIR/generic_duplicate_param_use3.rs:11:5
    |
-LL | type Two<T, U: std::fmt::Debug> = impl Debug;
-   |              +++++++++++++++++
+LL |     t
+   |     ^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
index 2338dbd522b73..a847bed93da79 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
@@ -4,6 +4,16 @@ error[E0277]: `U` doesn't implement `Debug`
 LL |     u
    |     ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
+note: required by a bound in an opaque type
+  --> $DIR/generic_duplicate_param_use4.rs:8:23
+   |
+LL | type Two<T, U> = impl Debug;
+   |                       ^^^^^
+note: this definition site has more where clauses than the opaque type
+  --> $DIR/generic_duplicate_param_use4.rs:10:1
+   |
+LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider restricting type parameter `U`
    |
 LL | type Two<T, U: std::fmt::Debug> = impl Debug;
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs
index 3bd1dda63314a..b3d6beaf84869 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs
@@ -9,12 +9,9 @@ type Two<T, U> = impl Debug;
 
 fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (t, u)
-    //~^ ERROR `T` doesn't implement `Debug`
-    //~| ERROR `U` doesn't implement `Debug`
 }
 
 fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (u, t)
-    //~^ ERROR `T` doesn't implement `Debug`
-    //~| ERROR `U` doesn't implement `Debug`
+    //~^ ERROR concrete type differs
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
index 586ea82342a8f..b0027f8fa57bb 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
@@ -1,51 +1,14 @@
-error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use5.rs:11:5
-   |
-LL |     (t, u)
-   |     ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/generic_duplicate_param_use5.rs:15:5
    |
-   = note: required for `(T, U)` to implement `Debug`
-help: consider restricting type parameter `T`
+LL |     (u, t)
+   |     ^^^^^^ expected `(T, U)`, got `(U, T)`
    |
-LL | type Two<T: std::fmt::Debug, U> = impl Debug;
-   |           +++++++++++++++++
-
-error[E0277]: `U` doesn't implement `Debug`
+note: previous use here
   --> $DIR/generic_duplicate_param_use5.rs:11:5
    |
 LL |     (t, u)
-   |     ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(T, U)` to implement `Debug`
-help: consider restricting type parameter `U`
-   |
-LL | type Two<T, U: std::fmt::Debug> = impl Debug;
-   |              +++++++++++++++++
-
-error[E0277]: `U` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use5.rs:17:5
-   |
-LL |     (u, t)
-   |     ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(U, T)` to implement `Debug`
-help: consider restricting type parameter `U`
-   |
-LL | type Two<T, U: std::fmt::Debug> = impl Debug;
-   |              +++++++++++++++++
-
-error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use5.rs:17:5
-   |
-LL |     (u, t)
-   |     ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(U, T)` to implement `Debug`
-help: consider restricting type parameter `T`
-   |
-LL | type Two<T: std::fmt::Debug, U> = impl Debug;
-   |           +++++++++++++++++
+   |     ^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs
index 5120925e5a4a5..fa8b2a290b933 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs
@@ -9,11 +9,9 @@ type Two<T, U> = impl Debug;
 
 fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (t, t)
-    //~^ ERROR `T` doesn't implement `Debug`
 }
 
 fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (u, t)
-    //~^ ERROR `T` doesn't implement `Debug`
-    //~| ERROR `U` doesn't implement `Debug`
+    //~^ ERROR concrete type differs
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
index cb162d382b6b5..09c01932cef7c 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
@@ -1,39 +1,14 @@
-error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use6.rs:11:5
-   |
-LL |     (t, t)
-   |     ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(T, T)` to implement `Debug`
-help: consider restricting type parameter `T`
-   |
-LL | type Two<T: std::fmt::Debug, U> = impl Debug;
-   |           +++++++++++++++++
-
-error[E0277]: `U` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use6.rs:16:5
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/generic_duplicate_param_use6.rs:15:5
    |
 LL |     (u, t)
-   |     ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(U, T)` to implement `Debug`
-help: consider restricting type parameter `U`
+   |     ^^^^^^ expected `(T, T)`, got `(U, T)`
    |
-LL | type Two<T, U: std::fmt::Debug> = impl Debug;
-   |              +++++++++++++++++
-
-error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use6.rs:16:5
-   |
-LL |     (u, t)
-   |     ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(U, T)` to implement `Debug`
-help: consider restricting type parameter `T`
+note: previous use here
+  --> $DIR/generic_duplicate_param_use6.rs:11:5
    |
-LL | type Two<T: std::fmt::Debug, U> = impl Debug;
-   |           +++++++++++++++++
+LL |     (t, t)
+   |     ^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs
index 3a4b5047b41e2..76c13bb027b0f 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs
@@ -8,10 +8,9 @@ type Two<T, U> = impl Debug;
 
 fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
     (t, 4u32)
-    //~^ ERROR `T` doesn't implement `Debug`
 }
 
 fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
     (u, 4u32)
-    //~^ ERROR `U` doesn't implement `Debug`
+    //~^ concrete type differs
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
index 14cbfb3806f84..09d2abe366366 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
@@ -1,27 +1,14 @@
-error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use8.rs:10:5
-   |
-LL |     (t, 4u32)
-   |     ^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(T, u32)` to implement `Debug`
-help: consider restricting type parameter `T`
-   |
-LL | type Two<T: std::fmt::Debug, U> = impl Debug;
-   |           +++++++++++++++++
-
-error[E0277]: `U` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use8.rs:15:5
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/generic_duplicate_param_use8.rs:14:5
    |
 LL |     (u, 4u32)
-   |     ^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |     ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
    |
-   = note: required for `(U, u32)` to implement `Debug`
-help: consider restricting type parameter `U`
+note: previous use here
+  --> $DIR/generic_duplicate_param_use8.rs:10:5
    |
-LL | type Two<T, U: std::fmt::Debug> = impl Debug;
-   |              +++++++++++++++++
+LL |     (t, 4u32)
+   |     ^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs
index 6afcdfe4d1c3d..5da7aab0da7a6 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs
@@ -13,13 +13,9 @@ trait Foo {
 
 fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
     (t, u, T::BAR)
-    //~^ ERROR the trait bound `A: Foo` is not satisfied
-    //~| ERROR `A` doesn't implement `Debug`
-    //~| ERROR `B` doesn't implement `Debug`
 }
 
 fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (t, u, 42)
-    //~^ ERROR `A` doesn't implement `Debug`
-    //~| ERROR `B` doesn't implement `Debug`
+    //~^ ERROR concrete type differs
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
index 722693e42669c..6e1bb3dfa1744 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
@@ -1,62 +1,14 @@
-error[E0277]: the trait bound `A: Foo` is not satisfied
-  --> $DIR/generic_duplicate_param_use9.rs:15:5
-   |
-LL |     (t, u, T::BAR)
-   |     ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
-   |
-help: consider restricting type parameter `A`
-   |
-LL | type Two<A: Foo, B> = impl Debug;
-   |           +++++
-
-error[E0277]: `A` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use9.rs:15:5
-   |
-LL |     (t, u, T::BAR)
-   |     ^^^^^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/generic_duplicate_param_use9.rs:19:5
    |
-   = note: required for `(A, B, _)` to implement `Debug`
-help: consider restricting type parameter `A`
+LL |     (t, u, 42)
+   |     ^^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
    |
-LL | type Two<A: std::fmt::Debug, B> = impl Debug;
-   |           +++++++++++++++++
-
-error[E0277]: `B` doesn't implement `Debug`
+note: previous use here
   --> $DIR/generic_duplicate_param_use9.rs:15:5
    |
 LL |     (t, u, T::BAR)
-   |     ^^^^^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(A, B, _)` to implement `Debug`
-help: consider restricting type parameter `B`
-   |
-LL | type Two<A, B: std::fmt::Debug> = impl Debug;
-   |              +++++++++++++++++
-
-error[E0277]: `A` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use9.rs:22:5
-   |
-LL |     (t, u, 42)
-   |     ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(A, B, i32)` to implement `Debug`
-help: consider restricting type parameter `A`
-   |
-LL | type Two<A: std::fmt::Debug, B> = impl Debug;
-   |           +++++++++++++++++
-
-error[E0277]: `B` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use9.rs:22:5
-   |
-LL |     (t, u, 42)
-   |     ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(A, B, i32)` to implement `Debug`
-help: consider restricting type parameter `B`
-   |
-LL | type Two<A, B: std::fmt::Debug> = impl Debug;
-   |              +++++++++++++++++
+   |     ^^^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
index b05121a489e40..be68bac55756b 100644
--- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
+++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
@@ -21,6 +21,20 @@ LL |     impl<T: Proj<Assoc = i32> + Copy> Copy for Bar<T> {}
    |                  -----------          ^^^^     ^^^^^^
    |                  |
    |                  unsatisfied trait bound introduced here
+note: required by a bound in an opaque type
+  --> $DIR/hidden_type_mismatch.rs:36:26
+   |
+LL |     pub type Tait = impl Copy + From<Bar<()>> + Into<Bar<()>>;
+   |                          ^^^^
+note: this definition site has more where clauses than the opaque type
+  --> $DIR/hidden_type_mismatch.rs:37:5
+   |
+LL | /     pub fn define_tait() -> Tait
+LL | |     where
+LL | |         // this proves `Bar<()>: Copy`, but `define_tait` is
+LL | |         // now uncallable
+LL | |         (): Proj<Assoc = i32>,
+   | |______________________________^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs
index f8b09814caac3..7b2bbc995307e 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs
@@ -2,9 +2,9 @@
 
 mod test_type_param_static {
     pub type Ty<A> = impl Sized + 'static;
-    //~^ ERROR: the parameter type `A` may not live long enough
     fn defining<A: 'static>(s: A) -> Ty<A> {
         s
+        //~^ ERROR: the parameter type `A` may not live long enough
     }
     pub fn assert_static<A: 'static>() {}
 }
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr
index f2e5e95b96f04..f23b978d0b640 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr
@@ -1,12 +1,17 @@
 error[E0310]: the parameter type `A` may not live long enough
-  --> $DIR/implied_lifetime_wf_check4_static.rs:4:22
+  --> $DIR/implied_lifetime_wf_check4_static.rs:6:9
    |
-LL |     pub type Ty<A> = impl Sized + 'static;
-   |                      ^^^^^^^^^^^^^^^^^^^^
-   |                      |
-   |                      the parameter type `A` must be valid for the static lifetime...
-   |                      ...so that the type `A` will meet its required lifetime bounds
+LL |         s
+   |         ^
+   |         |
+   |         the parameter type `A` must be valid for the static lifetime...
+   |         ...so that the type `A` will meet its required lifetime bounds...
+   |
+note: ...that is required by this bound
+  --> $DIR/implied_lifetime_wf_check4_static.rs:4:35
    |
+LL |     pub type Ty<A> = impl Sized + 'static;
+   |                                   ^^^^^^^
 help: consider adding an explicit lifetime bound
    |
 LL |     pub type Ty<A: 'static> = impl Sized + 'static;
diff --git a/tests/ui/type-alias-impl-trait/issue-52843.stderr b/tests/ui/type-alias-impl-trait/issue-52843.stderr
index ea4c5297ad5e3..a6bdddbc98c67 100644
--- a/tests/ui/type-alias-impl-trait/issue-52843.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-52843.stderr
@@ -4,6 +4,16 @@ error[E0277]: the trait bound `T: Default` is not satisfied
 LL |     t
    |     ^ the trait `Default` is not implemented for `T`
    |
+note: required by a bound in an opaque type
+  --> $DIR/issue-52843.rs:3:20
+   |
+LL | type Foo<T> = impl Default;
+   |                    ^^^^^^^
+note: this definition site has more where clauses than the opaque type
+  --> $DIR/issue-52843.rs:6:1
+   |
+LL | fn foo<T: Default>(t: T) -> Foo<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider restricting type parameter `T`
    |
 LL | type Foo<T: std::default::Default> = impl Default;
diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr
index b4b78f8175fa2..4a6a62bdf96dd 100644
--- a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr
@@ -4,11 +4,23 @@ error[E0277]: the trait bound `B: Bar` is not satisfied
 LL |         MyBaz(bar)
    |         ^^^^^^^^^^ the trait `Bar` is not implemented for `B`
    |
-note: required by a bound in `MyBaz`
-  --> $DIR/issue-90400-2.rs:29:17
+note: required for `MyBaz<B>` to implement `Baz`
+  --> $DIR/issue-90400-2.rs:30:14
    |
-LL | struct MyBaz<B: Bar>(B);
-   |                 ^^^ required by this bound in `MyBaz`
+LL | impl<B: Bar> Baz for MyBaz<B> {
+   |         ---  ^^^     ^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in an opaque type
+  --> $DIR/issue-90400-2.rs:22:26
+   |
+LL |     type FooFn<B> = impl Baz;
+   |                          ^^^
+note: this definition site has more where clauses than the opaque type
+  --> $DIR/issue-90400-2.rs:24:5
+   |
+LL |     fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider restricting type parameter `B`
    |
 LL |     type FooFn<B: Bar> = impl Baz;
diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs
index fa47d13f5164c..b5ef1470629bf 100644
--- a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs
+++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs
@@ -8,7 +8,6 @@ type Two<T, U> = impl Debug;
 
 fn three<T: Debug, U>(t: T) -> Two<T, U> {
     (t, 5i8)
-    //~^ ERROR `T` doesn't implement `Debug`
 }
 
 trait Bar {
@@ -23,8 +22,7 @@ impl Bar for u32 {
 
 fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
     (t, <U as Bar>::FOO)
-    //~^ ERROR `U: Bar` is not satisfied
-    //~| ERROR `T` doesn't implement `Debug`
+    //~^ ERROR concrete type differs
 }
 
 fn is_sync<T: Sync>() {}
diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr
index b11198c584c0d..b59f9c49b0776 100644
--- a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr
+++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr
@@ -1,38 +1,14 @@
-error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/not_a_defining_use.rs:10:5
-   |
-LL |     (t, 5i8)
-   |     ^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(T, i8)` to implement `Debug`
-help: consider restricting type parameter `T`
-   |
-LL | type Two<T: std::fmt::Debug, U> = impl Debug;
-   |           +++++++++++++++++
-
-error[E0277]: the trait bound `U: Bar` is not satisfied
-  --> $DIR/not_a_defining_use.rs:25:5
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/not_a_defining_use.rs:24:5
    |
 LL |     (t, <U as Bar>::FOO)
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `U`
-   |
-help: consider restricting type parameter `U`
+   |     ^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
    |
-LL | type Two<T, U: Bar> = impl Debug;
-   |              +++++
-
-error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/not_a_defining_use.rs:25:5
-   |
-LL |     (t, <U as Bar>::FOO)
-   |     ^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required for `(T, _)` to implement `Debug`
-help: consider restricting type parameter `T`
+note: previous use here
+  --> $DIR/not_a_defining_use.rs:10:5
    |
-LL | type Two<T: std::fmt::Debug, U> = impl Debug;
-   |           +++++++++++++++++
+LL |     (t, 5i8)
+   |     ^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
index e4de9245951cf..48cef847fbbff 100644
--- a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
+++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
@@ -11,6 +11,16 @@ LL | impl<X: Trait> ProofForConversion<X> for () {
    |         -----  ^^^^^^^^^^^^^^^^^^^^^     ^^
    |         |
    |         unsatisfied trait bound introduced here
+note: required by a bound in an opaque type
+  --> $DIR/underconstrained_generic.rs:19:26
+   |
+LL | type Converter<T> = impl ProofForConversion<T>;
+   |                          ^^^^^^^^^^^^^^^^^^^^^
+note: this definition site has more where clauses than the opaque type
+  --> $DIR/underconstrained_generic.rs:21:1
+   |
+LL | fn _defining_use<T: Trait>() -> Converter<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider restricting type parameter `T`
    |
 LL | type Converter<T: Trait> = impl ProofForConversion<T>;
diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs
index c5b2e8a1c5eed..e8e7dd0ea0822 100644
--- a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs
+++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs
@@ -13,11 +13,11 @@ impl<'a, 'b> ProofForConversion<'a, 'b> for &'b &'a () {
 }
 
 type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>;
-//~^ ERROR reference has a longer lifetime than the data it references
 
 // Even _defining_use with an explicit `'a: 'b` compiles fine, too.
 fn _defining_use<'a, 'b>(x: &'b &'a ()) -> Converter<'a, 'b> {
     x
+    //~^ ERROR reference has a longer lifetime than the data it references
 }
 
 fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T {
diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr
index 34b50fb1f05e4..7c07578d887e3 100644
--- a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr
+++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr
@@ -1,8 +1,8 @@
 error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references
-  --> $DIR/underconstrained_lifetime.rs:15:26
+  --> $DIR/underconstrained_lifetime.rs:19:5
    |
-LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>;
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     x
+   |     ^
    |
 note: the pointer is valid for the lifetime `'b` as defined here
   --> $DIR/underconstrained_lifetime.rs:15:20
diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr
index c4ad8434ed147..34648a420ac51 100644
--- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr
+++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr
@@ -1,23 +1,30 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/wf-in-associated-type.rs:38:23
+  --> $DIR/wf-in-associated-type.rs:40:13
    |
 LL |     impl<'a, T> Trait<'a, T> for () {
    |          -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
-LL |         type Opaque = impl Sized + 'a;
-   |                       ^^^^^^^^^^^^^^^ ...so that the type `&'a T` will meet its required lifetime bounds
+...
+LL |             req
+   |             ^^^ ...so that the type `&'a T` will meet its required lifetime bounds...
+   |
+note: ...that is required by this bound
+  --> $DIR/wf-in-associated-type.rs:38:36
    |
+LL |         type Opaque = impl Sized + 'a;
+   |                                    ^^
 help: consider adding an explicit lifetime bound
    |
 LL |     impl<'a, T: 'a> Trait<'a, T> for () {
    |               ++++
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/wf-in-associated-type.rs:38:23
+  --> $DIR/wf-in-associated-type.rs:40:13
    |
 LL |     impl<'a, T> Trait<'a, T> for () {
    |          -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
-LL |         type Opaque = impl Sized + 'a;
-   |                       ^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
+...
+LL |             req
+   |             ^^^ ...so that the reference type `&'a T` does not outlive the data it points at
    |
 help: consider adding an explicit lifetime bound
    |
diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs b/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs
index c20be3125bc7a..e548609e89a46 100644
--- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs
+++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs
@@ -36,10 +36,10 @@ mod fail {
 
     impl<'a, T> Trait<'a, T> for () {
         type Opaque = impl Sized + 'a;
-        //[fail]~^ ERROR the parameter type `T` may not live long enough
-        //[fail]~| ERROR the parameter type `T` may not live long enough
         fn constrain_opaque(req: &'a T) -> Self::Opaque {
             req
+            //[fail]~^ ERROR the parameter type `T` may not live long enough
+            //[fail]~| ERROR the parameter type `T` may not live long enough
         }
     }
 }