diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl
index ada20e5c614f8..33b80c4b03d6f 100644
--- a/compiler/rustc_borrowck/messages.ftl
+++ b/compiler/rustc_borrowck/messages.ftl
@@ -162,13 +162,6 @@ borrowck_opaque_type_lifetime_mismatch =
     .prev_lifetime_label = lifetime `{$prev}` previously used here
     .note = if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
 
-borrowck_opaque_type_non_generic_param =
-    expected generic {$kind} parameter, found `{$ty}`
-    .label = {STREQ($ty, "'static") ->
-        [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
-        *[other] this generic parameter must be used with a generic {$kind} parameter
-    }
-
 borrowck_partial_var_move_by_use_in_closure =
     variable {$is_partial ->
         [true] partially moved
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 7f0ee28531cfa..240bd20053b15 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -35,7 +35,7 @@ use rustc_infer::infer::{
 };
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode, fold_regions};
+use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
 use rustc_middle::{bug, span_bug};
 use rustc_mir_dataflow::impls::{
     EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
@@ -171,12 +171,6 @@ fn do_mir_borrowck<'tcx>(
     let free_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted);
     let body = &body_owned; // no further changes
 
-    // FIXME(-Znext-solver): A bit dubious that we're only registering
-    // predefined opaques in the typeck root.
-    if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
-        infcx.register_predefined_opaques_for_next_solver(def);
-    }
-
     let location_table = PoloniusLocationTable::new(body);
 
     let move_data = MoveData::gather_moves(body, tcx, |_| true);
@@ -431,7 +425,12 @@ pub(crate) struct BorrowckInferCtxt<'tcx> {
 
 impl<'tcx> BorrowckInferCtxt<'tcx> {
     pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
-        let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, def_id));
+        let typing_mode = if tcx.use_typing_mode_borrowck() {
+            TypingMode::borrowck(tcx, def_id)
+        } else {
+            TypingMode::analysis_in_body(tcx, def_id)
+        };
+        let infcx = tcx.infer_ctxt().build(typing_mode);
         let param_env = tcx.param_env(def_id);
         BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()), param_env }
     }
@@ -478,29 +477,6 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
 
         next_region
     }
-
-    /// With the new solver we prepopulate the opaque type storage during
-    /// MIR borrowck with the hidden types from HIR typeck. This is necessary
-    /// to avoid ambiguities as earlier goals can rely on the hidden type
-    /// of an opaque which is only constrained by a later goal.
-    fn register_predefined_opaques_for_next_solver(&self, def_id: LocalDefId) {
-        let tcx = self.tcx;
-        // OK to use the identity arguments for each opaque type key, since
-        // we remap opaques from HIR typeck back to their definition params.
-        for data in tcx.typeck(def_id).concrete_opaque_types.iter().map(|(k, v)| (*k, *v)) {
-            // HIR typeck did not infer the regions of the opaque, so we instantiate
-            // them with fresh inference variables.
-            let (key, hidden_ty) = fold_regions(tcx, data, |_, _| {
-                self.next_nll_region_var_in_universe(
-                    NllRegionVariableOrigin::Existential { from_forall: false },
-                    ty::UniverseIndex::ROOT,
-                )
-            });
-
-            let prev = self.register_hidden_type_in_storage(key, hidden_ty);
-            assert_eq!(prev, None);
-        }
-    }
 }
 
 impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index ca8b9fb4e9d82..a098450352ff9 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -1,22 +1,17 @@
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_errors::ErrorGuaranteed;
-use rustc_hir::OpaqueTyOrigin;
-use rustc_hir::def_id::LocalDefId;
-use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _};
+use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
 use rustc_macros::extension;
 use rustc_middle::ty::{
-    self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
-    TypeVisitableExt, TypingMode, fold_regions,
+    self, DefiningScopeKind, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
+    TypeVisitableExt, fold_regions,
 };
 use rustc_span::Span;
-use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt;
-use rustc_trait_selection::traits::ObligationCtxt;
+use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
 use tracing::{debug, instrument};
 
 use super::RegionInferenceContext;
 use crate::opaque_types::ConcreteOpaqueTypes;
-use crate::session_diagnostics::{LifetimeMismatchOpaqueParam, NonGenericOpaqueTypeParam};
+use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
 use crate::universal_regions::RegionClassification;
 
 impl<'tcx> RegionInferenceContext<'tcx> {
@@ -272,14 +267,21 @@ impl<'tcx> InferCtxt<'tcx> {
             return Ty::new_error(self.tcx, e);
         }
 
-        if let Err(guar) =
-            check_opaque_type_parameter_valid(self, opaque_type_key, instantiated_ty.span)
-        {
+        if let Err(guar) = check_opaque_type_parameter_valid(
+            self,
+            opaque_type_key,
+            instantiated_ty.span,
+            DefiningScopeKind::MirBorrowck,
+        ) {
             return Ty::new_error(self.tcx, guar);
         }
 
         let definition_ty = instantiated_ty
-            .remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
+            .remap_generic_params_to_declaration_params(
+                opaque_type_key,
+                self.tcx,
+                DefiningScopeKind::MirBorrowck,
+            )
             .ty;
 
         if let Err(e) = definition_ty.error_reported() {
@@ -289,156 +291,3 @@ impl<'tcx> InferCtxt<'tcx> {
         definition_ty
     }
 }
-
-/// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter].
-///
-/// [rustc-dev-guide chapter]:
-/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
-fn check_opaque_type_parameter_valid<'tcx>(
-    infcx: &InferCtxt<'tcx>,
-    opaque_type_key: OpaqueTypeKey<'tcx>,
-    span: Span,
-) -> Result<(), ErrorGuaranteed> {
-    let tcx = infcx.tcx;
-    let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
-    let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
-    let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
-
-    for (i, arg) in opaque_type_key.iter_captured_args(tcx) {
-        let arg_is_param = match arg.unpack() {
-            GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
-            GenericArgKind::Lifetime(lt) => {
-                matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
-                    || (lt.is_static() && opaque_env.param_equal_static(i))
-            }
-            GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
-        };
-
-        if arg_is_param {
-            // Register if the same lifetime appears multiple times in the generic args.
-            // There is an exception when the opaque type *requires* the lifetimes to be equal.
-            // See [rustc-dev-guide chapter] ยง "An exception to uniqueness rule".
-            let seen_where = seen_params.entry(arg).or_default();
-            if !seen_where.first().is_some_and(|&prev_i| opaque_env.params_equal(i, prev_i)) {
-                seen_where.push(i);
-            }
-        } else {
-            // Prevent `fn foo() -> Foo<u32>` from being defining.
-            let opaque_param = opaque_generics.param_at(i, tcx);
-            let kind = opaque_param.kind.descr();
-
-            opaque_env.param_is_error(i)?;
-
-            return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam {
-                ty: arg,
-                kind,
-                span,
-                param_span: tcx.def_span(opaque_param.def_id),
-            }));
-        }
-    }
-
-    for (_, indices) in seen_params {
-        if indices.len() > 1 {
-            let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
-            let spans: Vec<_> = indices
-                .into_iter()
-                .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
-                .collect();
-            #[allow(rustc::diagnostic_outside_of_impl)]
-            #[allow(rustc::untranslatable_diagnostic)]
-            return Err(infcx
-                .dcx()
-                .struct_span_err(span, "non-defining opaque type use in defining scope")
-                .with_span_note(spans, format!("{descr} used multiple times"))
-                .emit());
-        }
-    }
-
-    Ok(())
-}
-
-/// Computes if an opaque type requires a lifetime parameter to be equal to
-/// another one or to the `'static` lifetime.
-/// These requirements are derived from the explicit and implied bounds.
-struct LazyOpaqueTyEnv<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    def_id: LocalDefId,
-
-    /// Equal parameters will have the same name. Computed Lazily.
-    /// Example:
-    ///     `type Opaque<'a: 'static, 'b: 'c, 'c: 'b> = impl Sized;`
-    ///     Identity args: `['a, 'b, 'c]`
-    ///     Canonical args: `['static, 'b, 'b]`
-    canonical_args: std::cell::OnceCell<ty::GenericArgsRef<'tcx>>,
-}
-
-impl<'tcx> LazyOpaqueTyEnv<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
-        Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() }
-    }
-
-    fn param_equal_static(&self, param_index: usize) -> bool {
-        self.get_canonical_args()[param_index].expect_region().is_static()
-    }
-
-    fn params_equal(&self, param1: usize, param2: usize) -> bool {
-        let canonical_args = self.get_canonical_args();
-        canonical_args[param1] == canonical_args[param2]
-    }
-
-    fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> {
-        self.get_canonical_args()[param_index].error_reported()
-    }
-
-    fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> {
-        if let Some(&canonical_args) = self.canonical_args.get() {
-            return canonical_args;
-        }
-
-        let &Self { tcx, def_id, .. } = self;
-        let origin = tcx.local_opaque_ty_origin(def_id);
-        let parent = match origin {
-            OpaqueTyOrigin::FnReturn { parent, .. }
-            | OpaqueTyOrigin::AsyncFn { parent, .. }
-            | OpaqueTyOrigin::TyAlias { parent, .. } => parent,
-        };
-        let param_env = tcx.param_env(parent);
-        let args = GenericArgs::identity_for_item(tcx, parent).extend_to(
-            tcx,
-            def_id.to_def_id(),
-            |param, _| {
-                tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
-            },
-        );
-
-        // FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're
-        // in a body here.
-        let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
-        let ocx = ObligationCtxt::new(&infcx);
-
-        let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| {
-            tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds");
-            Default::default()
-        });
-        let outlives_env = OutlivesEnvironment::new(&infcx, parent, param_env, wf_tys);
-
-        let mut seen = vec![tcx.lifetimes.re_static];
-        let canonical_args = fold_regions(tcx, args, |r1, _| {
-            if r1.is_error() {
-                r1
-            } else if let Some(&r2) = seen.iter().find(|&&r2| {
-                let free_regions = outlives_env.free_region_map();
-                free_regions.sub_free_regions(tcx, r1, r2)
-                    && free_regions.sub_free_regions(tcx, r2, r1)
-            }) {
-                r2
-            } else {
-                seen.push(r1);
-                r1
-            }
-        });
-        self.canonical_args.set(canonical_args).unwrap();
-        canonical_args
-    }
-}
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index 4be5d0dbf4284..5143b2fa20598 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -294,17 +294,6 @@ pub(crate) struct MoveBorrow<'a> {
     pub borrow_span: Span,
 }
 
-#[derive(Diagnostic)]
-#[diag(borrowck_opaque_type_non_generic_param, code = E0792)]
-pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
-    pub ty: GenericArg<'tcx>,
-    pub kind: &'a str,
-    #[primary_span]
-    pub span: Span,
-    #[label]
-    pub param_span: Span,
-}
-
 #[derive(Diagnostic)]
 #[diag(borrowck_opaque_type_lifetime_mismatch)]
 pub(crate) struct LifetimeMismatchOpaqueParam<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 075abc3259449..625f51dd29eac 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -61,6 +61,7 @@ pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
         type_of: type_of::type_of,
         type_of_opaque: type_of::type_of_opaque,
+        type_of_opaque_hir_typeck: type_of::type_of_opaque_hir_typeck,
         type_alias_is_lazy: type_of::type_alias_is_lazy,
         item_bounds: item_bounds::item_bounds,
         explicit_item_bounds: item_bounds::explicit_item_bounds,
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index afda2c142e228..694c12288596f 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -7,7 +7,9 @@ use rustc_hir::{self as hir, AmbigArg, HirId};
 use rustc_middle::query::plumbing::CyclePlaceholder;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, fold_regions};
+use rustc_middle::ty::{
+    self, DefiningScopeKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, fold_regions,
+};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{DUMMY_SP, Ident, Span};
 
@@ -324,10 +326,18 @@ pub(super) fn type_of_opaque(
     if let Some(def_id) = def_id.as_local() {
         Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
             hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
-                opaque::find_opaque_ty_constraints_for_tait(tcx, def_id)
+                opaque::find_opaque_ty_constraints_for_tait(
+                    tcx,
+                    def_id,
+                    DefiningScopeKind::MirBorrowck,
+                )
             }
             hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. } => {
-                opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(tcx, def_id)
+                opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
+                    tcx,
+                    def_id,
+                    DefiningScopeKind::MirBorrowck,
+                )
             }
             // Opaque types desugared from `impl Trait`.
             hir::OpaqueTyOrigin::FnReturn { parent: owner, in_trait_or_impl }
@@ -340,7 +350,12 @@ pub(super) fn type_of_opaque(
                         "tried to get type of this RPITIT with no definition"
                     );
                 }
-                opaque::find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
+                opaque::find_opaque_ty_constraints_for_rpit(
+                    tcx,
+                    def_id,
+                    owner,
+                    DefiningScopeKind::MirBorrowck,
+                )
             }
         }))
     } else {
@@ -350,6 +365,42 @@ pub(super) fn type_of_opaque(
     }
 }
 
+pub(super) fn type_of_opaque_hir_typeck(
+    tcx: TyCtxt<'_>,
+    def_id: LocalDefId,
+) -> ty::EarlyBinder<'_, Ty<'_>> {
+    ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
+        hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
+            opaque::find_opaque_ty_constraints_for_tait(tcx, def_id, DefiningScopeKind::HirTypeck)
+        }
+        hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. } => {
+            opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
+                tcx,
+                def_id,
+                DefiningScopeKind::HirTypeck,
+            )
+        }
+        // Opaque types desugared from `impl Trait`.
+        hir::OpaqueTyOrigin::FnReturn { parent: owner, in_trait_or_impl }
+        | hir::OpaqueTyOrigin::AsyncFn { parent: owner, in_trait_or_impl } => {
+            if in_trait_or_impl == Some(hir::RpitContext::Trait)
+                && !tcx.defaultness(owner).has_value()
+            {
+                span_bug!(
+                    tcx.def_span(def_id),
+                    "tried to get type of this RPITIT with no definition"
+                );
+            }
+            opaque::find_opaque_ty_constraints_for_rpit(
+                tcx,
+                def_id,
+                owner,
+                DefiningScopeKind::HirTypeck,
+            )
+        }
+    })
+}
+
 fn infer_placeholder_type<'tcx>(
     cx: &dyn HirTyLowerer<'tcx>,
     def_id: LocalDefId,
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index 3dec1e286b4ef..3fe3d71b32da8 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -3,8 +3,7 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def, intravisit};
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_span::DUMMY_SP;
+use rustc_middle::ty::{self, DefiningScopeKind, Ty, TyCtxt, TypeVisitableExt};
 use tracing::{debug, instrument, trace};
 
 use crate::errors::{TaitForwardCompat2, UnconstrainedOpaqueType};
@@ -15,6 +14,7 @@ use crate::errors::{TaitForwardCompat2, UnconstrainedOpaqueType};
 pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
+    opaque_types_from: DefiningScopeKind,
 ) -> Ty<'_> {
     let mut parent_def_id = def_id;
     while tcx.def_kind(parent_def_id) == def::DefKind::OpaqueTy {
@@ -27,7 +27,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
         other => bug!("invalid impl trait in assoc type parent: {other:?}"),
     }
 
-    let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
+    let mut locator = TaitConstraintLocator { def_id, tcx, found: None, opaque_types_from };
 
     for &assoc_id in tcx.associated_item_def_ids(impl_def_id) {
         let assoc = tcx.associated_item(assoc_id);
@@ -39,25 +39,14 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
     }
 
     if let Some(hidden) = locator.found {
-        // Only check against typeck if we didn't already error
-        if !hidden.ty.references_error() {
-            for concrete_type in locator.typeck_types {
-                if concrete_type.ty != tcx.erase_regions(hidden.ty) {
-                    if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) {
-                        d.emit();
-                    }
-                }
-            }
-        }
-
         hidden.ty
     } else {
-        let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType {
+        let guar = tcx.dcx().emit_err(UnconstrainedOpaqueType {
             span: tcx.def_span(def_id),
             name: tcx.item_ident(parent_def_id.to_def_id()),
             what: "impl",
         });
-        Ty::new_error(tcx, reported)
+        Ty::new_error(tcx, guar)
     }
 }
 
@@ -80,23 +69,16 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
 /// fn b<T>() -> Foo<T, u32> { .. }
 /// ```
 #[instrument(skip(tcx), level = "debug")]
-pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
-    let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
+pub(super) fn find_opaque_ty_constraints_for_tait(
+    tcx: TyCtxt<'_>,
+    def_id: LocalDefId,
+    opaque_types_from: DefiningScopeKind,
+) -> Ty<'_> {
+    let mut locator = TaitConstraintLocator { def_id, tcx, found: None, opaque_types_from };
 
     tcx.hir_walk_toplevel_module(&mut locator);
 
     if let Some(hidden) = locator.found {
-        // Only check against typeck if we didn't already error
-        if !hidden.ty.references_error() {
-            for concrete_type in locator.typeck_types {
-                if concrete_type.ty != tcx.erase_regions(hidden.ty) {
-                    if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) {
-                        d.emit();
-                    }
-                }
-            }
-        }
-
         hidden.ty
     } else {
         let mut parent_def_id = def_id;
@@ -104,12 +86,12 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
             // Account for `type Alias = impl Trait<Foo = impl Trait>;` (#116031)
             parent_def_id = tcx.local_parent(parent_def_id);
         }
-        let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType {
+        let guar = tcx.dcx().emit_err(UnconstrainedOpaqueType {
             span: tcx.def_span(def_id),
             name: tcx.item_ident(parent_def_id.to_def_id()),
             what: "crate",
         });
-        Ty::new_error(tcx, reported)
+        Ty::new_error(tcx, guar)
     }
 }
 
@@ -126,22 +108,44 @@ struct TaitConstraintLocator<'tcx> {
     /// type).
     found: Option<ty::OpaqueHiddenType<'tcx>>,
 
-    /// In the presence of dead code, typeck may figure out a hidden type
-    /// while borrowck will not. We collect these cases here and check at
-    /// the end that we actually found a type that matches (modulo regions).
-    typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
+    opaque_types_from: DefiningScopeKind,
 }
 
-impl TaitConstraintLocator<'_> {
+impl<'tcx> TaitConstraintLocator<'tcx> {
+    fn insert_found(&mut self, hidden_ty: ty::OpaqueHiddenType<'tcx>) {
+        if let Some(prev) = &mut self.found {
+            if hidden_ty.ty != prev.ty {
+                let (Ok(guar) | Err(guar)) =
+                    prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit());
+                prev.ty = Ty::new_error(self.tcx, guar);
+            }
+        } else {
+            self.found = Some(hidden_ty);
+        }
+    }
+
+    fn non_defining_use_in_defining_scope(&mut self, item_def_id: LocalDefId) {
+        let guar = self.tcx.dcx().emit_err(TaitForwardCompat2 {
+            span: self
+                .tcx
+                .def_ident_span(item_def_id)
+                .unwrap_or_else(|| self.tcx.def_span(item_def_id)),
+            opaque_type_span: self.tcx.def_span(self.def_id),
+            opaque_type: self.tcx.def_path_str(self.def_id),
+        });
+        self.insert_found(ty::OpaqueHiddenType::new_error(self.tcx, guar));
+    }
+
     #[instrument(skip(self), level = "debug")]
     fn check(&mut self, item_def_id: LocalDefId) {
         // Don't try to check items that cannot possibly constrain the type.
-        if !self.tcx.has_typeck_results(item_def_id) {
+        let tcx = self.tcx;
+        if !tcx.has_typeck_results(item_def_id) {
             debug!("no constraint: no typeck results");
             return;
         }
 
-        let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
+        let opaque_types_defined_by = tcx.opaque_types_defined_by(item_def_id);
         // Don't try to check items that cannot possibly constrain the type.
         if !opaque_types_defined_by.contains(&self.def_id) {
             debug!("no constraint: no opaque types defined");
@@ -152,7 +156,7 @@ impl TaitConstraintLocator<'_> {
         // "non-defining use" errors for them.
         // Note that we use `Node::fn_sig` instead of `Node::fn_decl` here, because the former
         // excludes closures, which are allowed to have `_` in their return type.
-        let hir_node = self.tcx.hir_node_by_def_id(item_def_id);
+        let hir_node = tcx.hir_node_by_def_id(item_def_id);
         debug_assert!(
             !matches!(hir_node, Node::ForeignItem(..)),
             "foreign items cannot constrain opaque types",
@@ -164,88 +168,39 @@ impl TaitConstraintLocator<'_> {
                 hir_sig.decl.output.span(),
                 "inferring return types and opaque types do not mix well",
             );
-            self.found =
-                Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) });
+            self.found = Some(ty::OpaqueHiddenType::new_error(tcx, guar));
             return;
         }
 
-        // Calling `mir_borrowck` can lead to cycle errors through
-        // const-checking, avoid calling it if we don't have to.
-        // ```rust
-        // type Foo = impl Fn() -> usize; // when computing type for this
-        // const fn bar() -> Foo {
-        //     || 0usize
-        // }
-        // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles
-        // // because we again need to reveal `Foo` so we can check whether the
-        // // constant does not contain interior mutability.
-        // ```
-        let tables = self.tcx.typeck(item_def_id);
-        if let Some(guar) = tables.tainted_by_errors {
-            self.found =
-                Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) });
-            return;
-        }
-
-        let mut constrained = false;
-        for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
-            if opaque_type_key.def_id != self.def_id {
-                continue;
-            }
-            constrained = true;
-
-            let concrete_type =
-                self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
-                    opaque_type_key,
-                    self.tcx,
-                    true,
-                ));
-            if self.typeck_types.iter().all(|prev| prev.ty != concrete_type.ty) {
-                self.typeck_types.push(concrete_type);
-            }
-        }
-
-        if !constrained {
-            debug!("no constraints in typeck results");
-            if opaque_types_defined_by.contains(&self.def_id) {
-                let guar = self.tcx.dcx().emit_err(TaitForwardCompat2 {
-                    span: self
-                        .tcx
-                        .def_ident_span(item_def_id)
-                        .unwrap_or_else(|| self.tcx.def_span(item_def_id)),
-                    opaque_type_span: self.tcx.def_span(self.def_id),
-                    opaque_type: self.tcx.def_path_str(self.def_id),
-                });
-                // Avoid "opaque type not constrained" errors on the opaque itself.
-                self.found = Some(ty::OpaqueHiddenType {
-                    span: DUMMY_SP,
-                    ty: Ty::new_error(self.tcx, guar),
-                });
+        match self.opaque_types_from {
+            DefiningScopeKind::HirTypeck => {
+                let tables = tcx.typeck(item_def_id);
+                if let Some(guar) = tables.tainted_by_errors {
+                    self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar));
+                } else if let Some(&hidden_type) = tables.concrete_opaque_types.get(&self.def_id) {
+                    self.insert_found(hidden_type);
+                } else {
+                    self.non_defining_use_in_defining_scope(item_def_id);
+                }
             }
-            return;
-        };
-
-        // Use borrowck to get the type with unerased regions.
-        let borrowck_results = &self.tcx.mir_borrowck(item_def_id);
-
-        // If the body was tainted, then assume the opaque may have been constrained and just set it to error.
-        if let Some(guar) = borrowck_results.tainted_by_errors {
-            self.found =
-                Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) });
-            return;
-        }
-
-        debug!(?borrowck_results.concrete_opaque_types);
-        if let Some(&concrete_type) = borrowck_results.concrete_opaque_types.get(&self.def_id) {
-            debug!(?concrete_type, "found constraint");
-            if let Some(prev) = &mut self.found {
-                if concrete_type.ty != prev.ty {
-                    let (Ok(guar) | Err(guar)) =
-                        prev.build_mismatch_error(&concrete_type, self.tcx).map(|d| d.emit());
-                    prev.ty = Ty::new_error(self.tcx, guar);
+            DefiningScopeKind::MirBorrowck => {
+                let borrowck_result = tcx.mir_borrowck(item_def_id);
+                if let Some(guar) = borrowck_result.tainted_by_errors {
+                    self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar));
+                } else if let Some(&hidden_type) =
+                    borrowck_result.concrete_opaque_types.get(&self.def_id)
+                {
+                    debug!(?hidden_type, "found constraint");
+                    self.insert_found(hidden_type);
+                } else if let Err(guar) = tcx
+                    .type_of_opaque_hir_typeck(self.def_id)
+                    .instantiate_identity()
+                    .error_reported()
+                {
+                    self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar));
+                } else {
+                    self.non_defining_use_in_defining_scope(item_def_id);
                 }
-            } else {
-                self.found = Some(concrete_type);
             }
         }
     }
@@ -287,126 +242,42 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
     owner_def_id: LocalDefId,
+    opaque_types_from: DefiningScopeKind,
 ) -> Ty<'tcx> {
-    let tables = tcx.typeck(owner_def_id);
-
-    // Check that all of the opaques we inferred during HIR are compatible.
-    // FIXME: We explicitly don't check that the types inferred during HIR
-    // typeck are compatible with the one that we infer during borrowck,
-    // because that one actually sometimes has consts evaluated eagerly so
-    // using strict type equality will fail.
-    let mut hir_opaque_ty: Option<ty::OpaqueHiddenType<'tcx>> = None;
-    if tables.tainted_by_errors.is_none() {
-        for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
-            if opaque_type_key.def_id != def_id {
-                continue;
-            }
-            let concrete_type = tcx.erase_regions(
-                hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
-            );
-            if let Some(prev) = &mut hir_opaque_ty {
-                if concrete_type.ty != prev.ty {
-                    if let Ok(d) = prev.build_mismatch_error(&concrete_type, tcx) {
-                        d.emit();
-                    }
-                }
+    match opaque_types_from {
+        DefiningScopeKind::HirTypeck => {
+            let tables = tcx.typeck(owner_def_id);
+            if let Some(guar) = tables.tainted_by_errors {
+                Ty::new_error(tcx, guar)
+            } else if let Some(hidden_ty) = tables.concrete_opaque_types.get(&def_id) {
+                hidden_ty.ty
             } else {
-                hir_opaque_ty = Some(concrete_type);
+                // FIXME(-Znext-solver): This should not be necessary and we should
+                // instead rely on inference variable fallback inside of typeck itself.
+
+                // We failed to resolve the opaque type or it
+                // resolves to itself. We interpret this as the
+                // no values of the hidden type ever being constructed,
+                // so we can just make the hidden type be `!`.
+                // For backwards compatibility reasons, we fall back to
+                // `()` until we the diverging default is changed.
+                Ty::new_diverging_default(tcx)
             }
         }
-    }
-
-    let mir_opaque_ty = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
-    if let Some(mir_opaque_ty) = mir_opaque_ty {
-        if mir_opaque_ty.references_error() {
-            return mir_opaque_ty.ty;
-        }
-
-        debug!(?owner_def_id);
-        let mut locator = RpitConstraintChecker { def_id, tcx, found: mir_opaque_ty };
-
-        match tcx.hir_node_by_def_id(owner_def_id) {
-            Node::Item(it) => intravisit::walk_item(&mut locator, it),
-            Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it),
-            Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
-            other => bug!("{:?} is not a valid scope for an opaque type item", other),
-        }
-
-        mir_opaque_ty.ty
-    } else if let Some(guar) = tables.tainted_by_errors {
-        // Some error in the owner fn prevented us from populating
-        // the `concrete_opaque_types` table.
-        Ty::new_error(tcx, guar)
-    } else {
-        // Fall back to the RPIT we inferred during HIR typeck
-        if let Some(hir_opaque_ty) = hir_opaque_ty {
-            hir_opaque_ty.ty
-        } else {
-            // We failed to resolve the opaque type or it
-            // resolves to itself. We interpret this as the
-            // no values of the hidden type ever being constructed,
-            // so we can just make the hidden type be `!`.
-            // For backwards compatibility reasons, we fall back to
-            // `()` until we the diverging default is changed.
-            Ty::new_diverging_default(tcx)
-        }
-    }
-}
-
-struct RpitConstraintChecker<'tcx> {
-    tcx: TyCtxt<'tcx>,
-
-    /// def_id of the opaque type whose defining uses are being checked
-    def_id: LocalDefId,
-
-    found: ty::OpaqueHiddenType<'tcx>,
-}
-
-impl RpitConstraintChecker<'_> {
-    #[instrument(skip(self), level = "debug")]
-    fn check(&self, def_id: LocalDefId) {
-        // Use borrowck to get the type with unerased regions.
-        let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
-        debug!(?concrete_opaque_types);
-        if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
-            debug!(?concrete_type, "found constraint");
-            if concrete_type.ty != self.found.ty {
-                if let Ok(d) = self.found.build_mismatch_error(&concrete_type, self.tcx) {
-                    d.emit();
+        DefiningScopeKind::MirBorrowck => {
+            let borrowck_result = tcx.mir_borrowck(owner_def_id);
+            if let Some(guar) = borrowck_result.tainted_by_errors {
+                Ty::new_error(tcx, guar)
+            } else if let Some(hidden_ty) = borrowck_result.concrete_opaque_types.get(&def_id) {
+                hidden_ty.ty
+            } else {
+                let hir_ty = tcx.type_of_opaque_hir_typeck(def_id).instantiate_identity();
+                if let Err(guar) = hir_ty.error_reported() {
+                    Ty::new_error(tcx, guar)
+                } else {
+                    hir_ty
                 }
             }
         }
     }
 }
-
-impl<'tcx> intravisit::Visitor<'tcx> for RpitConstraintChecker<'tcx> {
-    type NestedFilter = nested_filter::OnlyBodies;
-
-    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
-        self.tcx
-    }
-    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
-        intravisit::walk_expr(self, ex);
-    }
-    fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
-        trace!(?it.owner_id);
-        // The opaque type itself or its children are not within its reveal scope.
-        if it.owner_id.def_id != self.def_id {
-            self.check(it.owner_id.def_id);
-            intravisit::walk_item(self, it);
-        }
-    }
-    fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
-        trace!(?it.owner_id);
-        // The opaque type itself or its children are not within its reveal scope.
-        if it.owner_id.def_id != self.def_id {
-            self.check(it.owner_id.def_id);
-            intravisit::walk_impl_item(self, it);
-        }
-    }
-    fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
-        trace!(?it.owner_id);
-        self.check(it.owner_id.def_id);
-        intravisit::walk_trait_item(self, it);
-    }
-}
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 588383534f6ba..4d7e2c7629f00 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -12,10 +12,12 @@ use rustc_middle::span_bug;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
 use rustc_middle::ty::{
-    self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, fold_regions,
+    self, DefiningScopeKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
+    TypeVisitableExt, fold_regions,
 };
 use rustc_span::{Span, sym};
 use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
+use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
 use rustc_trait_selection::solve;
 use tracing::{debug, instrument};
 
@@ -553,6 +555,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
     #[instrument(skip(self), level = "debug")]
     fn visit_opaque_types(&mut self) {
+        let tcx = self.tcx();
         // We clone the opaques instead of stealing them here as they are still used for
         // normalization in the next generation trait solver.
         //
@@ -575,16 +578,46 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                 }
             }
 
-            // Here we only detect impl trait definition conflicts when they
-            // are equal modulo regions.
-            if let Some(last_opaque_ty) =
-                self.typeck_results.concrete_opaque_types.insert(opaque_type_key, hidden_type)
-                && last_opaque_ty.ty != hidden_type.ty
+            if let Err(guar) = check_opaque_type_parameter_valid(
+                &self.fcx,
+                opaque_type_key,
+                hidden_type.span,
+                DefiningScopeKind::HirTypeck,
+            ) {
+                self.typeck_results
+                    .concrete_opaque_types
+                    .insert(opaque_type_key.def_id, ty::OpaqueHiddenType::new_error(tcx, guar));
+            }
+
+            let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
+                opaque_type_key,
+                tcx,
+                DefiningScopeKind::HirTypeck,
+            );
+
+            if let Some(prev) = self
+                .typeck_results
+                .concrete_opaque_types
+                .insert(opaque_type_key.def_id, hidden_type)
             {
-                assert!(!self.fcx.next_trait_solver());
-                if let Ok(d) = hidden_type.build_mismatch_error(&last_opaque_ty, self.tcx()) {
-                    d.emit();
+                let entry = &mut self
+                    .typeck_results
+                    .concrete_opaque_types
+                    .get_mut(&opaque_type_key.def_id)
+                    .unwrap();
+                if prev.ty != hidden_type.ty {
+                    if let Some(guar) = self.typeck_results.tainted_by_errors {
+                        entry.ty = Ty::new_error(tcx, guar);
+                    } else {
+                        let (Ok(guar) | Err(guar)) =
+                            prev.build_mismatch_error(&hidden_type, tcx).map(|d| d.emit());
+                        entry.ty = Ty::new_error(tcx, guar);
+                    }
                 }
+
+                // Pick a better span if there is one.
+                // FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
+                entry.span = prev.span.substitute_dummy(hidden_type.span);
             }
         }
     }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index fa8dea064daaa..20aa8e44f4392 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -966,7 +966,8 @@ impl<'tcx> InferCtxt<'tcx> {
     pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
         debug_assert!(!self.next_trait_solver());
         match self.typing_mode() {
-            TypingMode::Analysis { defining_opaque_types } => {
+            TypingMode::Analysis { defining_opaque_types }
+            | TypingMode::Borrowck { defining_opaque_types } => {
                 id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
             }
             // FIXME(#132279): This function is quite weird in post-analysis
@@ -1260,7 +1261,8 @@ impl<'tcx> InferCtxt<'tcx> {
             // to handle them without proper canonicalization. This means we may cause cycle
             // errors and fail to reveal opaques while inside of bodies. We should rename this
             // function and require explicit comments on all use-sites in the future.
-            ty::TypingMode::Analysis { defining_opaque_types: _ } => {
+            ty::TypingMode::Analysis { defining_opaque_types: _ }
+            | ty::TypingMode::Borrowck { defining_opaque_types: _ } => {
                 TypingMode::non_body_analysis()
             }
             mode @ (ty::TypingMode::Coherence
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index d9297fb419446..ce5d2e6e17a96 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -12,7 +12,7 @@ use rustc_middle::ty::{
 use rustc_span::Span;
 use tracing::{debug, instrument};
 
-use super::DefineOpaqueTypes;
+use super::{DefineOpaqueTypes, RegionVariableOrigin};
 use crate::errors::OpaqueHiddenTypeDiag;
 use crate::infer::{InferCtxt, InferOk};
 use crate::traits::{self, Obligation, PredicateObligations};
@@ -221,6 +221,7 @@ impl<'tcx> InferCtxt<'tcx> {
         hidden_ty: Ty<'tcx>,
         goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
     ) -> Result<(), TypeError<'tcx>> {
+        let tcx = self.tcx;
         // Ideally, we'd get the span where *this specific `ty` came
         // from*, but right now we just use the span from the overall
         // value being folded. In simple cases like `-> impl Foo`,
@@ -231,7 +232,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 // During intercrate we do not define opaque types but instead always
                 // force ambiguity unless the hidden type is known to not implement
                 // our trait.
-                goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous));
+                goals.push(Goal::new(tcx, param_env, ty::PredicateKind::Ambiguous));
             }
             ty::TypingMode::Analysis { .. } => {
                 let prev = self
@@ -249,6 +250,36 @@ impl<'tcx> InferCtxt<'tcx> {
                     );
                 }
             }
+            ty::TypingMode::Borrowck { .. } => {
+                let prev = self
+                    .inner
+                    .borrow_mut()
+                    .opaque_types()
+                    .register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
+
+                // We either equate the new hidden type with the previous entry or with the type
+                // inferred by HIR typeck.
+                let actual = prev.unwrap_or_else(|| {
+                    let actual = tcx
+                        .type_of_opaque_hir_typeck(opaque_type_key.def_id)
+                        .instantiate(self.tcx, opaque_type_key.args);
+                    let actual = ty::fold_regions(tcx, actual, |re, _dbi| match re.kind() {
+                        ty::ReErased => {
+                            self.next_region_var(RegionVariableOrigin::MiscVariable(span))
+                        }
+                        _ => re,
+                    });
+                    actual
+                });
+
+                goals.extend(
+                    self.at(&ObligationCause::dummy_with_span(span), param_env)
+                        .eq(DefineOpaqueTypes::Yes, hidden_ty, actual)?
+                        .obligations
+                        .into_iter()
+                        .map(|obligation| obligation.as_goal()),
+                );
+            }
             mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => {
                 bug!("insert hidden type in {mode:?}")
             }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 698859c663b17..0d5fba3cc69b4 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -267,6 +267,8 @@ rustc_queries! {
     ///
     /// This is a specialized instance of [`Self::type_of`] that detects query cycles.
     /// Unless `CyclePlaceholder` needs to be handled separately, call [`Self::type_of`] instead.
+    /// This is used to improve the error message in cases where revealing the hidden type
+    /// for auto-trait leakage cycles.
     ///
     /// # Panics
     ///
@@ -278,6 +280,12 @@ rustc_queries! {
         }
         cycle_stash
     }
+    query type_of_opaque_hir_typeck(key: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
+        desc { |tcx|
+            "computing type of opaque `{path}` via HIR typeck",
+            path = tcx.def_path_str(key),
+        }
+    }
 
     /// Returns whether the type alias given by `DefId` is lazy.
     ///
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 618a65a018644..b1ace67440461 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -206,6 +206,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
         self.type_of(def_id)
     }
+    fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
+        self.type_of_opaque_hir_typeck(def_id)
+    }
 
     type AdtDef = ty::AdtDef<'tcx>;
     fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef {
@@ -3248,6 +3251,11 @@ impl<'tcx> TyCtxt<'tcx> {
         self.sess.opts.unstable_opts.next_solver.coherence
     }
 
+    #[allow(rustc::bad_opt_access)]
+    pub fn use_typing_mode_borrowck(self) -> bool {
+        self.next_trait_solver_globally() || self.sess.opts.unstable_opts.typing_mode_borrowck
+    }
+
     pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
         self.opt_rpitit_info(def_id).is_some()
     }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 255d464d26541..8db0c7c9b3aa3 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -48,7 +48,7 @@ use rustc_serialize::{Decodable, Encodable};
 use rustc_session::lint::LintBuffer;
 pub use rustc_session::lint::RegisteredTools;
 use rustc_span::hygiene::MacroKind;
-use rustc_span::{ExpnId, ExpnKind, Ident, Span, Symbol, kw, sym};
+use rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol, kw, sym};
 pub use rustc_type_ir::relate::VarianceDiagInfo;
 pub use rustc_type_ir::*;
 use tracing::{debug, instrument};
@@ -782,7 +782,22 @@ pub struct OpaqueHiddenType<'tcx> {
     pub ty: Ty<'tcx>,
 }
 
+/// Whether we're currently in HIR typeck or MIR borrowck.
+#[derive(Debug, Clone, Copy)]
+pub enum DefiningScopeKind {
+    /// During writeback in typeck, we don't care about regions and simply
+    /// erase them. This means we also don't check whether regions are
+    /// universal in the opaque type key. This will only be checked in
+    /// MIR borrowck.
+    HirTypeck,
+    MirBorrowck,
+}
+
 impl<'tcx> OpaqueHiddenType<'tcx> {
+    pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> OpaqueHiddenType<'tcx> {
+        OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(tcx, guar) }
+    }
+
     pub fn build_mismatch_error(
         &self,
         other: &Self,
@@ -808,8 +823,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
         self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
         tcx: TyCtxt<'tcx>,
-        // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck.
-        ignore_errors: bool,
+        defining_scope_kind: DefiningScopeKind,
     ) -> Self {
         let OpaqueTypeKey { def_id, args } = opaque_type_key;
 
@@ -828,10 +842,19 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
         let map = args.iter().zip(id_args).collect();
         debug!("map = {:#?}", map);
 
-        // Convert the type from the function into a type valid outside
-        // the function, by replacing invalid regions with 'static,
-        // after producing an error for each of them.
-        self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span, ignore_errors))
+        // Convert the type from the function into a type valid outside by mapping generic
+        // parameters to into the context of the opaque.
+        //
+        // We erase regions when doing this during HIR typeck.
+        let this = match defining_scope_kind {
+            DefiningScopeKind::HirTypeck => tcx.erase_regions(self),
+            DefiningScopeKind::MirBorrowck => self,
+        };
+        let result = this.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span));
+        if cfg!(debug_assertions) && matches!(defining_scope_kind, DefiningScopeKind::HirTypeck) {
+            assert_eq!(result.ty, tcx.erase_regions(result.ty));
+        }
+        result
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 56c44c8a84c04..c72efde099497 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -20,12 +20,6 @@ pub(super) struct ReverseMapper<'tcx> {
     /// for an explanation of this field.
     do_not_error: bool,
 
-    /// We do not want to emit any errors in typeck because
-    /// the spans in typeck are subpar at the moment.
-    /// Borrowck will do the same work again (this time with
-    /// lifetime information) and thus report better errors.
-    ignore_errors: bool,
-
     /// Span of function being checked.
     span: Span,
 }
@@ -35,9 +29,8 @@ impl<'tcx> ReverseMapper<'tcx> {
         tcx: TyCtxt<'tcx>,
         map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
         span: Span,
-        ignore_errors: bool,
     ) -> Self {
-        Self { tcx, map, do_not_error: false, ignore_errors, span }
+        Self { tcx, map, do_not_error: false, span }
     }
 
     fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
@@ -176,20 +169,18 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
                     Some(u) => panic!("type mapped to unexpected kind: {u:?}"),
                     None => {
                         debug!(?param, ?self.map);
-                        if !self.ignore_errors {
-                            self.tcx
-                                .dcx()
-                                .struct_span_err(
-                                    self.span,
-                                    format!(
-                                        "type parameter `{ty}` is part of concrete type but not \
+                        let guar = self
+                            .tcx
+                            .dcx()
+                            .struct_span_err(
+                                self.span,
+                                format!(
+                                    "type parameter `{ty}` is part of concrete type but not \
                                           used in parameter list for the `impl Trait` type alias"
-                                    ),
-                                )
-                                .emit();
-                        }
-
-                        Ty::new_misc_error(self.tcx)
+                                ),
+                            )
+                            .emit();
+                        Ty::new_error(self.tcx, guar)
                     }
                 }
             }
@@ -217,8 +208,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
                                 ct: ct.to_string(),
                                 span: self.span,
                             })
-                            .emit_unless(self.ignore_errors);
-
+                            .emit();
                         ty::Const::new_error(self.tcx, guar)
                     }
                 }
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 3d3f4e2773a2d..7c437abfe24c9 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -158,7 +158,7 @@ pub struct TypeckResults<'tcx> {
     /// We also store the type here, so that the compiler can use it as a hint
     /// for figuring out hidden types, even if they are only set in dead code
     /// (which doesn't show up in MIR).
-    pub concrete_opaque_types: FxIndexMap<ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>>,
+    pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
 
     /// Tracks the minimum captures required for a closure;
     /// see `MinCaptureInformationMap` for more details.
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index 199f0c7512e1b..7641e9a16ee62 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -330,6 +330,7 @@ where
             // During analysis, opaques are rigid unless they may be defined by
             // the current body.
             TypingMode::Analysis { defining_opaque_types: non_rigid_opaques }
+            | TypingMode::Borrowck { defining_opaque_types: non_rigid_opaques }
             | TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
                 !def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))
             }
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
index 82dae51b3d038..aa89e77bb6fb9 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
@@ -96,6 +96,42 @@ where
                 );
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
+            // Very similar to `TypingMode::Analysis` with some notably differences:
+            // - we accept opaque types even if they have non-universal arguments
+            // - we do a structural lookup instead of semantically unifying regions
+            // - the hidden type starts out as the type from HIR typeck with fresh region
+            //   variables instead of a fully unconstrained inference variable
+            TypingMode::Borrowck { defining_opaque_types } => {
+                let Some(def_id) = opaque_ty
+                    .def_id
+                    .as_local()
+                    .filter(|&def_id| defining_opaque_types.contains(&def_id))
+                else {
+                    self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
+                    return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
+                };
+
+                let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args };
+                let actual = self
+                    .register_hidden_type_in_storage(opaque_type_key, expected)
+                    .unwrap_or_else(|| {
+                        let actual =
+                            cx.type_of_opaque_hir_typeck(def_id).instantiate(cx, opaque_ty.args);
+                        let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() {
+                            ty::ReErased => self.next_region_var(),
+                            _ => re,
+                        });
+                        actual
+                    });
+                self.eq(goal.param_env, expected, actual)?;
+                self.add_item_bounds_for_hidden_type(
+                    def_id.into(),
+                    opaque_ty.args,
+                    goal.param_env,
+                    expected,
+                );
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+            }
             TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
                 let Some(def_id) = opaque_ty
                     .def_id
diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
index eba496fa22659..ecffbbff7a2dc 100644
--- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
@@ -62,6 +62,7 @@ where
                     response_no_constraints(cx, input, Certainty::overflow(false))
                 }
                 TypingMode::Analysis { .. }
+                | TypingMode::Borrowck { .. }
                 | TypingMode::PostBorrowckAnalysis { .. }
                 | TypingMode::PostAnalysis => Err(NoSolution),
             },
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index b72f776e5cb48..2a1196735cd34 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -72,6 +72,7 @@ where
             (ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() {
                 TypingMode::Coherence => Certainty::AMBIGUOUS,
                 TypingMode::Analysis { .. }
+                | TypingMode::Borrowck { .. }
                 | TypingMode::PostBorrowckAnalysis { .. }
                 | TypingMode::PostAnalysis => return Err(NoSolution),
             },
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index a25a80cd45f74..31c4ee0fa0bbf 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -135,7 +135,10 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
     /// Returns the hidden type corresponding to this key if the body under analysis is allowed to
     /// know it.
     fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> {
-        self.typeck_results.concrete_opaque_types.get(&key).map(|x| x.ty)
+        self.typeck_results
+            .concrete_opaque_types
+            .get(&key.def_id)
+            .map(|x| ty::EarlyBinder::bind(x.ty).instantiate(self.tcx, key.args))
     }
     // This can take a non-revealed `Ty` because it reveals opaques itself.
     pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index cd5e2c4173e7b..36f7486f1d4cd 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -2553,6 +2553,9 @@ written to standard error output)"),
         "in diagnostics, use heuristics to shorten paths referring to items"),
     tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
         "select processor to schedule for (`rustc --print target-cpus` for details)"),
+    #[rustc_lint_opt_deny_field_access("use `TyCtxt::use_typing_mode_borrowck` instead of this field")]
+    typing_mode_borrowck: bool = (false, parse_bool, [TRACKED],
+        "enable `TypingMode::Borrowck`, changing the way opaque types are handled during MIR borrowck"),
     #[rustc_lint_opt_deny_field_access("use `Session::ub_checks` instead of this field")]
     ub_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "emit runtime checks for Undefined Behavior (default: -Cdebug-assertions)"),
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index 4db9d9915b139..05bbb42fb7c63 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -264,8 +264,15 @@ trait_selection_oc_no_diverge = `else` clause of `let...else` does not diverge
 trait_selection_oc_no_else = `if` may be missing an `else` clause
 trait_selection_oc_try_compat = `?` operator has incompatible types
 trait_selection_oc_type_compat = type not compatible with trait
+
 trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
     .label = opaque type defined here
+trait_selection_opaque_type_non_generic_param =
+    expected generic {$kind} parameter, found `{$ty}`
+    .label = {STREQ($ty, "'static") ->
+        [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+        *[other] this generic parameter must be used with a generic {$kind} parameter
+    }
 
 trait_selection_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
 trait_selection_outlives_content = lifetime of reference outlives lifetime of borrowed content...
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index b30390a9330eb..9f7bfe5101ab2 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -12,7 +12,7 @@ use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
 use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, IsAnonInPath, Node};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
-use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, Region, Ty, TyCtxt};
+use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, GenericArg, Region, Ty, TyCtxt};
 use rustc_span::{BytePos, Ident, Span, Symbol, kw};
 
 use crate::error_reporting::infer::ObligationCauseAsDiagArg;
@@ -1922,3 +1922,14 @@ impl Subdiagnostic for AddPreciseCapturingForOvercapture {
         }
     }
 }
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_opaque_type_non_generic_param, code = E0792)]
+pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
+    pub ty: GenericArg<'tcx>,
+    pub kind: &'a str,
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub param_span: Span,
+}
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index b18fb0fb8fd31..93c1180530452 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -36,6 +36,7 @@
 pub mod error_reporting;
 pub mod errors;
 pub mod infer;
+pub mod opaque_types;
 pub mod regions;
 pub mod solve;
 pub mod traits;
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
new file mode 100644
index 0000000000000..c7b8f0631962e
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -0,0 +1,182 @@
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_hir::OpaqueTyOrigin;
+use rustc_hir::def_id::LocalDefId;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_middle::ty::{
+    self, DefiningScopeKind, GenericArgKind, GenericArgs, OpaqueTypeKey, TyCtxt, TypeVisitableExt,
+    TypingMode, fold_regions,
+};
+use rustc_span::{ErrorGuaranteed, Span};
+
+use crate::errors::NonGenericOpaqueTypeParam;
+use crate::regions::OutlivesEnvironmentBuildExt;
+use crate::traits::ObligationCtxt;
+
+/// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter].
+///
+/// [rustc-dev-guide chapter]:
+/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
+pub fn check_opaque_type_parameter_valid<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    opaque_type_key: OpaqueTypeKey<'tcx>,
+    span: Span,
+    defining_scope_kind: DefiningScopeKind,
+) -> Result<(), ErrorGuaranteed> {
+    let tcx = infcx.tcx;
+    let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
+    let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
+    let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
+
+    // Avoid duplicate errors in case the opaque has already been malformed in
+    // HIR typeck.
+    if let DefiningScopeKind::MirBorrowck = defining_scope_kind {
+        if let Err(guar) = infcx
+            .tcx
+            .type_of_opaque_hir_typeck(opaque_type_key.def_id)
+            .instantiate_identity()
+            .error_reported()
+        {
+            return Err(guar);
+        }
+    }
+
+    for (i, arg) in opaque_type_key.iter_captured_args(tcx) {
+        let arg_is_param = match arg.unpack() {
+            GenericArgKind::Lifetime(lt) => match defining_scope_kind {
+                DefiningScopeKind::HirTypeck => continue,
+                DefiningScopeKind::MirBorrowck => {
+                    matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
+                        || (lt.is_static() && opaque_env.param_equal_static(i))
+                }
+            },
+            GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
+            GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
+        };
+
+        if arg_is_param {
+            // Register if the same lifetime appears multiple times in the generic args.
+            // There is an exception when the opaque type *requires* the lifetimes to be equal.
+            // See [rustc-dev-guide chapter] ยง "An exception to uniqueness rule".
+            let seen_where = seen_params.entry(arg).or_default();
+            if !seen_where.first().is_some_and(|&prev_i| opaque_env.params_equal(i, prev_i)) {
+                seen_where.push(i);
+            }
+        } else {
+            // Prevent `fn foo() -> Foo<u32>` from being defining.
+            let opaque_param = opaque_generics.param_at(i, tcx);
+            let kind = opaque_param.kind.descr();
+
+            opaque_env.param_is_error(i)?;
+
+            return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam {
+                ty: arg,
+                kind,
+                span,
+                param_span: tcx.def_span(opaque_param.def_id),
+            }));
+        }
+    }
+
+    for (_, indices) in seen_params {
+        if indices.len() > 1 {
+            let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
+            let spans: Vec<_> = indices
+                .into_iter()
+                .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
+                .collect();
+            return Err(infcx
+                .dcx()
+                .struct_span_err(span, "non-defining opaque type use in defining scope")
+                .with_span_note(spans, format!("{descr} used multiple times"))
+                .emit());
+        }
+    }
+
+    Ok(())
+}
+
+/// Computes if an opaque type requires a lifetime parameter to be equal to
+/// another one or to the `'static` lifetime.
+/// These requirements are derived from the explicit and implied bounds.
+struct LazyOpaqueTyEnv<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+
+    /// Equal parameters will have the same name. Computed Lazily.
+    /// Example:
+    ///     `type Opaque<'a: 'static, 'b: 'c, 'c: 'b> = impl Sized;`
+    ///     Identity args: `['a, 'b, 'c]`
+    ///     Canonical args: `['static, 'b, 'b]`
+    canonical_args: std::cell::OnceCell<ty::GenericArgsRef<'tcx>>,
+}
+
+impl<'tcx> LazyOpaqueTyEnv<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
+        Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() }
+    }
+
+    fn param_equal_static(&self, param_index: usize) -> bool {
+        self.get_canonical_args()[param_index].expect_region().is_static()
+    }
+
+    fn params_equal(&self, param1: usize, param2: usize) -> bool {
+        let canonical_args = self.get_canonical_args();
+        canonical_args[param1] == canonical_args[param2]
+    }
+
+    fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> {
+        self.get_canonical_args()[param_index].error_reported()
+    }
+
+    fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> {
+        if let Some(&canonical_args) = self.canonical_args.get() {
+            return canonical_args;
+        }
+
+        let &Self { tcx, def_id, .. } = self;
+        let origin = tcx.local_opaque_ty_origin(def_id);
+        let parent = match origin {
+            OpaqueTyOrigin::FnReturn { parent, .. }
+            | OpaqueTyOrigin::AsyncFn { parent, .. }
+            | OpaqueTyOrigin::TyAlias { parent, .. } => parent,
+        };
+        let param_env = tcx.param_env(parent);
+        let args = GenericArgs::identity_for_item(tcx, parent).extend_to(
+            tcx,
+            def_id.to_def_id(),
+            |param, _| {
+                tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
+            },
+        );
+
+        // FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're
+        // in a body here.
+        let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
+        let ocx = ObligationCtxt::new(&infcx);
+
+        let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| {
+            tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds");
+            Default::default()
+        });
+        let outlives_env = OutlivesEnvironment::new(&infcx, parent, param_env, wf_tys);
+
+        let mut seen = vec![tcx.lifetimes.re_static];
+        let canonical_args = fold_regions(tcx, args, |r1, _| {
+            if r1.is_error() {
+                r1
+            } else if let Some(&r2) = seen.iter().find(|&&r2| {
+                let free_regions = outlives_env.free_region_map();
+                free_regions.sub_free_regions(tcx, r1, r2)
+                    && free_regions.sub_free_regions(tcx, r2, r1)
+            }) {
+                r2
+            } else {
+                seen.push(r1);
+                r1
+            }
+        });
+        self.canonical_args.set(canonical_args).unwrap();
+        canonical_args
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index f2725411e13c3..e0b425fa7391b 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -195,6 +195,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
             match self.typing_mode() {
                 TypingMode::Coherence
                 | TypingMode::Analysis { .. }
+                | TypingMode::Borrowck { .. }
                 | TypingMode::PostBorrowckAnalysis { .. } => false,
                 TypingMode::PostAnalysis => {
                     let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index ad62b456ad461..4ac45172a0e1c 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -130,6 +130,7 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
         // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
         TypingMode::Coherence
         | TypingMode::Analysis { .. }
+        | TypingMode::Borrowck { .. }
         | TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE),
         TypingMode::PostAnalysis => {}
     }
@@ -226,6 +227,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                     // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
                     TypingMode::Coherence
                     | TypingMode::Analysis { .. }
+                    | TypingMode::Borrowck { .. }
                     | TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self),
                     TypingMode::PostAnalysis => {
                         let recursion_limit = self.cx().recursion_limit();
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 6057b66c483f5..349569d750e08 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -952,6 +952,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                             match selcx.infcx.typing_mode() {
                                 TypingMode::Coherence
                                 | TypingMode::Analysis { .. }
+                                | TypingMode::Borrowck { .. }
                                 | TypingMode::PostBorrowckAnalysis { .. } => {
                                     debug!(
                                         assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 165c63f3745a2..5dbb4382fd1be 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -216,6 +216,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
                 match self.infcx.typing_mode() {
                     TypingMode::Coherence
                     | TypingMode::Analysis { .. }
+                    | TypingMode::Borrowck { .. }
                     | TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?,
 
                     TypingMode::PostAnalysis => {
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 0679dbf1296af..d78938225f1dc 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1446,6 +1446,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         match self.infcx.typing_mode() {
             TypingMode::Coherence => {}
             TypingMode::Analysis { .. }
+            | TypingMode::Borrowck { .. }
             | TypingMode::PostBorrowckAnalysis { .. }
             | TypingMode::PostAnalysis => return Ok(()),
         }
@@ -1491,7 +1492,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // However, if we disqualify *all* goals from being cached, perf suffers.
             // This is likely fixed by better caching in general in the new solver.
             // See: <https://github.com/rust-lang/rust/issues/132064>.
-            TypingMode::Analysis { defining_opaque_types } => {
+            TypingMode::Analysis { defining_opaque_types }
+            | TypingMode::Borrowck { defining_opaque_types } => {
                 defining_opaque_types.is_empty() || !pred.has_opaque_types()
             }
             // The hidden types of `defined_opaque_types` is not local to the current
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 962e1353ebcd7..66c18bed5e71a 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -149,6 +149,7 @@ fn resolve_associated_item<'tcx>(
                 match typing_env.typing_mode {
                     ty::TypingMode::Coherence
                     | ty::TypingMode::Analysis { .. }
+                    | ty::TypingMode::Borrowck { .. }
                     | ty::TypingMode::PostBorrowckAnalysis { .. } => false,
                     ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(),
                 }
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index e512e8fc838f1..fec6e24e2cb4d 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -66,6 +66,14 @@ pub enum TypingMode<I: Interner> {
     /// }
     /// ```
     Analysis { defining_opaque_types: I::DefiningOpaqueTypes },
+    /// The behavior during MIR borrowck is identical to `TypingMode::Analysis`
+    /// except that the initial value for opaque types is the type computed during
+    /// HIR typeck with unique unconstrained region inference variables.
+    ///
+    /// This is currently only used with by the new solver as it results in new
+    /// non-universal defining uses of opaque types, which is a breaking change.
+    /// See tests/ui/impl-trait/non-defining-use/as-projection-term.rs.
+    Borrowck { defining_opaque_types: I::DefiningOpaqueTypes },
     /// Any analysis after borrowck for a given body should be able to use all the
     /// hidden types defined by borrowck, without being able to define any new ones.
     ///
@@ -95,6 +103,10 @@ impl<I: Interner> TypingMode<I> {
         TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
     }
 
+    pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
+        TypingMode::Borrowck { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
+    }
+
     pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
         TypingMode::PostBorrowckAnalysis {
             defined_opaque_types: cx.opaque_types_defined_by(body_def_id),
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 8f86270d7dce7..44b260ddd3a2f 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -149,6 +149,8 @@ pub trait Interner:
     ) -> Option<Self::VariancesOf>;
 
     fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder<Self, Self::Ty>;
+    fn type_of_opaque_hir_typeck(self, def_id: Self::LocalDefId)
+    -> ty::EarlyBinder<Self, Self::Ty>;
 
     type AdtDef: AdtDef<Self>;
     fn adt_def(self, adt_def_id: Self::DefId) -> Self::AdtDef;
diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs
index d49f8d3093db7..8dd7c4df24421 100644
--- a/compiler/rustc_type_ir/src/relate/combine.rs
+++ b/compiler/rustc_type_ir/src/relate/combine.rs
@@ -137,6 +137,7 @@ where
                     Ok(a)
                 }
                 TypingMode::Analysis { .. }
+                | TypingMode::Borrowck { .. }
                 | TypingMode::PostBorrowckAnalysis { .. }
                 | TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b),
             }
diff --git a/tests/crashes/112201.rs b/tests/crashes/112201.rs
deleted file mode 100644
index 5d363403b8acb..0000000000000
--- a/tests/crashes/112201.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-//@ known-bug: #112201
-
-pub fn compose(
-    f1: impl FnOnce(f64) -> f64 + Clone,
-    f2: impl FnOnce(f64) -> f64 + Clone,
-) -> impl FnOnce(f64) -> f64 + Clone {
-    move |x| f1(f2(x))
-}
-
-fn repeat_helper(
-    f: impl FnOnce(f64) -> f64 + Clone,
-    res: impl FnOnce(f64) -> f64 + Clone,
-    times: usize,
-) -> impl FnOnce(f64) -> f64 + Clone {
-    return res;
-    repeat_helper(f.clone(), compose(f, res), times - 1)
-}
-
-fn main() {}
diff --git a/tests/crashes/137751.rs b/tests/crashes/137751.rs
deleted file mode 100644
index 85ae3acd53d30..0000000000000
--- a/tests/crashes/137751.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-//@ known-bug: #137751
-//@ compile-flags: --edition=2021 -Znext-solver=globally
-async fn test() {
-    Box::pin(test()).await;
-}
-fn main() {}
diff --git a/tests/ui/coroutine/clone-rpit.next.stderr b/tests/ui/coroutine/clone-rpit.next.stderr
index c223f1f211ac6..213e9e908f56d 100644
--- a/tests/ui/coroutine/clone-rpit.next.stderr
+++ b/tests/ui/coroutine/clone-rpit.next.stderr
@@ -35,11 +35,11 @@ note: ...which requires type-checking `foo::{closure#0}`...
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
    = note: ...which again requires type-checking `foo`, completing the cycle
-note: cycle used when computing type of opaque `foo::{opaque#0}`
-  --> $DIR/clone-rpit.rs:13:25
+note: cycle used when match-checking `foo`
+  --> $DIR/clone-rpit.rs:13:1
    |
 LL | pub fn foo<'a, 'b>() -> impl Clone {
-   |                         ^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/generic-associated-types/issue-87258_a.rs b/tests/ui/generic-associated-types/issue-87258_a.rs
index 6f737b21f53cd..2ea77bbca768c 100644
--- a/tests/ui/generic-associated-types/issue-87258_a.rs
+++ b/tests/ui/generic-associated-types/issue-87258_a.rs
@@ -15,8 +15,8 @@ pub trait Trait2 {
 
 impl<'c, S: Trait2> Trait2 for &'c mut S {
     type FooFuture<'a> = impl Trait1;
-    //~^ ERROR unconstrained opaque type
     fn foo<'a>() -> Self::FooFuture<'a> {
+        //~^ ERROR item does not constrain `<&'c mut S as Trait2>::FooFuture::{opaque#0}`
         Struct(unimplemented!())
     }
 }
diff --git a/tests/ui/generic-associated-types/issue-87258_a.stderr b/tests/ui/generic-associated-types/issue-87258_a.stderr
index 01f2a92f94a6b..f175c15bd02b2 100644
--- a/tests/ui/generic-associated-types/issue-87258_a.stderr
+++ b/tests/ui/generic-associated-types/issue-87258_a.stderr
@@ -1,10 +1,15 @@
-error: unconstrained opaque type
+error: item does not constrain `<&'c mut S as Trait2>::FooFuture::{opaque#0}`
+  --> $DIR/issue-87258_a.rs:18:8
+   |
+LL |     fn foo<'a>() -> Self::FooFuture<'a> {
+   |        ^^^
+   |
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/issue-87258_a.rs:17:26
    |
 LL |     type FooFuture<'a> = impl Trait1;
    |                          ^^^^^^^^^^^
-   |
-   = note: `FooFuture` must be used in combination with a concrete type within the same impl
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/generic-associated-types/issue-87258_b.rs b/tests/ui/generic-associated-types/issue-87258_b.rs
index 84c7182cdcbc9..8b820e75f6043 100644
--- a/tests/ui/generic-associated-types/issue-87258_b.rs
+++ b/tests/ui/generic-associated-types/issue-87258_b.rs
@@ -14,12 +14,12 @@ pub trait Trait2 {
 }
 
 type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1;
-//~^ ERROR unconstrained opaque type
 
 impl<'c, S: Trait2> Trait2 for &'c mut S {
     type FooFuture<'a> = Helper<'c, 'a, S>;
     #[define_opaque(Helper)]
     fn foo<'a>() -> Self::FooFuture<'a> {
+        //~^ ERROR item does not constrain `Helper::{opaque#0}`
         Struct(unimplemented!())
     }
 }
diff --git a/tests/ui/generic-associated-types/issue-87258_b.stderr b/tests/ui/generic-associated-types/issue-87258_b.stderr
index 906ce1f50da79..56abcef0d3776 100644
--- a/tests/ui/generic-associated-types/issue-87258_b.stderr
+++ b/tests/ui/generic-associated-types/issue-87258_b.stderr
@@ -1,10 +1,15 @@
-error: unconstrained opaque type
+error: item does not constrain `Helper::{opaque#0}`
+  --> $DIR/issue-87258_b.rs:21:8
+   |
+LL |     fn foo<'a>() -> Self::FooFuture<'a> {
+   |        ^^^
+   |
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/issue-87258_b.rs:16:49
    |
 LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1;
    |                                                 ^^^^^^^^^^^
-   |
-   = note: `Helper` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr
index 34617448a692a..79ded34d9cd9e 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr
@@ -1,18 +1,5 @@
-error: item does not constrain `Foo::{opaque#0}`
-  --> $DIR/norm-before-method-resolution-opaque-type.rs:17:4
-   |
-LL | fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
-   |    ^^^^^^^^^^^
-   |
-   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
-note: this opaque type is supposed to be constrained
-  --> $DIR/norm-before-method-resolution-opaque-type.rs:14:12
-   |
-LL | type Foo = impl Sized;
-   |            ^^^^^^^^^^
-
 error[E0507]: cannot move out of `*x` which is behind a shared reference
-  --> $DIR/norm-before-method-resolution-opaque-type.rs:23:13
+  --> $DIR/norm-before-method-resolution-opaque-type.rs:22:13
    |
 LL |     let x = *x;
    |             ^^ move occurs because `*x` has type `<X as Trait<'_>>::Out<Foo>`, which does not implement the `Copy` trait
@@ -23,6 +10,6 @@ LL -     let x = *x;
 LL +     let x = x;
    |
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs
index bb663c82abb0e..f881fcb779fa8 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs
@@ -15,7 +15,6 @@ type Foo = impl Sized;
 
 #[define_opaque(Foo)]
 fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
-//[old]~^ ERROR: item does not constrain
 where
     for<'a> X: Trait<'a>,
     for<'a> <X as Trait<'a>>::Out<()>: Copy,
diff --git a/tests/ui/impl-trait/issue-55872-1.rs b/tests/ui/impl-trait/issue-55872-1.rs
index f36a310ddf310..663cdbc2f5cba 100644
--- a/tests/ui/impl-trait/issue-55872-1.rs
+++ b/tests/ui/impl-trait/issue-55872-1.rs
@@ -13,6 +13,7 @@ impl<S: Default> Bar for S {
         //~^ ERROR impl has stricter requirements than trait
         //~| ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277]
         //~| ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277]
+        //~| ERROR type parameter `T` is part of concrete type
         (S::default(), T::default())
     }
 }
diff --git a/tests/ui/impl-trait/issue-55872-1.stderr b/tests/ui/impl-trait/issue-55872-1.stderr
index 81759760bf13e..e048bec1b6d22 100644
--- a/tests/ui/impl-trait/issue-55872-1.stderr
+++ b/tests/ui/impl-trait/issue-55872-1.stderr
@@ -37,7 +37,13 @@ help: consider further restricting type parameter `T` with trait `Copy`
 LL |     fn foo<T: Default + std::marker::Copy>() -> Self::E {
    |                       +++++++++++++++++++
 
-error: aborting due to 3 previous errors
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+  --> $DIR/issue-55872-1.rs:12:29
+   |
+LL |     fn foo<T: Default>() -> Self::E {
+   |                             ^^^^^^^
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0276, E0277.
 For more information about an error, try `rustc --explain E0276`.
diff --git a/tests/ui/impl-trait/issue-55872-2.rs b/tests/ui/impl-trait/issue-55872-2.rs
index caca5c69a4aea..a3b2225126a22 100644
--- a/tests/ui/impl-trait/issue-55872-2.rs
+++ b/tests/ui/impl-trait/issue-55872-2.rs
@@ -11,9 +11,9 @@ pub trait Bar {
 impl<S> Bar for S {
     type E = impl std::marker::Send;
     fn foo<T>() -> Self::E {
-        async {}
         //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
         //~| ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+        async {}
     }
 }
 
diff --git a/tests/ui/impl-trait/issue-55872-2.stderr b/tests/ui/impl-trait/issue-55872-2.stderr
index b5b7f293a40b2..51a7dd00ade63 100644
--- a/tests/ui/impl-trait/issue-55872-2.stderr
+++ b/tests/ui/impl-trait/issue-55872-2.stderr
@@ -1,14 +1,14 @@
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872-2.rs:14:9
+  --> $DIR/issue-55872-2.rs:13:20
    |
-LL |         async {}
-   |         ^^^^^^^^
+LL |     fn foo<T>() -> Self::E {
+   |                    ^^^^^^^
 
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872-2.rs:14:9
+  --> $DIR/issue-55872-2.rs:13:20
    |
-LL |         async {}
-   |         ^^^^^^^^
+LL |     fn foo<T>() -> Self::E {
+   |                    ^^^^^^^
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
diff --git a/tests/ui/impl-trait/issue-55872-3.rs b/tests/ui/impl-trait/issue-55872-3.rs
index 50b9eb3ce0ecd..698e7f362341e 100644
--- a/tests/ui/impl-trait/issue-55872-3.rs
+++ b/tests/ui/impl-trait/issue-55872-3.rs
@@ -13,6 +13,7 @@ impl<S> Bar for S {
     type E = impl std::marker::Copy;
     fn foo<T>() -> Self::E {
         //~^ ERROR : Copy` is not satisfied [E0277]
+        //~| ERROR type parameter `T` is part of concrete type
         async {}
     }
 }
diff --git a/tests/ui/impl-trait/issue-55872-3.stderr b/tests/ui/impl-trait/issue-55872-3.stderr
index 827155d48b827..3281dcc3501d6 100644
--- a/tests/ui/impl-trait/issue-55872-3.stderr
+++ b/tests/ui/impl-trait/issue-55872-3.stderr
@@ -1,12 +1,18 @@
-error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}: Copy` is not satisfied
+error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}: Copy` is not satisfied
   --> $DIR/issue-55872-3.rs:14:20
    |
 LL |     fn foo<T>() -> Self::E {
-   |                    ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}`
-LL |
+   |                    ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}`
+...
 LL |         async {}
-   |         -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}` here
+   |         -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}` here
 
-error: aborting due to 1 previous error
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+  --> $DIR/issue-55872-3.rs:14:20
+   |
+LL |     fn foo<T>() -> Self::E {
+   |                    ^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/issue-55872.rs b/tests/ui/impl-trait/issue-55872.rs
index 10850f0a9335e..b76f8182b204f 100644
--- a/tests/ui/impl-trait/issue-55872.rs
+++ b/tests/ui/impl-trait/issue-55872.rs
@@ -10,8 +10,8 @@ impl<S> Bar for S {
     type E = impl Copy;
 
     fn foo<T>() -> Self::E {
-        || ()
         //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+        || ()
     }
 }
 
diff --git a/tests/ui/impl-trait/issue-55872.stderr b/tests/ui/impl-trait/issue-55872.stderr
index 4ff8527bbe9d1..54e852f8edf8d 100644
--- a/tests/ui/impl-trait/issue-55872.stderr
+++ b/tests/ui/impl-trait/issue-55872.stderr
@@ -1,8 +1,8 @@
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872.rs:13:9
+  --> $DIR/issue-55872.rs:12:20
    |
-LL |         || ()
-   |         ^^^^^
+LL |     fn foo<T>() -> Self::E {
+   |                    ^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issue-99073-2.rs b/tests/ui/impl-trait/issue-99073-2.rs
index 37ea211bec368..bfb8850857de2 100644
--- a/tests/ui/impl-trait/issue-99073-2.rs
+++ b/tests/ui/impl-trait/issue-99073-2.rs
@@ -7,8 +7,7 @@ fn main() {
 fn test<T: Display>(t: T, recurse: bool) -> impl Display {
     let f = || {
         let i: u32 = test::<i32>(-1, false);
-        //~^ ERROR concrete type differs from previous defining opaque type use
-        //~| ERROR expected generic type parameter, found `i32`
+        //~^ ERROR expected generic type parameter, found `i32`
         println!("{i}");
     };
     if recurse {
diff --git a/tests/ui/impl-trait/issue-99073-2.stderr b/tests/ui/impl-trait/issue-99073-2.stderr
index 0bcac7c7c534b..519530b539625 100644
--- a/tests/ui/impl-trait/issue-99073-2.stderr
+++ b/tests/ui/impl-trait/issue-99073-2.stderr
@@ -1,15 +1,3 @@
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/issue-99073-2.rs:9:22
-   |
-LL |         let i: u32 = test::<i32>(-1, false);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `u32`
-   |
-note: previous use here
-  --> $DIR/issue-99073-2.rs:7:45
-   |
-LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
-   |                                             ^^^^^^^^^^^^
-
 error[E0792]: expected generic type parameter, found `i32`
   --> $DIR/issue-99073-2.rs:9:22
    |
@@ -19,6 +7,6 @@ LL |     let f = || {
 LL |         let i: u32 = test::<i32>(-1, false);
    |                      ^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/issue-99073.rs b/tests/ui/impl-trait/issue-99073.rs
index b4ef3e66f964a..d2a2a61a40845 100644
--- a/tests/ui/impl-trait/issue-99073.rs
+++ b/tests/ui/impl-trait/issue-99073.rs
@@ -4,6 +4,5 @@ fn main() {
 
 fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
   move || f(fix(&f))
-  //~^ ERROR concrete type differs from previous defining opaque type use
-  //~| ERROR expected generic type parameter, found `&F`
+  //~^ ERROR expected generic type parameter, found `&F`
 }
diff --git a/tests/ui/impl-trait/issue-99073.stderr b/tests/ui/impl-trait/issue-99073.stderr
index 19854ef894051..1917c1bfd6b4f 100644
--- a/tests/ui/impl-trait/issue-99073.stderr
+++ b/tests/ui/impl-trait/issue-99073.stderr
@@ -1,23 +1,11 @@
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/issue-99073.rs:6:13
-   |
-LL |   move || f(fix(&f))
-   |             ^^^^^^^ expected `{closure@$DIR/issue-99073.rs:6:3: 6:10}`, got `G`
-   |
-note: previous use here
-  --> $DIR/issue-99073.rs:5:36
-   |
-LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
-   |                                    ^^^^^^^^^
-
 error[E0792]: expected generic type parameter, found `&F`
-  --> $DIR/issue-99073.rs:6:11
+  --> $DIR/issue-99073.rs:6:13
    |
 LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
    |        - this generic parameter must be used with a generic type parameter
 LL |   move || f(fix(&f))
-   |           ^^^^^^^^^^
+   |             ^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.rs b/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.rs
new file mode 100644
index 0000000000000..a76ed7b094745
--- /dev/null
+++ b/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.rs
@@ -0,0 +1,17 @@
+// Regression test for #112201. This recursive call previously meant that
+// we delay an error when checking opaques at the end of writeback but don't
+// encounter that incorrect defining use during borrowck as it's in dead code.
+
+pub fn wrap<T>(x: T) -> impl Sized {
+    x
+}
+
+fn repeat_helper<T>(x: T) -> impl Sized {
+    return x;
+    repeat_helper(wrap(x))
+    //~^ ERROR expected generic type parameter, found `impl Sized`
+    //~| ERROR type parameter `T` is part of concrete type
+}
+
+
+fn main() {}
diff --git a/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.stderr b/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.stderr
new file mode 100644
index 0000000000000..f507ad385a171
--- /dev/null
+++ b/tests/ui/impl-trait/issues/fuzzer-ice-issue-112201.stderr
@@ -0,0 +1,18 @@
+error[E0792]: expected generic type parameter, found `impl Sized`
+  --> $DIR/fuzzer-ice-issue-112201.rs:11:5
+   |
+LL | fn repeat_helper<T>(x: T) -> impl Sized {
+   |                  - this generic parameter must be used with a generic type parameter
+LL |     return x;
+LL |     repeat_helper(wrap(x))
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+  --> $DIR/fuzzer-ice-issue-112201.rs:11:5
+   |
+LL |     repeat_helper(wrap(x))
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/issues/issue-86800.rs b/tests/ui/impl-trait/issues/issue-86800.rs
index 9e8ea439dde95..cf82467b72ee3 100644
--- a/tests/ui/impl-trait/issues/issue-86800.rs
+++ b/tests/ui/impl-trait/issues/issue-86800.rs
@@ -29,7 +29,6 @@ where
     F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f,
 {
     f
-    //~^ ERROR expected generic lifetime parameter, found `'_`
 }
 
 impl Context {
@@ -39,7 +38,6 @@ impl Context {
         &self,
         f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>,
     ) -> TransactionResult<O> {
-        //~^ ERROR expected generic lifetime parameter, found `'_`
         let mut conn = Connection {};
         let mut transaction = TestTransaction { conn: &mut conn };
         f(&mut transaction).await
diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr
index 80aa5d75c3c69..e122fc229ccd3 100644
--- a/tests/ui/impl-trait/issues/issue-86800.stderr
+++ b/tests/ui/impl-trait/issues/issue-86800.stderr
@@ -12,7 +12,7 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResu
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item does not constrain `TransactionFuture::{opaque#0}`
-  --> $DIR/issue-86800.rs:37:14
+  --> $DIR/issue-86800.rs:36:14
    |
 LL |     async fn do_transaction<O>(
    |              ^^^^^^^^^^^^^^
@@ -24,30 +24,5 @@ note: this opaque type is supposed to be constrained
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/issue-86800.rs:31:5
-   |
-LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
-   |                        --- this generic parameter must be used with a generic lifetime parameter
-...
-LL |     f
-   |     ^
-
-error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/issue-86800.rs:41:31
-   |
-LL |   type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
-   |                          --- this generic parameter must be used with a generic lifetime parameter
-...
-LL |       ) -> TransactionResult<O> {
-   |  _______________________________^
-LL | |
-LL | |         let mut conn = Connection {};
-LL | |         let mut transaction = TestTransaction { conn: &mut conn };
-LL | |         f(&mut transaction).await
-LL | |     }
-   | |_____^
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/non-defining-uses/as-projection-term.next.stderr b/tests/ui/impl-trait/non-defining-uses/as-projection-term.next.stderr
new file mode 100644
index 0000000000000..08c8365b1805a
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/as-projection-term.next.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/as-projection-term.rs:14:19
+   |
+LL | fn recur<'a>() -> impl Sized + 'a {
+   |                                -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     prove_proj(|| recur());
+   |                   ^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/non-defining-uses/as-projection-term.rs b/tests/ui/impl-trait/non-defining-uses/as-projection-term.rs
new file mode 100644
index 0000000000000..4c5adc7a00ab1
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/as-projection-term.rs
@@ -0,0 +1,17 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[current] check-pass
+
+fn prove_proj<R>(_: impl FnOnce() -> R) {}
+fn recur<'a>() -> impl Sized + 'a {
+    // The closure has the signature `fn() -> opaque<'1>`. `prove_proj`
+    // requires us to prove `<closure as FnOnce<()>>::Output = opaque<'2>`.
+    // The old solver uses `replace_opaque_types_with_infer` during normalization
+    // to replace `opaque<'2>` with its hidden type. If that hidden type is still an
+    // inference variable at this point, we unify it with `opaque<'1>` and
+    // end up ignoring that defining use as the hidden type is equal to its key.
+    prove_proj(|| recur());
+    //[next]~^ ERROR expected generic lifetime parameter, found `'_`
+}
+fn main() {}
diff --git a/tests/ui/impl-trait/recursive-ice-101862.stderr b/tests/ui/impl-trait/recursive-ice-101862.stderr
index 970373422e8a5..85745c25e2bfa 100644
--- a/tests/ui/impl-trait/recursive-ice-101862.stderr
+++ b/tests/ui/impl-trait/recursive-ice-101862.stderr
@@ -1,3 +1,12 @@
+error[E0792]: expected generic type parameter, found `&str`
+  --> $DIR/recursive-ice-101862.rs:6:19
+   |
+LL | pub fn ice(x: impl AsRef<str>) -> impl IntoIterator<Item = ()> {
+   |               --------------- this generic parameter must be used with a generic type parameter
+LL |
+LL |     vec![].append(&mut ice(x.as_ref()));
+   |                   ^^^^^^^^^^^^^^^^^^^^
+
 warning: function cannot return without recursing
   --> $DIR/recursive-ice-101862.rs:4:1
    |
@@ -10,15 +19,6 @@ LL |     vec![].append(&mut ice(x.as_ref()));
    = help: a `loop` may express intention better if this is on purpose
    = note: `#[warn(unconditional_recursion)]` on by default
 
-error[E0792]: expected generic type parameter, found `&str`
-  --> $DIR/recursive-ice-101862.rs:6:19
-   |
-LL | pub fn ice(x: impl AsRef<str>) -> impl IntoIterator<Item = ()> {
-   |               --------------- this generic parameter must be used with a generic type parameter
-LL |
-LL |     vec![].append(&mut ice(x.as_ref()));
-   |                   ^^^^^^^^^^^^^^^^^^^^
-
 error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/rpit/early_bound.rs b/tests/ui/impl-trait/rpit/early_bound.rs
index 005bcea59f243..0337f605e487b 100644
--- a/tests/ui/impl-trait/rpit/early_bound.rs
+++ b/tests/ui/impl-trait/rpit/early_bound.rs
@@ -1,11 +1,10 @@
 use std::convert::identity;
 
 fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
-    //~^ ERROR concrete type differs from previous defining opaque type use
     let true = n else { loop {} };
     let _ = || {
         let _ = identity::<&'a ()>(test(false));
-        //~^ ERROR expected generic lifetime parameter, found `'_`
+        //~^ ERROR concrete type differs from previous defining opaque type use
     };
     loop {}
 }
diff --git a/tests/ui/impl-trait/rpit/early_bound.stderr b/tests/ui/impl-trait/rpit/early_bound.stderr
index 230dde95764bf..d00005f20d4a3 100644
--- a/tests/ui/impl-trait/rpit/early_bound.stderr
+++ b/tests/ui/impl-trait/rpit/early_bound.stderr
@@ -1,24 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/early_bound.rs:3:29
+  --> $DIR/early_bound.rs:6:36
    |
-LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
-   |                             ^^^^^^^^^^^^^^^ expected `&()`, got `()`
+LL |         let _ = identity::<&'a ()>(test(false));
+   |                                    ^^^^^^^^^^^ expected `()`, got `&()`
    |
 note: previous use here
-  --> $DIR/early_bound.rs:7:36
-   |
-LL |         let _ = identity::<&'a ()>(test(false));
-   |                                    ^^^^^^^^^^^
-
-error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/early_bound.rs:7:17
+  --> $DIR/early_bound.rs:3:29
    |
 LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
-   |                                          -- this generic parameter must be used with a generic lifetime parameter
-...
-LL |         let _ = identity::<&'a ()>(test(false));
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                             ^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/rpit/non-defining-use.rs b/tests/ui/impl-trait/rpit/non-defining-use.rs
index 255a8929a8786..3ab0e0ee4e29f 100644
--- a/tests/ui/impl-trait/rpit/non-defining-use.rs
+++ b/tests/ui/impl-trait/rpit/non-defining-use.rs
@@ -6,8 +6,7 @@ fn foo<T>() -> impl Sized {
 
 fn bar<T>(val: T) -> impl Sized {
     let _: u8 = bar(0u8);
-    //~^ ERROR concrete type differs from previous defining opaque type use
-    //~| ERROR expected generic type parameter, found `u8`
+    //~^ ERROR expected generic type parameter, found `u8`
     val
 }
 
diff --git a/tests/ui/impl-trait/rpit/non-defining-use.stderr b/tests/ui/impl-trait/rpit/non-defining-use.stderr
index 10a8232e646d0..c2b1b0f824976 100644
--- a/tests/ui/impl-trait/rpit/non-defining-use.stderr
+++ b/tests/ui/impl-trait/rpit/non-defining-use.stderr
@@ -1,31 +1,19 @@
 error[E0792]: expected generic type parameter, found `u8`
-  --> $DIR/non-defining-use.rs:4:12
+  --> $DIR/non-defining-use.rs:4:17
    |
 LL | fn foo<T>() -> impl Sized {
    |        - this generic parameter must be used with a generic type parameter
 LL |     let _: () = foo::<u8>();
-   |            ^^
-
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/non-defining-use.rs:8:17
-   |
-LL |     let _: u8 = bar(0u8);
-   |                 ^^^^^^^^ expected `T`, got `u8`
-   |
-note: previous use here
-  --> $DIR/non-defining-use.rs:7:22
-   |
-LL | fn bar<T>(val: T) -> impl Sized {
-   |                      ^^^^^^^^^^
+   |                 ^^^^^^^^^^^
 
 error[E0792]: expected generic type parameter, found `u8`
-  --> $DIR/non-defining-use.rs:8:12
+  --> $DIR/non-defining-use.rs:8:17
    |
 LL | fn bar<T>(val: T) -> impl Sized {
    |        - this generic parameter must be used with a generic type parameter
 LL |     let _: u8 = bar(0u8);
-   |            ^^
+   |                 ^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/transmute/in-defining-scope.stderr b/tests/ui/impl-trait/transmute/in-defining-scope.stderr
index 7172bfdf0d7e2..3153569517835 100644
--- a/tests/ui/impl-trait/transmute/in-defining-scope.stderr
+++ b/tests/ui/impl-trait/transmute/in-defining-scope.stderr
@@ -9,6 +9,31 @@ note: ...which requires computing type of opaque `foo::{opaque#0}`...
    |
 LL | fn foo() -> impl Sized {
    |             ^^^^^^^^^^
+note: ...which requires borrow-checking `foo`...
+  --> $DIR/in-defining-scope.rs:6:1
+   |
+LL | fn foo() -> impl Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires promoting constants in MIR for `foo`...
+  --> $DIR/in-defining-scope.rs:6:1
+   |
+LL | fn foo() -> impl Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires checking if `foo` contains FFI-unwind calls...
+  --> $DIR/in-defining-scope.rs:6:1
+   |
+LL | fn foo() -> impl Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `foo`...
+  --> $DIR/in-defining-scope.rs:6:1
+   |
+LL | fn foo() -> impl Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires match-checking `foo`...
+  --> $DIR/in-defining-scope.rs:6:1
+   |
+LL | fn foo() -> impl Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `foo`...
   --> $DIR/in-defining-scope.rs:6:1
    |
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
index 0711af1cad405..11b57ad98c458 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
@@ -1,18 +1,5 @@
-error: item does not constrain `A::{opaque#0}`
-  --> $DIR/two_tait_defining_each_other2.rs:12:4
-   |
-LL | fn muh(x: A) -> B {
-   |    ^^^
-   |
-   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
-note: this opaque type is supposed to be constrained
-  --> $DIR/two_tait_defining_each_other2.rs:6:10
-   |
-LL | type A = impl Foo;
-   |          ^^^^^^^^
-
 error: opaque type's hidden type cannot be another opaque type from the same scope
-  --> $DIR/two_tait_defining_each_other2.rs:15:5
+  --> $DIR/two_tait_defining_each_other2.rs:14:5
    |
 LL |     x // B's hidden type is A (opaquely)
    |     ^ one of the two opaque types used here has to be outside its defining scope
@@ -28,5 +15,5 @@ note: opaque type being used as hidden type
 LL | type A = impl Foo;
    |          ^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.rs b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
index a3223b07a7ed4..6c454bba5023f 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
@@ -10,8 +10,7 @@ trait Foo {}
 
 #[define_opaque(A, B)]
 fn muh(x: A) -> B {
-    //[current]~^ ERROR: item does not constrain `A::{opaque#0}`
-    //[next]~^^ ERROR: cannot satisfy `_ == A`
+    //[next]~^ ERROR: cannot satisfy `_ == A`
     x // B's hidden type is A (opaquely)
     //[current]~^ ERROR opaque type's hidden type cannot be another opaque type
 }
diff --git a/tests/crashes/132335.rs b/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs
similarity index 74%
rename from tests/crashes/132335.rs
rename to tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs
index 2294539cfcfa0..e5208e3e47d06 100644
--- a/tests/crashes/132335.rs
+++ b/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs
@@ -1,5 +1,8 @@
-//@ known-bug: #132335
+// Regression test for #132335. This previously ICE'd due to ambiguity
+// in MIR typeck.
+
 //@ compile-flags: -Znext-solver=globally --crate-type lib --edition=2018
+//@ check-pass
 use core::future::Future;
 use core::pin::Pin;
 
diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr
index 5625cb24d4265..ff0afd319d90d 100644
--- a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr
+++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr
@@ -1,34 +1,54 @@
-error: unconstrained opaque type
+error: item does not constrain `ex1::Tait1::{opaque#0}`
+  --> $DIR/no-define-in-wf-check.rs:21:8
+   |
+LL |     fn foo(x: Tait1) -> impl Sized {
+   |        ^^^
+   |
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/no-define-in-wf-check.rs:19:18
    |
 LL |     type Tait1 = impl Sized;
    |                  ^^^^^^^^^^
-   |
-   = note: `Tait1` must be used in combination with a concrete type within the same crate
 
-error: unconstrained opaque type
+error: item does not constrain `ex2::Tait1::{opaque#0}`
+  --> $DIR/no-define-in-wf-check.rs:31:8
+   |
+LL |     fn foo(x: Tait1) -> Tait2 {
+   |        ^^^
+   |
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/no-define-in-wf-check.rs:28:18
    |
 LL |     type Tait1 = impl Sized;
    |                  ^^^^^^^^^^
-   |
-   = note: `Tait1` must be used in combination with a concrete type within the same crate
 
-error: unconstrained opaque type
+error: item does not constrain `ex3::Tait1::{opaque#0}`
+  --> $DIR/no-define-in-wf-check.rs:43:8
+   |
+LL |     fn foo(x: Tait1) -> Tait2 {
+   |        ^^^
+   |
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/no-define-in-wf-check.rs:38:18
    |
 LL |     type Tait1 = impl Sized;
    |                  ^^^^^^^^^^
-   |
-   = note: `Tait1` must be used in combination with a concrete type within the same crate
 
-error: unconstrained opaque type
+error: item does not constrain `ex4::Tait1::{opaque#0}`
+  --> $DIR/no-define-in-wf-check.rs:64:8
+   |
+LL |     fn foo(x: Tait1) -> Tait2 {
+   |        ^^^
+   |
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/no-define-in-wf-check.rs:50:18
    |
 LL |     type Tait1 = impl Sized;
    |                  ^^^^^^^^^^
-   |
-   = note: `Tait1` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs
index 31d07d89d8dc8..26c17edeb93bb 100644
--- a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs
+++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs
@@ -17,38 +17,37 @@ mod ex0 {
 }
 mod ex1 {
     type Tait1 = impl Sized;
-    //[current]~^ ERROR unconstrained opaque type
     #[define_opaque(Tait1)]
     fn foo(x: Tait1) -> impl Sized {
+        //[current]~^ ERROR item does not constrain `ex1::Tait1::{opaque#0}`
         let () = x;
     }
 }
 
 mod ex2 {
     type Tait1 = impl Sized;
-    //[current]~^ ERROR unconstrained opaque type
     type Tait2 = impl Sized;
     #[define_opaque(Tait1, Tait2)]
     fn foo(x: Tait1) -> Tait2 {
+        //[current]~^ ERROR item does not constrain `ex2::Tait1::{opaque#0}`
         let () = x;
     }
 }
 
 mod ex3 {
     type Tait1 = impl Sized;
-    //[current]~^ ERROR unconstrained opaque type
     trait Something<T> {}
     impl<T, U> Something<U> for T {}
     type Tait2 = impl Something<Tait1>;
     #[define_opaque(Tait1, Tait2)]
     fn foo(x: Tait1) -> Tait2 {
+        //[current]~^ ERROR item does not constrain `ex3::Tait1::{opaque#0}`
         let () = x;
     }
 }
 
 mod ex4 {
     type Tait1 = impl Sized;
-    //[current]~^ ERROR unconstrained opaque type
     trait Trait<U> {
         type Assoc;
     }
@@ -63,6 +62,7 @@ mod ex4 {
     type Tait2 = impl Trait<(), Assoc = impl Trait<Tait1>>;
     #[define_opaque(Tait1, Tait2)]
     fn foo(x: Tait1) -> Tait2 {
+        //[current]~^ ERROR item does not constrain `ex4::Tait1::{opaque#0}`
         let () = x;
     }
 }
diff --git a/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs b/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs
new file mode 100644
index 0000000000000..8388751fea64d
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs
@@ -0,0 +1,11 @@
+// Regression test for #137751. This previously ICE'd as
+// we did not provide the hidden type of the opaque inside
+// of the async block. This caused borrowck of the recursive
+// call to ICE.
+
+//@ compile-flags: --edition=2021
+//@ check-pass
+async fn test() {
+    Box::pin(test()).await;
+}
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs
index b6870b1645096..5c93bd14d3252 100644
--- a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs
+++ b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs
@@ -12,7 +12,6 @@ pub enum UninhabitedVariants {
 
 #[define_opaque(Alias)]
 fn uwu(x: UninhabitedVariants) {
-    //~^ ERROR item does not constrain
     match x {}
     //~^ ERROR non-exhaustive patterns
 }
diff --git a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr
index 59909197e7bc3..72fae0173cbb5 100644
--- a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr
+++ b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr
@@ -26,21 +26,8 @@ help: add missing generic argument
 LL |     Tuple(Alias<U>),
    |                +++
 
-error: item does not constrain `Alias::{opaque#0}`
-  --> $DIR/bad-tait-no-substs.rs:14:4
-   |
-LL | fn uwu(x: UninhabitedVariants) {
-   |    ^^^
-   |
-   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
-note: this opaque type is supposed to be constrained
-  --> $DIR/bad-tait-no-substs.rs:5:21
-   |
-LL | type Alias<'a, U> = impl Trait<U>;
-   |                     ^^^^^^^^^^^^^
-
 error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` not covered
-  --> $DIR/bad-tait-no-substs.rs:16:11
+  --> $DIR/bad-tait-no-substs.rs:15:11
    |
 LL |     match x {}
    |           ^ pattern `UninhabitedVariants::Tuple(_)` not covered
@@ -60,7 +47,7 @@ LL +         UninhabitedVariants::Tuple(_) => todo!(),
 LL ~     }
    |
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0004, E0106, E0107.
 For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.rs b/tests/ui/type-alias-impl-trait/bound_reduction2.rs
index 78288caffefe3..fadc2beba7191 100644
--- a/tests/ui/type-alias-impl-trait/bound_reduction2.rs
+++ b/tests/ui/type-alias-impl-trait/bound_reduction2.rs
@@ -14,6 +14,6 @@ impl<W> Trait<W> for () {}
 
 #[define_opaque(Foo)]
 fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
-    ()
     //~^ ERROR expected generic type parameter, found `<T as TraitWithAssoc>::Assoc`
+    ()
 }
diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr
index 289826cc1d02e..53b20d61025f0 100644
--- a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr
+++ b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr
@@ -1,11 +1,11 @@
 error[E0792]: expected generic type parameter, found `<T as TraitWithAssoc>::Assoc`
-  --> $DIR/bound_reduction2.rs:17:5
+  --> $DIR/bound_reduction2.rs:16:46
    |
 LL | type Foo<V> = impl Trait<V>;
    |          - this generic parameter must be used with a generic type parameter
 ...
-LL |     ()
-   |     ^^
+LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+   |                                              ^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs b/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs
index e56f60a6693e6..b5a9bf4a59f36 100644
--- a/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs
+++ b/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs
@@ -9,7 +9,7 @@ fn get_one<'a>(a: *mut &'a str) -> Opaque<'a> {
 
 #[define_opaque(Opaque)]
 fn get_iter<'a>() -> impl IntoIterator<Item = Opaque<'a>> {
-    //~^ ERROR:  item does not constrain
+    //~^ ERROR item does not constrain `Opaque::{opaque#0}`
     None::<Opaque<'static>>
 }
 
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses.rs b/tests/ui/type-alias-impl-trait/different_defining_uses.rs
index 246f255e8fcff..547696b83da56 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses.rs
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses.rs
@@ -12,6 +12,6 @@ fn foo() -> Foo {
 
 #[define_opaque(Foo)]
 fn bar() -> Foo {
+    //~^ ERROR concrete type differs
     42i32
-    //~^ ERROR concrete type differs from previous
 }
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr
index 9a7f4b416f4b4..36d7e33dca0aa 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses.rs:15:5
+  --> $DIR/different_defining_uses.rs:14:13
    |
-LL |     42i32
-   |     ^^^^^ expected `&'static str`, got `i32`
+LL | fn bar() -> Foo {
+   |             ^^^ expected `&str`, got `i32`
    |
 note: previous use here
-  --> $DIR/different_defining_uses.rs:10:5
+  --> $DIR/different_defining_uses.rs:9:13
    |
-LL |     ""
-   |     ^^
+LL | fn foo() -> Foo {
+   |             ^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
index e8c40e8bf926c..bbbc2086bdf5c 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
@@ -12,7 +12,6 @@ fn foo<'a, 'b>() -> Tait<'a> {
     }
     let x: Tait<'a> = ();
     x
-    //~^ ERROR concrete type differs from previous defining opaque type use
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
index d4bd397592477..4d7dd6b2ad5f5 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
@@ -1,15 +1,3 @@
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses_never_type-2.rs:14:5
-   |
-LL |     x
-   |     ^ expected `i32`, got `()`
-   |
-note: previous use here
-  --> $DIR/different_defining_uses_never_type-2.rs:9:31
-   |
-LL |             let y: Tait<'b> = 1i32;
-   |                               ^^^^
-
 error: concrete type differs from previous defining opaque type use
   --> $DIR/different_defining_uses_never_type-2.rs:9:31
    |
@@ -17,10 +5,10 @@ LL |             let y: Tait<'b> = 1i32;
    |                               ^^^^ expected `()`, got `i32`
    |
 note: previous use here
-  --> $DIR/different_defining_uses_never_type-2.rs:8:14
+  --> $DIR/different_defining_uses_never_type-2.rs:14:5
    |
-LL |         if { return } {
-   |              ^^^^^^
+LL |     x
+   |     ^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr
index cb12fddd9a037..eb9001cc6244c 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr
@@ -5,10 +5,10 @@ LL |             let y: Tait<U> = 1i32;
    |                              ^^^^ expected `()`, got `i32`
    |
 note: previous use here
-  --> $DIR/different_defining_uses_never_type-3.rs:13:22
+  --> $DIR/different_defining_uses_never_type-3.rs:14:5
    |
-LL |     let x: Tait<T> = ();
-   |                      ^^
+LL |     x
+   |     ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
index 38afa3cbcd0ec..0914dd1c546e4 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
@@ -2,13 +2,13 @@ error: concrete type differs from previous defining opaque type use
   --> $DIR/different_defining_uses_never_type.rs:14:13
    |
 LL | fn bar() -> Foo {
-   |             ^^^ expected `&'static str`, got `()`
+   |             ^^^ expected `&str`, got `()`
    |
 note: previous use here
-  --> $DIR/different_defining_uses_never_type.rs:10:5
+  --> $DIR/different_defining_uses_never_type.rs:9:13
    |
-LL |     ""
-   |     ^^
+LL | fn foo() -> Foo {
+   |             ^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr
index 21fab8180633f..78a9f6b636543 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr
@@ -5,10 +5,10 @@ LL | fn two() -> Tait { Two::<()>(todo!()) }
    |             ^^^^ expected `One`, got `Two<()>`
    |
 note: previous use here
-  --> $DIR/different_defining_uses_never_type3.rs:7:20
+  --> $DIR/different_defining_uses_never_type3.rs:7:13
    |
 LL | fn one() -> Tait { One }
-   |                    ^^^
+   |             ^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs
index 726820bbd5a14..c2578297006b3 100644
--- a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs
+++ b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs
@@ -31,7 +31,6 @@ impl<F: for<'a> Fn(&'a ()) -> StateWidget<'a>> Widget<()> for StatefulWidget<F>
 fn new_stateful_widget<F: for<'a> Fn(&'a ()) -> StateWidget<'a>>(build: F) -> impl Widget<()> {
     //~^ ERROR item does not constrain
     StatefulWidget(build)
-    //~^ ERROR expected generic lifetime parameter, found `'a`
 }
 
 fn main() {
diff --git a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr
index 4f5c65adab9cf..dee729e1f9f40 100644
--- a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr
+++ b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr
@@ -24,17 +24,8 @@ note: this opaque type is supposed to be constrained
 LL | type StateWidget<'a> = impl Widget<&'a ()>;
    |                        ^^^^^^^^^^^^^^^^^^^
 
-error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/failed-to-normalize-ice-99945.rs:33:5
-   |
-LL | type StateWidget<'a> = impl Widget<&'a ()>;
-   |                  -- this generic parameter must be used with a generic lifetime parameter
-...
-LL |     StatefulWidget(build)
-   |     ^^^^^^^^^^^^^^^^^^^^^
-
 error[E0308]: mismatched types
-  --> $DIR/failed-to-normalize-ice-99945.rs:38:29
+  --> $DIR/failed-to-normalize-ice-99945.rs:37:29
    |
 LL | type StateWidget<'a> = impl Widget<&'a ()>;
    |                        ------------------- the expected opaque type
@@ -45,7 +36,6 @@ LL |     new_stateful_widget(|_| ()).make_state();
    = note: expected opaque type `StateWidget<'_>`
                 found unit type `()`
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0308, E0792.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs
index d55a9a376b9fb..41fb6fe8587fc 100644
--- a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs
+++ b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs
@@ -11,6 +11,6 @@ fn my_iter<T>(t: T) -> MyIter<T> {
 
 #[define_opaque(MyIter)]
 fn my_iter2<T>(t: T) -> MyIter<T> {
-    Some(t).into_iter()
     //~^ ERROR concrete type differs from previous
+    Some(t).into_iter()
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr
index 6d3279144d8fb..b4be8542163fe 100644
--- a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_different_defining_uses.rs:14:5
+  --> $DIR/generic_different_defining_uses.rs:13:25
    |
-LL |     Some(t).into_iter()
-   |     ^^^^^^^^^^^^^^^^^^^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
+LL | fn my_iter2<T>(t: T) -> MyIter<T> {
+   |                         ^^^^^^^^^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
    |
 note: previous use here
-  --> $DIR/generic_different_defining_uses.rs:9:5
+  --> $DIR/generic_different_defining_uses.rs:8:24
    |
-LL |     std::iter::once(t)
-   |     ^^^^^^^^^^^^^^^^^^
+LL | fn my_iter<T>(t: T) -> MyIter<T> {
+   |                        ^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
index e8ed38a24ceb0..6e791a3bdb9dc 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
@@ -20,8 +20,8 @@ type TwoConsts<const X: usize, const Y: usize> = impl Debug;
 
 #[define_opaque(TwoTys)]
 fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
-    t
     //~^ ERROR non-defining opaque type use in defining scope
+    t
 }
 
 #[define_opaque(TwoLifetimes)]
@@ -32,6 +32,6 @@ fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
 
 #[define_opaque(TwoConsts)]
 fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
-    t
     //~^ ERROR non-defining opaque type use in defining scope
+    t
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
index 3e048c8138d04..022e534df1a29 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:23:5
+  --> $DIR/generic_duplicate_param_use.rs:22:30
    |
-LL |     t
-   |     ^
+LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
+   |                              ^^^^^^^^^^^^
    |
 note: type used multiple times
   --> $DIR/generic_duplicate_param_use.rs:15:13
@@ -23,10 +23,10 @@ LL | type TwoLifetimes<'a, 'b> = impl Debug;
    |                   ^^  ^^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:35:5
+  --> $DIR/generic_duplicate_param_use.rs:34:50
    |
-LL |     t
-   |     ^
+LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
+   |                                                  ^^^^^^^^^^^^^^^
    |
 note: constant used multiple times
   --> $DIR/generic_duplicate_param_use.rs:19:16
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 f732b23339618..873c7b614b69d 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
@@ -14,6 +14,6 @@ fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
 
 #[define_opaque(Two)]
 fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
-    u
     //~^ ERROR concrete type differs
+    u
 }
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 b0a1bd77f8578..3f5f2c93c59d2 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,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use3.rs:17:5
+  --> $DIR/generic_duplicate_param_use3.rs:16:38
    |
-LL |     u
-   |     ^ expected `T`, got `U`
+LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+   |                                      ^^^^^^^^^ expected `T`, got `U`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use3.rs:12:5
+  --> $DIR/generic_duplicate_param_use3.rs:11:36
    |
-LL |     t
-   |     ^
+LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+   |                                    ^^^^^^^^^
 
 error: aborting due to 1 previous error
 
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 d450bef57581d..1d4d3ab737f35 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
@@ -14,6 +14,6 @@ fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
 
 #[define_opaque(Two)]
 fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-    (u, t)
     //~^ ERROR concrete type differs
+    (u, t)
 }
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 b8a2a93741614..59b37a8b792c0 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,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use5.rs:17:5
+  --> $DIR/generic_duplicate_param_use5.rs:16:45
    |
-LL |     (u, t)
-   |     ^^^^^^ expected `(T, U)`, got `(U, T)`
+LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+   |                                             ^^^^^^^^^ expected `(T, U)`, got `(U, T)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use5.rs:12:5
+  --> $DIR/generic_duplicate_param_use5.rs:11:43
    |
-LL |     (t, u)
-   |     ^^^^^^
+LL | fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+   |                                           ^^^^^^^^^
 
 error: aborting due to 1 previous error
 
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 24d03b9e60d24..961e2910dbeec 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
@@ -14,6 +14,6 @@ fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
 
 #[define_opaque(Two)]
 fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-    (u, t)
     //~^ ERROR concrete type differs
+    (u, t)
 }
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 983e58d3c7024..0940d6f541fc3 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,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use6.rs:17:5
+  --> $DIR/generic_duplicate_param_use6.rs:16:52
    |
-LL |     (u, t)
-   |     ^^^^^^ expected `(T, T)`, got `(U, T)`
+LL | fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+   |                                                    ^^^^^^^^^ expected `(T, T)`, got `(U, T)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use6.rs:12:5
+  --> $DIR/generic_duplicate_param_use6.rs:11:50
    |
-LL |     (t, t)
-   |     ^^^^^^
+LL | fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+   |                                                  ^^^^^^^^^
 
 error: aborting due to 1 previous error
 
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 03057c8478253..d01cc7ff04eb4 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
@@ -13,6 +13,6 @@ fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
 
 #[define_opaque(Two)]
 fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
-    (u, 4u32)
     //~^ concrete type differs
+    (u, 4u32)
 }
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 48c98c1e2b15c..f9615d455d134 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,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use8.rs:16:5
+  --> $DIR/generic_duplicate_param_use8.rs:15:45
    |
-LL |     (u, 4u32)
-   |     ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
+LL | fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
+   |                                             ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use8.rs:11:5
+  --> $DIR/generic_duplicate_param_use8.rs:10:43
    |
-LL |     (t, 4u32)
-   |     ^^^^^^^^^
+LL | fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
+   |                                           ^^^^^^^^^
 
 error: aborting due to 1 previous error
 
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 74176550ab242..ec03ff1675edb 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
@@ -18,6 +18,6 @@ fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
 
 #[define_opaque(Two)]
 fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-    (t, u, 42)
     //~^ ERROR concrete type differs
+    (t, u, 42)
 }
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 542324c949f19..df9984cd07392 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,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use9.rs:21:5
+  --> $DIR/generic_duplicate_param_use9.rs:20:45
    |
-LL |     (t, u, 42)
-   |     ^^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
+LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+   |                                             ^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use9.rs:16:5
+  --> $DIR/generic_duplicate_param_use9.rs:15:49
    |
-LL |     (t, u, T::BAR)
-   |     ^^^^^^^^^^^^^^
+LL | fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
+   |                                                 ^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
index 7791410294c0d..cf38c93bd921e 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
@@ -14,8 +14,8 @@ type OneConst<const X: usize> = impl Debug;
 
 #[define_opaque(OneTy)]
 fn concrete_ty() -> OneTy<u32> {
-    5u32
     //~^ ERROR: expected generic type parameter, found `u32`
+    5u32
 }
 
 #[define_opaque(OneLifetime)]
@@ -26,6 +26,6 @@ fn concrete_lifetime() -> OneLifetime<'static> {
 
 #[define_opaque(OneConst)]
 fn concrete_const() -> OneConst<{ 123 }> {
-    7u32
     //~^ ERROR: expected generic constant parameter, found `123`
+    7u32
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
index 1b0ce7cc619f5..71e415271ee82 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
@@ -1,11 +1,11 @@
 error[E0792]: expected generic type parameter, found `u32`
-  --> $DIR/generic_nondefining_use.rs:17:5
+  --> $DIR/generic_nondefining_use.rs:16:21
    |
 LL | type OneTy<T> = impl Debug;
    |            - this generic parameter must be used with a generic type parameter
 ...
-LL |     5u32
-   |     ^^^^
+LL | fn concrete_ty() -> OneTy<u32> {
+   |                     ^^^^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'static`
   --> $DIR/generic_nondefining_use.rs:23:5
@@ -17,13 +17,13 @@ LL |     6u32
    |     ^^^^
 
 error[E0792]: expected generic constant parameter, found `123`
-  --> $DIR/generic_nondefining_use.rs:29:5
+  --> $DIR/generic_nondefining_use.rs:28:24
    |
 LL | type OneConst<const X: usize> = impl Debug;
    |               -------------- this generic parameter must be used with a generic constant parameter
 ...
-LL |     7u32
-   |     ^^^^
+LL | fn concrete_const() -> OneConst<{ 123 }> {
+   |                        ^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/generic_not_used.rs b/tests/ui/type-alias-impl-trait/generic_not_used.rs
index 6042cdd30a940..f270f65f43ed9 100644
--- a/tests/ui/type-alias-impl-trait/generic_not_used.rs
+++ b/tests/ui/type-alias-impl-trait/generic_not_used.rs
@@ -7,6 +7,6 @@ type WrongGeneric<T: 'static> = impl 'static;
 
 #[define_opaque(WrongGeneric)]
 fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
-    v
     //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
+    v
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_not_used.stderr b/tests/ui/type-alias-impl-trait/generic_not_used.stderr
index 5fe2fefcecfd0..a480040006eaf 100644
--- a/tests/ui/type-alias-impl-trait/generic_not_used.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_not_used.stderr
@@ -5,10 +5,10 @@ LL | type WrongGeneric<T: 'static> = impl 'static;
    |                                 ^^^^^^^^^^^^
 
 error: type parameter `V` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/generic_not_used.rs:10:5
+  --> $DIR/generic_not_used.rs:9:57
    |
-LL |     v
-   |     ^
+LL | fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
+   |                                                         ^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
index cbd8150d11775..4b4db8ec2ed3b 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
@@ -10,18 +10,15 @@ use std::future::Future;
 type FutNothing<'a> = impl 'a + Future<Output = ()>;
 
 async fn operation(_: &mut ()) -> () {
-    //~^ ERROR: concrete type differs from previous
     call(operation).await
-    //~^ ERROR: expected generic lifetime parameter, found `'any`
+    //~^ ERROR: concrete type differs from previous
 }
 
 #[define_opaque(FutNothing)]
 async fn call<F>(_f: F)
-//~^ ERROR item does not constrain
+//~^ ERROR item does not constrain `FutNothing::{opaque#0}`
 where
     for<'any> F: FnMut(&'any mut ()) -> FutNothing<'any>,
-{
-    //~^ ERROR: expected generic lifetime parameter, found `'any`
-}
+{}
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
index 2c0be0cbcdca6..2aacf9698379b 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
@@ -1,5 +1,5 @@
 error: item does not constrain `FutNothing::{opaque#0}`
-  --> $DIR/hkl_forbidden4.rs:19:10
+  --> $DIR/hkl_forbidden4.rs:18:10
    |
 LL | async fn call<F>(_f: F)
    |          ^^^^
@@ -12,37 +12,16 @@ LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/hkl_forbidden4.rs:12:1
+  --> $DIR/hkl_forbidden4.rs:13:5
    |
-LL | async fn operation(_: &mut ()) -> () {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}`
+LL |     call(operation).await
+   |     ^^^^^^^^^^^^^^^ expected `{async fn body of operation()}`, got `FutNothing<'_>`
    |
 note: previous use here
-  --> $DIR/hkl_forbidden4.rs:14:5
-   |
-LL |     call(operation).await
-   |     ^^^^^^^^^^^^^^^
-
-error[E0792]: expected generic lifetime parameter, found `'any`
-  --> $DIR/hkl_forbidden4.rs:14:5
+  --> $DIR/hkl_forbidden4.rs:12:1
    |
 LL | async fn operation(_: &mut ()) -> () {
-   |                       - this generic parameter must be used with a generic lifetime parameter
-LL |
-LL |     call(operation).await
-   |     ^^^^^^^^^^^^^^^
-
-error[E0792]: expected generic lifetime parameter, found `'any`
-  --> $DIR/hkl_forbidden4.rs:23:1
-   |
-LL |   type FutNothing<'a> = impl 'a + Future<Output = ()>;
-   |                   -- this generic parameter must be used with a generic lifetime parameter
-...
-LL | / {
-LL | |
-LL | | }
-   | |_^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.stderr b/tests/ui/type-alias-impl-trait/in-where-clause.stderr
index 114cac64573ce..9fcb26c20a682 100644
--- a/tests/ui/type-alias-impl-trait/in-where-clause.stderr
+++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr
@@ -20,6 +20,41 @@ error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}`
 LL | type Bar = impl Sized;
    |            ^^^^^^^^^^
    |
+note: ...which requires borrow-checking `foo`...
+  --> $DIR/in-where-clause.rs:9:1
+   |
+LL | / fn foo() -> Bar
+LL | | where
+LL | |     Bar: Send,
+   | |______________^
+note: ...which requires promoting constants in MIR for `foo`...
+  --> $DIR/in-where-clause.rs:9:1
+   |
+LL | / fn foo() -> Bar
+LL | | where
+LL | |     Bar: Send,
+   | |______________^
+note: ...which requires checking if `foo` contains FFI-unwind calls...
+  --> $DIR/in-where-clause.rs:9:1
+   |
+LL | / fn foo() -> Bar
+LL | | where
+LL | |     Bar: Send,
+   | |______________^
+note: ...which requires building MIR for `foo`...
+  --> $DIR/in-where-clause.rs:9:1
+   |
+LL | / fn foo() -> Bar
+LL | | where
+LL | |     Bar: Send,
+   | |______________^
+note: ...which requires match-checking `foo`...
+  --> $DIR/in-where-clause.rs:9:1
+   |
+LL | / fn foo() -> Bar
+LL | | where
+LL | |     Bar: Send,
+   | |______________^
 note: ...which requires type-checking `foo`...
   --> $DIR/in-where-clause.rs:9:1
    |
diff --git a/tests/ui/type-alias-impl-trait/issue-109054.rs b/tests/ui/type-alias-impl-trait/issue-109054.rs
index 0c9304a42f355..a8bb5ee3301fb 100644
--- a/tests/ui/type-alias-impl-trait/issue-109054.rs
+++ b/tests/ui/type-alias-impl-trait/issue-109054.rs
@@ -18,7 +18,7 @@ impl std::ops::Deref for CallMe {
             async move { *val * 2 }
         }
 
-        &inner //~ ERROR: expected generic lifetime parameter, found `'_`
+        &inner
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/issue-109054.stderr b/tests/ui/type-alias-impl-trait/issue-109054.stderr
index 919b0a287c4f3..5ce6f54e5f9ad 100644
--- a/tests/ui/type-alias-impl-trait/issue-109054.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-109054.stderr
@@ -11,15 +11,5 @@ note: this opaque type is supposed to be constrained
 LL | type ReturnType<'a> = impl std::future::Future<Output = u32> + 'a;
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/issue-109054.rs:21:9
-   |
-LL | type ReturnType<'a> = impl std::future::Future<Output = u32> + 'a;
-   |                 -- this generic parameter must be used with a generic lifetime parameter
-...
-LL |         &inner
-   |         ^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
index 3062e55dc4909..c8db9fdfc579e 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
@@ -9,6 +9,31 @@ note: ...which requires computing type of opaque `Bug::{opaque#0}`...
    |
 LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
    |                  ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires borrow-checking `CONST_BUG`...
+  --> $DIR/issue-53092-2.rs:8:1
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires promoting constants in MIR for `CONST_BUG`...
+  --> $DIR/issue-53092-2.rs:8:1
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const checking `CONST_BUG`...
+  --> $DIR/issue-53092-2.rs:8:1
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `CONST_BUG`...
+  --> $DIR/issue-53092-2.rs:8:1
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires match-checking `CONST_BUG`...
+  --> $DIR/issue-53092-2.rs:8:1
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `CONST_BUG`...
   --> $DIR/issue-53092-2.rs:8:1
    |
diff --git a/tests/ui/type-alias-impl-trait/issue-53598.rs b/tests/ui/type-alias-impl-trait/issue-53598.rs
index e3e2787b66bb4..3262c69cf5a4e 100644
--- a/tests/ui/type-alias-impl-trait/issue-53598.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53598.rs
@@ -17,8 +17,8 @@ impl Foo for S2 {
     type Item = impl Debug;
 
     fn foo<T: Debug>(_: T) -> Self::Item {
-        S::<T>(Default::default())
         //~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+        S::<T>(Default::default())
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/issue-53598.stderr b/tests/ui/type-alias-impl-trait/issue-53598.stderr
index a31aabedba542..f1dd3c69443cf 100644
--- a/tests/ui/type-alias-impl-trait/issue-53598.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-53598.stderr
@@ -1,8 +1,8 @@
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-53598.rs:20:9
+  --> $DIR/issue-53598.rs:19:31
    |
-LL |         S::<T>(Default::default())
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn foo<T: Debug>(_: T) -> Self::Item {
+   |                               ^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/issue-60564.rs b/tests/ui/type-alias-impl-trait/issue-60564.rs
index f28258b3b2277..ae9a4d0267037 100644
--- a/tests/ui/type-alias-impl-trait/issue-60564.rs
+++ b/tests/ui/type-alias-impl-trait/issue-60564.rs
@@ -18,8 +18,8 @@ where
     type BitsIter = IterBitsIter<T, E, u8>;
     #[define_opaque(IterBitsIter)]
     fn iter_bits(self, n: u8) -> Self::BitsIter {
-        (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
         //~^ ERROR expected generic type parameter, found `u8`
+        (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/issue-60564.stderr b/tests/ui/type-alias-impl-trait/issue-60564.stderr
index 6aaed7d4296a5..bfe8d92fedd3a 100644
--- a/tests/ui/type-alias-impl-trait/issue-60564.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-60564.stderr
@@ -1,11 +1,11 @@
 error[E0792]: expected generic type parameter, found `u8`
-  --> $DIR/issue-60564.rs:21:9
+  --> $DIR/issue-60564.rs:20:34
    |
 LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
    |                         - this generic parameter must be used with a generic type parameter
 ...
-LL |         (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
+   |                                  ^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
index 178aa5cf34535..e58b2d4aa6098 100644
--- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
@@ -1,11 +1,11 @@
 error[E0792]: expected generic type parameter, found `()`
-  --> $DIR/issue-68368-non-defining-use-2.rs:10:29
+  --> $DIR/issue-68368-non-defining-use-2.rs:10:15
    |
 LL | type Alias<'a, U> = impl Trait<U>;
    |                - this generic parameter must be used with a generic type parameter
 ...
 LL | fn f<'a>() -> Alias<'a, ()> {}
-   |                             ^^
+   |               ^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
index bfbd506a7a5c0..3ec19e206008d 100644
--- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
@@ -1,11 +1,11 @@
 error[E0792]: expected generic type parameter, found `()`
-  --> $DIR/issue-68368-non-defining-use.rs:10:29
+  --> $DIR/issue-68368-non-defining-use.rs:10:15
    |
 LL | type Alias<'a, U> = impl Trait<U>;
    |                - this generic parameter must be used with a generic type parameter
 ...
 LL | fn f<'a>() -> Alias<'a, ()> {}
-   |                             ^^
+   |               ^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs
index 18afc54dbdc6e..9e0c8fbbd269a 100644
--- a/tests/ui/type-alias-impl-trait/issue-77179.rs
+++ b/tests/ui/type-alias-impl-trait/issue-77179.rs
@@ -6,9 +6,9 @@ type Pointer<T> = impl std::ops::Deref<Target = T>;
 
 #[define_opaque(Pointer)]
 fn test() -> Pointer<_> {
-    //~^ ERROR: the placeholder `_` is not allowed within types
+    //~^ ERROR the placeholder `_` is not allowed within types
+    //~| ERROR expected generic type parameter, found `i32`
     Box::new(1)
-    //~^ ERROR: expected generic type parameter, found `i32`
 }
 
 fn main() {
@@ -17,5 +17,5 @@ fn main() {
 
 extern "Rust" {
     fn bar() -> Pointer<_>;
-    //~^ ERROR: the placeholder `_` is not allowed within types
+    //~^ ERROR the placeholder `_` is not allowed within types
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr
index bc11283f32821..c0f197ec48c37 100644
--- a/tests/ui/type-alias-impl-trait/issue-77179.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr
@@ -1,3 +1,12 @@
+error[E0792]: expected generic type parameter, found `i32`
+  --> $DIR/issue-77179.rs:8:14
+   |
+LL | type Pointer<T> = impl std::ops::Deref<Target = T>;
+   |              - this generic parameter must be used with a generic type parameter
+...
+LL | fn test() -> Pointer<_> {
+   |              ^^^^^^^^^^
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/issue-77179.rs:8:22
    |
@@ -13,15 +22,6 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
 LL |     fn bar() -> Pointer<_>;
    |                         ^ not allowed in type signatures
 
-error[E0792]: expected generic type parameter, found `i32`
-  --> $DIR/issue-77179.rs:10:5
-   |
-LL | type Pointer<T> = impl std::ops::Deref<Target = T>;
-   |              - this generic parameter must be used with a generic type parameter
-...
-LL |     Box::new(1)
-   |     ^^^^^^^^^^^
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0121, E0792.
diff --git a/tests/ui/type-alias-impl-trait/multi-error.rs b/tests/ui/type-alias-impl-trait/multi-error.rs
index cb4ad4dc63372..2f42f14d4cb49 100644
--- a/tests/ui/type-alias-impl-trait/multi-error.rs
+++ b/tests/ui/type-alias-impl-trait/multi-error.rs
@@ -16,8 +16,8 @@ impl Foo for () {
     type Baz = impl Sized;
     fn foo() -> (Self::Bar<u32>, Self::Baz) {
         //~^ ERROR non-defining opaque type use
+        //~| ERROR expected generic type parameter, found `u32`
         ((), ())
-        //~^ ERROR expected generic type parameter
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/multi-error.stderr b/tests/ui/type-alias-impl-trait/multi-error.stderr
index 761f01b32acf4..3cb267c7c2615 100644
--- a/tests/ui/type-alias-impl-trait/multi-error.stderr
+++ b/tests/ui/type-alias-impl-trait/multi-error.stderr
@@ -11,13 +11,13 @@ LL |     type Bar<T> = impl Sized;
    |                   ^^^^^^^^^^
 
 error[E0792]: expected generic type parameter, found `u32`
-  --> $DIR/multi-error.rs:19:9
+  --> $DIR/multi-error.rs:17:17
    |
 LL |     type Bar<T> = impl Sized;
    |              - this generic parameter must be used with a generic type parameter
-...
-LL |         ((), ())
-   |         ^^^^^^^^
+LL |     type Baz = impl Sized;
+LL |     fn foo() -> (Self::Bar<u32>, Self::Baz) {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs
index 3dd2d53fe3d88..839ac47162382 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs
@@ -8,7 +8,8 @@ type Y<A, B> = impl std::fmt::Debug;
 
 #[define_opaque(Y)]
 fn g<A, B>() -> (Y<A, B>, Y<B, A>) {
-    (42_i64, 60) //~ ERROR concrete type differs from previous defining opaque type use
+    //~^ ERROR concrete type differs from previous defining opaque type use
+    (42_i64, 60)
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr
index d6558576577f4..e044cbe819e8c 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/multiple-def-uses-in-one-fn-infer.rs:11:5
+  --> $DIR/multiple-def-uses-in-one-fn-infer.rs:10:17
    |
-LL |     (42_i64, 60)
-   |     ^^^^^^^^^^^^
-   |     |
-   |     expected `i64`, got `i32`
-   |     this expression supplies two conflicting concrete types for the same opaque type
+LL | fn g<A, B>() -> (Y<A, B>, Y<B, A>) {
+   |                 ^^^^^^^^^^^^^^^^^^
+   |                 |
+   |                 expected `i64`, got `i32`
+   |                 this expression supplies two conflicting concrete types for the same opaque type
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
index 1357d772be17c..aa31901fc5ef3 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
@@ -8,8 +8,8 @@ type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
 
 #[define_opaque(X)]
 fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
-    (a.clone(), a)
     //~^ ERROR concrete type differs from previous defining opaque type
+    (a.clone(), a)
 }
 
 fn main() {
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
index 15e9b6fbf7615..8d79b37f0f5f3 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/multiple-def-uses-in-one-fn2.rs:11:5
+  --> $DIR/multiple-def-uses-in-one-fn2.rs:10:63
    |
-LL |     (a.clone(), a)
-   |     ^^^^^^^^^^^^^^
-   |     |
-   |     expected `A`, got `B`
-   |     this expression supplies two conflicting concrete types for the same opaque type
+LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+   |                                                               ^^^^^^^^^^^^^^^^^^
+   |                                                               |
+   |                                                               expected `A`, got `B`
+   |                                                               this expression supplies two conflicting concrete types for the same opaque type
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
index 5adae476bfe29..57fa86f5eb75d 100644
--- a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
+++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
@@ -12,7 +12,7 @@ pub fn get_foo() -> Foo {
 
 #[define_opaque(Foot, Foo)]
 pub fn get_foot(_: Foo) -> Foot {
-    //~^ ERROR: item does not constrain `Foo::{opaque#0}`
+    //~^ ERROR item does not constrain `Foo::{opaque#0}`
     get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type
 }
 
diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.stderr b/tests/ui/type-alias-impl-trait/non-defining-method.stderr
index 49a393ca745bb..22f173b5be9fb 100644
--- a/tests/ui/type-alias-impl-trait/non-defining-method.stderr
+++ b/tests/ui/type-alias-impl-trait/non-defining-method.stderr
@@ -11,12 +11,12 @@ LL |     type Bar<T> = impl Sized;
    |                   ^^^^^^^^^^
 
 error[E0792]: expected generic type parameter, found `u32`
-  --> $DIR/non-defining-method.rs:16:32
+  --> $DIR/non-defining-method.rs:16:17
    |
 LL |     type Bar<T> = impl Sized;
    |              - this generic parameter must be used with a generic type parameter
 LL |     fn foo() -> Self::Bar<u32> {}
-   |                                ^^
+   |                 ^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
index 75cc5948e93c7..53e312e3e64ff 100644
--- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
+++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
@@ -1,26 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/normalize-hidden-types.rs:27:20
+  --> $DIR/normalize-hidden-types.rs:38:22
    |
-LL |     fn define() -> Opaque {
-   |                    ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
+LL |     fn define_2() -> Opaque { dyn_hoops::<u8>(0) }
+   |                      ^^^^^^ expected `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`, got `*const dyn FnOnce(())`
    |
 note: previous use here
-  --> $DIR/normalize-hidden-types.rs:28:9
-   |
-LL |         dyn_hoops::<_>(0)
-   |         ^^^^^^^^^^^^^^^^^
-
-error: concrete type differs from previous defining opaque type use
   --> $DIR/normalize-hidden-types.rs:36:22
    |
 LL |     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
-   |                      ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
-   |
-note: previous use here
-  --> $DIR/normalize-hidden-types.rs:36:31
-   |
-LL |     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
-   |                               ^^^^^^^^^^^^^^^^^
+   |                      ^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/normalize-hidden-types.rs:47:25
@@ -38,18 +26,6 @@ LL |         let _: Opaque = dyn_hoops::<u8>(0);
    = help: consider constraining the associated type `<u8 as Trait>::Gat<'_>` to `()` or calling a method that returns `<u8 as Trait>::Gat<'_>`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/normalize-hidden-types.rs:57:25
-   |
-LL |         let _: Opaque = dyn_hoops::<_>(0);
-   |                         ^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
-   |
-note: previous use here
-  --> $DIR/normalize-hidden-types.rs:58:9
-   |
-LL |         None
-   |         ^^^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
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 d20622dc2e05e..cfbbf9ce487cb 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
@@ -23,8 +23,8 @@ impl Bar for u32 {
 
 #[define_opaque(Two)]
 fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
-    (t, <U as Bar>::FOO)
     //~^ ERROR concrete type differs
+    (t, <U as Bar>::FOO)
 }
 
 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 d90e4531879b9..37d28b3883c27 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,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/not_a_defining_use.rs:26:5
+  --> $DIR/not_a_defining_use.rs:25:36
    |
-LL |     (t, <U as Bar>::FOO)
-   |     ^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
+LL | fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
+   |                                    ^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
    |
 note: previous use here
-  --> $DIR/not_a_defining_use.rs:11:5
+  --> $DIR/not_a_defining_use.rs:10:32
    |
-LL |     (t, 5i8)
-   |     ^^^^^^^^
+LL | fn three<T: Debug, U>(t: T) -> Two<T, U> {
+   |                                ^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs b/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs
index cfd7e1bf38235..94597adfed04f 100644
--- a/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs
+++ b/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs
@@ -13,7 +13,8 @@ pub fn add(
     n: Diff,
     m: Diff,
 ) -> Diff {
-    move |x: usize| m(n(x)) //~ ERROR: concrete type differs
+    //~^ ERROR concrete type differs
+    move |x: usize| m(n(x))
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr
index 1a8ab21940498..59ff991761247 100644
--- a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr
+++ b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/recursive-fn-tait.rs:16:5
+  --> $DIR/recursive-fn-tait.rs:15:6
    |
-LL |     move |x: usize| m(n(x))
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ expected `{closure@$DIR/recursive-fn-tait.rs:8:5: 8:16}`, got `{closure@$DIR/recursive-fn-tait.rs:16:5: 16:20}`
+LL | ) -> Diff {
+   |      ^^^^ expected `{closure@$DIR/recursive-fn-tait.rs:8:5: 8:16}`, got `{closure@$DIR/recursive-fn-tait.rs:17:5: 17:20}`
    |
 note: previous use here
-  --> $DIR/recursive-fn-tait.rs:8:5
+  --> $DIR/recursive-fn-tait.rs:7:18
    |
-LL |     |_: usize |loop {}
-   |     ^^^^^^^^^^^^^^^^^^
+LL | pub fn lift() -> Diff {
+   |                  ^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs
index 26ffd5c16a291..858f2a2feb678 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs
@@ -13,8 +13,8 @@ fn transform<S>() -> impl std::fmt::Display {
 }
 #[define_opaque(Op)]
 fn bad() -> Op {
-    transform::<Op>()
     //~^ ERROR concrete type differs from previous defining opaque type use
+    transform::<Op>()
 }
 
 fn main() {
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr
index 259f3b2b9f3dc..e527b5bc7f8f8 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/recursive-tait-conflicting-defn-2.rs:16:5
+  --> $DIR/recursive-tait-conflicting-defn-2.rs:15:13
    |
-LL |     transform::<Op>()
-   |     ^^^^^^^^^^^^^^^^^ expected `&'static &'static str`, got `impl std::fmt::Display`
+LL | fn bad() -> Op {
+   |             ^^ expected `&&str`, got `impl std::fmt::Display`
    |
 note: previous use here
-  --> $DIR/recursive-tait-conflicting-defn-2.rs:8:5
+  --> $DIR/recursive-tait-conflicting-defn-2.rs:7:13
    |
-LL |     &"hello world"
-   |     ^^^^^^^^^^^^^^
+LL | fn foo() -> Op {
+   |             ^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs
index c9e2773905d77..90581a98a3468 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs
@@ -23,10 +23,9 @@ pub fn test() -> TestImpl {
 
 #[define_opaque(TestImpl)]
 fn make_option2() -> Option<TestImpl> {
+    //~^ ERROR concrete type differs from previous defining opaque type use
     let inner = make_option().unwrap();
-
     Some(B { inner })
-    //~^ ERROR concrete type differs from previous defining opaque type use
 }
 
 fn make_option() -> Option<TestImpl> {
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr
index 47471c9728c4a..256f13b622179 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/recursive-tait-conflicting-defn.rs:28:5
+  --> $DIR/recursive-tait-conflicting-defn.rs:25:22
    |
-LL |     Some(B { inner })
-   |     ^^^^^^^^^^^^^^^^^ expected `A`, got `B<TestImpl>`
+LL | fn make_option2() -> Option<TestImpl> {
+   |                      ^^^^^^^^^^^^^^^^ expected `A`, got `B<TestImpl>`
    |
 note: previous use here
-  --> $DIR/recursive-tait-conflicting-defn.rs:21:5
+  --> $DIR/recursive-tait-conflicting-defn.rs:20:18
    |
-LL |     A
-   |     ^
+LL | pub fn test() -> TestImpl {
+   |                  ^^^^^^^^
 
 error: aborting due to 1 previous error