about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJubilee <workingjubilee@gmail.com>2024-11-08 20:46:12 -0800
committerGitHub <noreply@github.com>2024-11-08 20:46:12 -0800
commit7a4970476e8a9cb387ca48a14a657051769b094f (patch)
treed17e627b0f5a78ae04210b464cfee240e3ec50fd
parent1077c08ad5fbf4c8aad28e8681fa80d9297005bc (diff)
parent97dfe8b87115c44d480b6282aae7754e7c4ab4fe (diff)
downloadrust-7a4970476e8a9cb387ca48a14a657051769b094f.tar.gz
rust-7a4970476e8a9cb387ca48a14a657051769b094f.zip
Rollup merge of #132757 - compiler-errors:yeet-check-wf, r=lcnr
Get rid of `check_opaque_type_well_formed`

Instead, replicate it by improving the span of the opaque in `check_opaque_meets_bounds`.

This has two consequences:
1. We now prefer "concrete type differs" errors, since we'll hit those first before we check the opaque is WF.
2. Spans have gotten slightly worse.

Specifically, (2.) could be improved by adding a new obligation cause that explains that the definition's environment has stronger assumptions than the declaration.

r? lcnr
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs90
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs155
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs1
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs16
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.rs2
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.stderr21
-rw-r--r--tests/ui/pattern/usefulness/impl-trait.stderr56
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/closure_wf_outlives.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr38
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr27
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr51
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr41
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr29
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr62
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr17
-rw-r--r--tests/ui/type-alias-impl-trait/issue-52843.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/issue-90400-2.stderr20
-rw-r--r--tests/ui/type-alias-impl-trait/not_a_defining_use.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/not_a_defining_use.stderr40
-rw-r--r--tests/ui/type-alias-impl-trait/underconstrained_generic.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr19
-rw-r--r--tests/ui/type-alias-impl-trait/wf-in-associated-type.rs4
35 files changed, 388 insertions, 411 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index f9dd649ab9f..d676ce59cfe 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 50ea8018e76..3080d8b3510 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 e0e03a29220..b1d5d688295 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 40e5ec45959..09731d565b6 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 86fd4c230f6..a5e364d49f7 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 a74bd9890ca..2851637ae78 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 c6b7e21b9dd..31d15c45921 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 75cba4b5f02..34f8eb1e163 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 0c937f92253..8f887a6ac68 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 430b444aae1..caa9b6d979a 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 3484485e3fd..04288112fa8 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 d2d6380b65a..af6e6e1e66e 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 e7a25fc7240..2074f12750f 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 7bec3822071..9a10a4980d8 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 2338dbd522b..a847bed93da 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 3bd1dda6331..b3d6beaf848 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 586ea82342a..b0027f8fa57 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 5120925e5a4..fa8b2a290b9 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 cb162d382b6..09c01932cef 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 3a4b5047b41..76c13bb027b 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 14cbfb3806f..09d2abe3663 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 6afcdfe4d1c..5da7aab0da7 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 722693e4266..6e1bb3dfa17 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 b05121a489e..be68bac5575 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 f8b09814caa..7b2bbc99530 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 f2e5e95b96f..f23b978d0b6 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 ea4c5297ad5..a6bdddbc98c 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 b4b78f8175f..4a6a62bdf96 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 fa47d13f516..b5ef1470629 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 b11198c584c..b59f9c49b07 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 e4de9245951..48cef847fbb 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 c5b2e8a1c5e..e8e7dd0ea08 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 34b50fb1f05..7c07578d887 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 c4ad8434ed1..34648a420ac 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 c20be3125bc..e548609e89a 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
         }
     }
 }