about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs3
-rw-r--r--compiler/rustc_borrowck/src/lib.rs3
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs19
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs7
-rw-r--r--compiler/rustc_infer/src/infer/at.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs15
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs9
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs50
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/mod.rs104
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs14
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs8
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs32
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs3
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs12
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs6
-rw-r--r--compiler/rustc_middle/src/ty/context.rs15
-rw-r--r--compiler/rustc_middle/src/ty/list.rs6
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs3
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs103
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs39
-rw-r--r--compiler/rustc_type_ir/src/debug.rs4
-rw-r--r--compiler/rustc_type_ir/src/infcx.rs2
-rw-r--r--compiler/rustc_type_ir/src/interner.rs1
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir60
-rw-r--r--tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir4
-rw-r--r--tests/mir-opt/building/issue_101867.main.built.after.mir4
-rw-r--r--tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir8
-rw-r--r--tests/mir-opt/issue_72181_1.main.built.after.mir4
-rw-r--r--tests/mir-opt/issue_99325.main.built.after.32bit.mir4
-rw-r--r--tests/mir-opt/issue_99325.main.built.after.64bit.mir4
-rw-r--r--tests/ui/impl-trait/different_where_bounds.rs27
-rw-r--r--tests/ui/impl-trait/equality-in-canonical-query.clone.stderr23
-rw-r--r--tests/ui/impl-trait/equality-in-canonical-query.rs11
-rw-r--r--tests/ui/impl-trait/nested-hkl-lifetime.rs32
-rw-r--r--tests/ui/impl-trait/nested-rpit-hrtb.rs2
-rw-r--r--tests/ui/impl-trait/nested-rpit-hrtb.stderr7
-rw-r--r--tests/ui/inference/issue-80409.no-compat.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs11
-rw-r--r--tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr23
-rw-r--r--tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs12
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs (renamed from tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs)6
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs (renamed from tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs)2
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs10
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs16
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr39
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr10
59 files changed, 470 insertions, 388 deletions
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index 31307ef1410..64726eacca7 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -4,7 +4,6 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::{Body, Promoted};
-use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::TyCtxt;
 use std::rc::Rc;
 
@@ -106,7 +105,7 @@ pub fn get_body_with_borrowck_facts(
     options: ConsumerOptions,
 ) -> BodyWithBorrowckFacts<'_> {
     let (input_body, promoted) = tcx.mir_promoted(def);
-    let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build();
+    let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build();
     let input_body: &Body<'_> = &input_body.borrow();
     let promoted: &IndexSlice<_, _> = &promoted.borrow();
     *super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap()
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 9c23c2f9e01..7fbf4c47ec8 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -32,7 +32,6 @@ use rustc_infer::infer::{
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
-use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt};
 use rustc_session::lint::builtin::UNUSED_MUT;
 use rustc_span::{Span, Symbol};
@@ -126,7 +125,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
         return tcx.arena.alloc(result);
     }
 
-    let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build();
+    let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build();
     let promoted: &IndexSlice<_, _> = &promoted.borrow();
     let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
     debug!("mir_borrowck done");
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 63b80445817..9f0e54febe4 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -7,7 +7,6 @@ use rustc_infer::infer::TyCtxtInferExt as _;
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
 use rustc_infer::traits::{Obligation, ObligationCause};
 use rustc_macros::extension;
-use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{GenericArgKind, GenericArgs};
@@ -133,6 +132,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
             let ty =
                 infcx.infer_opaque_definition_from_instantiation(opaque_type_key, concrete_type);
+
+            // Sometimes, when the hidden type is an inference variable, it can happen that
+            // the hidden type becomes the opaque type itself. In this case, this was an opaque
+            // usage of the opaque type and we can ignore it. This check is mirrored in typeck's
+            // writeback.
+            // FIXME(-Znext-solver): This should be unnecessary with the new solver.
+            if let ty::Alias(ty::Opaque, alias_ty) = ty.kind()
+                && alias_ty.def_id == opaque_type_key.def_id.to_def_id()
+                && alias_ty.args == opaque_type_key.args
+            {
+                continue;
+            }
             // Sometimes two opaque types are the same only after we remap the generic parameters
             // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
             // and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
@@ -321,13 +332,13 @@ fn check_opaque_type_well_formed<'tcx>(
         parent_def_id = tcx.local_parent(parent_def_id);
     }
 
-    // FIXME(-Znext-solver): We probably should use `DefiningAnchor::Bind(&[])`
+    // FIXME(-Znext-solver): We probably should use `&[]` instead of
     // and prepopulate this `InferCtxt` with known opaque values, rather than
-    // using the `Bind` anchor here. For now it's fine.
+    // allowing opaque types to be defined and checking them after the fact.
     let infcx = tcx
         .infer_ctxt()
         .with_next_trait_solver(next_trait_solver)
-        .with_opaque_type_inference(DefiningAnchor::bind(tcx, parent_def_id))
+        .with_opaque_type_inference(parent_def_id)
         .build();
     let ocx = ObligationCtxt::new(&infcx);
     let identity_args = GenericArgs::identity_for_item(tcx, def_id);
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index f28b786e4f7..a950f10787b 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -39,6 +39,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         let TypeOpOutput { output, constraints, error_info } =
             op.fully_perform(self.infcx, locations.span(self.body))?;
+        if cfg!(debug_assertions) {
+            let data = self.infcx.take_and_reset_region_constraints();
+            if !data.is_empty() {
+                panic!("leftover region constraints: {data:#?}");
+            }
+        }
 
         debug!(?output, ?constraints);
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 739a7086992..8d4ae10d4bf 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -13,7 +13,7 @@ use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
 use rustc_infer::traits::{Obligation, TraitEngineExt as _};
 use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
 use rustc_middle::middle::stability::EvalResult;
-use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode};
+use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
@@ -345,10 +345,7 @@ fn check_opaque_meets_bounds<'tcx>(
     };
     let param_env = tcx.param_env(defining_use_anchor);
 
-    let infcx = tcx
-        .infer_ctxt()
-        .with_opaque_type_inference(DefiningAnchor::bind(tcx, defining_use_anchor))
-        .build();
+    let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build();
     let ocx = ObligationCtxt::new(&infcx);
 
     let args = match *origin {
@@ -1567,7 +1564,7 @@ pub(super) fn check_coroutine_obligations(
         .ignoring_regions()
         // Bind opaque types to type checking root, as they should have been checked by borrowck,
         // but may show up in some cases, like when (root) obligations are stalled in the new solver.
-        .with_opaque_type_inference(DefiningAnchor::bind(tcx, typeck.hir_owner.def_id))
+        .with_opaque_type_inference(typeck.hir_owner.def_id)
         .build();
 
     let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 85d04f7d1c4..f1e82543a99 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -730,8 +730,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             for ty in ret_ty.walk() {
                 if let ty::GenericArgKind::Type(ty) = ty.unpack()
                     && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind()
-                    && let Some(def_id) = def_id.as_local()
-                    && self.opaque_type_origin(def_id).is_some()
+                    && self.can_define_opaque_ty(def_id)
                 {
                     return None;
                 }
diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
index 88777bf5b02..694ddd0e3e8 100644
--- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
+++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
@@ -5,7 +5,6 @@ use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::HirIdMap;
 use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
-use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefIdMap;
@@ -78,11 +77,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
     pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
         let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner;
 
-        let infcx = tcx
-            .infer_ctxt()
-            .ignoring_regions()
-            .with_opaque_type_inference(DefiningAnchor::bind(tcx, def_id))
-            .build();
+        let infcx = tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(def_id).build();
         let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
 
         TypeckRootCtxt {
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 94088216c02..f2222eec76a 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -75,7 +75,7 @@ impl<'tcx> InferCtxt<'tcx> {
     pub fn fork_with_intercrate(&self, intercrate: bool) -> Self {
         Self {
             tcx: self.tcx,
-            defining_use_anchor: self.defining_use_anchor,
+            defining_opaque_types: self.defining_opaque_types,
             considering_regions: self.considering_regions,
             skip_leak_check: self.skip_leak_check,
             inner: self.inner.clone(),
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 6421a3f038c..825c3bf82fc 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -42,7 +42,7 @@ impl<'tcx> InferCtxt<'tcx> {
         V: TypeFoldable<TyCtxt<'tcx>>,
     {
         let (param_env, value) = value.into_parts();
-        let param_env = self.tcx.canonical_param_env_cache.get_or_insert(
+        let mut param_env = self.tcx.canonical_param_env_cache.get_or_insert(
             self.tcx,
             param_env,
             query_state,
@@ -59,6 +59,8 @@ impl<'tcx> InferCtxt<'tcx> {
             },
         );
 
+        param_env.defining_opaque_types = self.defining_opaque_types;
+
         Canonicalizer::canonicalize_with_base(
             param_env,
             value,
@@ -541,6 +543,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
             max_universe: ty::UniverseIndex::ROOT,
             variables: List::empty(),
             value: (),
+            defining_opaque_types: infcx.map(|i| i.defining_opaque_types).unwrap_or_default(),
         };
         Canonicalizer::canonicalize_with_base(
             base,
@@ -610,7 +613,15 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
             .max()
             .unwrap_or(ty::UniverseIndex::ROOT);
 
-        Canonical { max_universe, variables: canonical_variables, value: (base.value, out_value) }
+        assert!(
+            !infcx.is_some_and(|infcx| infcx.defining_opaque_types != base.defining_opaque_types)
+        );
+        Canonical {
+            max_universe,
+            variables: canonical_variables,
+            value: (base.value, out_value),
+            defining_opaque_types: base.defining_opaque_types,
+        }
     }
 
     /// Creates a canonical variable replacing `kind` from the input,
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 9d2e065afa3..b948067e750 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -505,12 +505,9 @@ impl<'tcx> InferCtxt<'tcx> {
             let b = instantiate_value(self.tcx, &result_args, b);
             debug!(?a, ?b, "constrain opaque type");
             // We use equate here instead of, for example, just registering the
-            // opaque type's hidden value directly, because we may be instantiating
-            // a query response that was canonicalized in an InferCtxt that had
-            // a different defining anchor. In that case, we may have inferred
-            // `NonLocalOpaque := LocalOpaque` but can only instantiate it in
-            // the other direction as `LocalOpaque := NonLocalOpaque`. Using eq
-            // here allows us to try both directions (in `InferCtxt::handle_opaque_type`).
+            // opaque type's hidden value directly, because the hidden type may have been an inference
+            // variable that got constrained to the opaque type itself. In that case we want to equate
+            // the generic args of the opaque with the generic params of its hidden type version.
             obligations.extend(
                 self.at(cause, param_env)
                     .eq(
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 6e5ed0a31cb..0b8061104ab 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -34,7 +34,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
 use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
 use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::traits::{select, DefiningAnchor};
+use rustc_middle::traits::select;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BoundVarReplacerDelegate;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@@ -243,18 +243,8 @@ impl<'tcx> InferCtxtInner<'tcx> {
 pub struct InferCtxt<'tcx> {
     pub tcx: TyCtxt<'tcx>,
 
-    /// The `DefId` of the item in whose context we are performing inference or typeck.
-    /// It is used to check whether an opaque type use is a defining use.
-    ///
-    /// If it is `DefiningAnchor::Bubble`, we can't resolve opaque types here and need to bubble up
-    /// the obligation. This frequently happens for
-    /// short lived InferCtxt within queries. The opaque type obligations are forwarded
-    /// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
-    ///
-    /// Its default value is `DefiningAnchor::Bind(&[])`, which means no opaque types may be defined.
-    /// This way it is easier to catch errors that
-    /// might come up during inference or typeck.
-    pub defining_use_anchor: DefiningAnchor<'tcx>,
+    /// The `DefIds` of the opaque types that may have their hidden types constrained.
+    defining_opaque_types: &'tcx ty::List<LocalDefId>,
 
     /// Whether this inference context should care about region obligations in
     /// the root universe. Most notably, this is used during hir typeck as region
@@ -401,6 +391,10 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
     fn probe_ct_var(&self, vid: ConstVid) -> Option<ty::Const<'tcx>> {
         self.probe_const_var(vid).ok()
     }
+
+    fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
+        self.defining_opaque_types
+    }
 }
 
 /// See the `error_reporting` module for more details.
@@ -615,7 +609,7 @@ impl fmt::Display for FixupError {
 /// Used to configure inference contexts before their creation.
 pub struct InferCtxtBuilder<'tcx> {
     tcx: TyCtxt<'tcx>,
-    defining_use_anchor: DefiningAnchor<'tcx>,
+    defining_opaque_types: &'tcx ty::List<LocalDefId>,
     considering_regions: bool,
     skip_leak_check: bool,
     /// Whether we are in coherence mode.
@@ -630,7 +624,7 @@ impl<'tcx> TyCtxt<'tcx> {
     fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
         InferCtxtBuilder {
             tcx: self,
-            defining_use_anchor: DefiningAnchor::Bind(ty::List::empty()),
+            defining_opaque_types: ty::List::empty(),
             considering_regions: true,
             skip_leak_check: false,
             intercrate: false,
@@ -646,8 +640,16 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     /// It is only meant to be called in two places, for typeck
     /// (via `Inherited::build`) and for the inference context used
     /// in mir borrowck.
-    pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor<'tcx>) -> Self {
-        self.defining_use_anchor = defining_use_anchor;
+    pub fn with_opaque_type_inference(mut self, defining_anchor: LocalDefId) -> Self {
+        self.defining_opaque_types = self.tcx.opaque_types_defined_by(defining_anchor);
+        self
+    }
+
+    pub fn with_defining_opaque_types(
+        mut self,
+        defining_opaque_types: &'tcx ty::List<LocalDefId>,
+    ) -> Self {
+        self.defining_opaque_types = defining_opaque_types;
         self
     }
 
@@ -679,14 +681,14 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     /// the bound values in `C` to their instantiated values in `V`
     /// (in other words, `S(C) = V`).
     pub fn build_with_canonical<T>(
-        &mut self,
+        self,
         span: Span,
         canonical: &Canonical<'tcx, T>,
     ) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>)
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        let infcx = self.build();
+        let infcx = self.with_defining_opaque_types(canonical.defining_opaque_types).build();
         let (value, args) = infcx.instantiate_canonical(span, canonical);
         (infcx, value, args)
     }
@@ -694,7 +696,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     pub fn build(&mut self) -> InferCtxt<'tcx> {
         let InferCtxtBuilder {
             tcx,
-            defining_use_anchor,
+            defining_opaque_types,
             considering_regions,
             skip_leak_check,
             intercrate,
@@ -702,7 +704,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
         } = *self;
         InferCtxt {
             tcx,
-            defining_use_anchor,
+            defining_opaque_types,
             considering_regions,
             skip_leak_check,
             inner: RefCell::new(InferCtxtInner::new()),
@@ -1230,6 +1232,12 @@ impl<'tcx> InferCtxt<'tcx> {
         self.inner.borrow().opaque_type_storage.opaque_types.clone()
     }
 
+    #[inline(always)]
+    pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
+        let Some(id) = id.into().as_local() else { return false };
+        self.defining_opaque_types.contains(&id)
+    }
+
     pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
         self.resolve_vars_if_possible(t).to_string()
     }
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index 01430e830e5..d32515425c4 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -4,11 +4,10 @@ use crate::errors::OpaqueHiddenTypeDiag;
 use crate::infer::{InferCtxt, InferOk};
 use crate::traits::{self, PredicateObligation};
 use hir::def_id::{DefId, LocalDefId};
-use hir::OpaqueTyOrigin;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
-use rustc_middle::traits::{DefiningAnchor, ObligationCause};
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::GenericArgKind;
@@ -54,16 +53,13 @@ impl<'tcx> InferCtxt<'tcx> {
         }
 
         let mut obligations = vec![];
-        let replace_opaque_type = |def_id: DefId| {
-            def_id.as_local().is_some_and(|def_id| self.opaque_type_origin(def_id).is_some())
-        };
         let value = value.fold_with(&mut BottomUpFolder {
             tcx: self.tcx,
             lt_op: |lt| lt,
             ct_op: |ct| ct,
             ty_op: |ty| match *ty.kind() {
                 ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })
-                    if replace_opaque_type(def_id) && !ty.has_escaping_bound_vars() =>
+                    if self.can_define_opaque_ty(def_id) && !ty.has_escaping_bound_vars() =>
                 {
                     let def_span = self.tcx.def_span(def_id);
                     let span = if span.contains(def_span) { def_span } else { span };
@@ -106,56 +102,52 @@ impl<'tcx> InferCtxt<'tcx> {
                         b,
                     ));
                 }
-                match self.defining_use_anchor {
-                    DefiningAnchor::Bind(_) => {
-                        // Check that this is `impl Trait` type is
-                        // declared by `parent_def_id` -- i.e., one whose
-                        // value we are inferring. At present, this is
-                        // always true during the first phase of
-                        // type-check, but not always true later on during
-                        // NLL. Once we support named opaque types more fully,
-                        // this same scenario will be able to arise during all phases.
-                        //
-                        // Here is an example using type alias `impl Trait`
-                        // that indicates the distinction we are checking for:
-                        //
-                        // ```rust
-                        // mod a {
-                        //   pub type Foo = impl Iterator;
-                        //   pub fn make_foo() -> Foo { .. }
-                        // }
-                        //
-                        // mod b {
-                        //   fn foo() -> a::Foo { a::make_foo() }
-                        // }
-                        // ```
-                        //
-                        // Here, the return type of `foo` references an
-                        // `Opaque` indeed, but not one whose value is
-                        // presently being inferred. You can get into a
-                        // similar situation with closure return types
-                        // today:
-                        //
-                        // ```rust
-                        // fn foo() -> impl Iterator { .. }
-                        // fn bar() {
-                        //     let x = || foo(); // returns the Opaque assoc with `foo`
-                        // }
-                        // ```
-                        if self.opaque_type_origin(def_id).is_none() {
-                            return None;
-                        }
-                    }
-                    DefiningAnchor::Bubble => {}
+                // Check that this is `impl Trait` type is
+                // declared by `parent_def_id` -- i.e., one whose
+                // value we are inferring. At present, this is
+                // always true during the first phase of
+                // type-check, but not always true later on during
+                // NLL. Once we support named opaque types more fully,
+                // this same scenario will be able to arise during all phases.
+                //
+                // Here is an example using type alias `impl Trait`
+                // that indicates the distinction we are checking for:
+                //
+                // ```rust
+                // mod a {
+                //   pub type Foo = impl Iterator;
+                //   pub fn make_foo() -> Foo { .. }
+                // }
+                //
+                // mod b {
+                //   fn foo() -> a::Foo { a::make_foo() }
+                // }
+                // ```
+                //
+                // Here, the return type of `foo` references an
+                // `Opaque` indeed, but not one whose value is
+                // presently being inferred. You can get into a
+                // similar situation with closure return types
+                // today:
+                //
+                // ```rust
+                // fn foo() -> impl Iterator { .. }
+                // fn bar() {
+                //     let x = || foo(); // returns the Opaque assoc with `foo`
+                // }
+                // ```
+                if !self.can_define_opaque_ty(def_id) {
+                    return None;
                 }
+
                 if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
                     // We could accept this, but there are various ways to handle this situation, and we don't
                     // want to make a decision on it right now. Likely this case is so super rare anyway, that
                     // no one encounters it in practice.
                     // It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
                     // where it is of no concern, so we only check for TAITs.
-                    if let Some(OpaqueTyOrigin::TyAlias { .. }) =
-                        b_def_id.as_local().and_then(|b_def_id| self.opaque_type_origin(b_def_id))
+                    if self.can_define_opaque_ty(b_def_id)
+                        && self.tcx.is_type_alias_impl_trait(b_def_id)
                     {
                         self.tcx.dcx().emit_err(OpaqueHiddenTypeDiag {
                             span: cause.span,
@@ -367,20 +359,6 @@ impl<'tcx> InferCtxt<'tcx> {
             op: |r| self.member_constraint(opaque_type_key, span, concrete_ty, r, &choice_regions),
         });
     }
-
-    /// Returns the origin of the opaque type `def_id` if we're currently
-    /// in its defining scope.
-    #[instrument(skip(self), level = "trace", ret)]
-    pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
-        let defined_opaque_types = match self.defining_use_anchor {
-            DefiningAnchor::Bubble => return None,
-            DefiningAnchor::Bind(bind) => bind,
-        };
-
-        let origin = self.tcx.opaque_type_origin(def_id);
-
-        defined_opaque_types.contains(&def_id).then_some(origin)
-    }
 }
 
 /// Visitor that requires that (almost) all regions in the type visited outlive
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index acea89e4aab..62d7b7c28d1 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -153,11 +153,6 @@ pub struct QueryResponse<'tcx, R> {
     pub var_values: CanonicalVarValues<'tcx>,
     pub region_constraints: QueryRegionConstraints<'tcx>,
     pub certainty: Certainty,
-    /// List of opaque types which we tried to compare to another type.
-    /// Inside the query we don't know yet whether the opaque type actually
-    /// should get its hidden type inferred. So we bubble the opaque type
-    /// and the type it was compared against upwards and let the query caller
-    /// handle it.
     pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
     pub value: R,
 }
@@ -330,6 +325,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> {
                 max_universe: ty::UniverseIndex::ROOT,
                 variables: List::empty(),
                 value: key,
+                defining_opaque_types: ty::List::empty(),
             };
         }
 
@@ -340,6 +336,14 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> {
         match self.map.borrow().entry(key) {
             Entry::Occupied(e) => {
                 let (canonical, var_values) = e.get();
+                if cfg!(debug_assertions) {
+                    let mut state = state.clone();
+                    let rerun_canonical = canonicalize_op(tcx, key, &mut state);
+                    assert_eq!(rerun_canonical, *canonical);
+                    let OriginalQueryValues { var_values: rerun_var_values, universe_map } = state;
+                    assert_eq!(universe_map.len(), 1);
+                    assert_eq!(**var_values, *rerun_var_values);
+                }
                 state.var_values.extend_from_slice(var_values);
                 *canonical
             }
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 8cb4ee7bd41..6555a687152 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -338,10 +338,11 @@ macro_rules! define_callbacks {
 
                 pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache<Erase<$V>>;
 
-                // Ensure that keys grow no larger than 64 bytes
+                // Ensure that keys grow no larger than 72 bytes by accident.
+                // Increase this limit if necessary, but do try to keep the size low if possible
                 #[cfg(all(any(target_arch = "x86_64", target_arch="aarch64"), target_pointer_width = "64"))]
                 const _: () = {
-                    if mem::size_of::<Key<'static>>() > 64 {
+                    if mem::size_of::<Key<'static>>() > 72 {
                         panic!("{}", concat!(
                             "the query `",
                             stringify!($name),
@@ -352,7 +353,8 @@ macro_rules! define_callbacks {
                     }
                 };
 
-                // Ensure that values grow no larger than 64 bytes
+                // Ensure that values grow no larger than 64 bytes by accident.
+                // Increase this limit if necessary, but do try to keep the size low if possible
                 #[cfg(all(any(target_arch = "x86_64", target_arch="aarch64"), target_pointer_width = "64"))]
                 const _: () = {
                     if mem::size_of::<Value<'static>>() > 64 {
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index ee816791919..d51e86c909c 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -12,8 +12,8 @@ pub mod util;
 use crate::infer::canonical::Canonical;
 use crate::mir::ConstraintCategory;
 use crate::ty::abstract_const::NotConstEvaluatable;
+use crate::ty::GenericArgsRef;
 use crate::ty::{self, AdtKind, Ty};
-use crate::ty::{GenericArgsRef, TyCtxt};
 
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, Diag, EmissionGuarantee};
@@ -997,33 +997,3 @@ pub enum CodegenObligationError {
     Unimplemented,
     FulfillmentError,
 }
-
-/// Defines the treatment of opaque types in a given inference context.
-///
-/// This affects both what opaques are allowed to be defined, but also whether
-/// opaques are replaced with inference vars eagerly in the old solver (e.g.
-/// in projection, and in the signature during function type-checking).
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
-pub enum DefiningAnchor<'tcx> {
-    /// Define opaques which are in-scope of the current item being analyzed.
-    /// Also, eagerly replace these opaque types in `replace_opaque_types_with_inference_vars`.
-    ///
-    /// If the list is empty, do not allow any opaques to be defined. This is used to catch type mismatch
-    /// errors when handling opaque types, and also should be used when we would
-    /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode).
-    Bind(&'tcx ty::List<LocalDefId>),
-    /// In contexts where we don't currently know what opaques are allowed to be
-    /// defined, such as (old solver) canonical queries, we will simply allow
-    /// opaques to be defined, but "bubble" them up in the canonical response or
-    /// otherwise treat them to be handled later.
-    ///
-    /// We do not eagerly replace opaque types in `replace_opaque_types_with_inference_vars`,
-    /// which may affect what predicates pass and fail in the old trait solver.
-    Bubble,
-}
-
-impl<'tcx> DefiningAnchor<'tcx> {
-    pub fn bind(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
-        Self::Bind(tcx.opaque_types_defined_by(item))
-    }
-}
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index 6dcea2aaff1..13504c6ae93 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -4,7 +4,7 @@ use rustc_span::def_id::DefId;
 
 use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints};
 use crate::traits::query::NoSolution;
-use crate::traits::{Canonical, DefiningAnchor};
+use crate::traits::Canonical;
 use crate::ty::{
     self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable,
     TypeVisitor,
@@ -114,7 +114,6 @@ impl MaybeCause {
 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
 pub struct QueryInput<'tcx, T> {
     pub goal: Goal<'tcx, T>,
-    pub anchor: DefiningAnchor<'tcx>,
     pub predefined_opaques_in_body: PredefinedOpaques<'tcx>,
 }
 
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 7db64504f85..95d1e08b58b 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -45,7 +45,7 @@ impl UpvarId {
 
 /// Information describing the capture of an upvar. This is computed
 /// during `typeck`, specifically by `regionck`.
-#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)]
+#[derive(Eq, PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable, Hash)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub enum UpvarCapture {
     /// Upvar is captured by value. This is always true when the
@@ -73,7 +73,7 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<hir::HirId, MinCaptureLis
 pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>;
 
 /// A composite describing a `Place` that is captured by a closure.
-#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
+#[derive(Eq, PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable, Hash)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct CapturedPlace<'tcx> {
     /// Name and span where the binding happens.
@@ -192,7 +192,7 @@ impl<'tcx> CapturedPlace<'tcx> {
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct ClosureTypeInfo<'tcx> {
     user_provided_sig: ty::CanonicalPolyFnSig<'tcx>,
-    captures: &'tcx [&'tcx ty::CapturedPlace<'tcx>],
+    captures: &'tcx ty::List<&'tcx ty::CapturedPlace<'tcx>>,
     kind_origin: Option<&'tcx (Span, HirPlace<'tcx>)>,
 }
 
@@ -201,7 +201,7 @@ fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo
     let typeck_results = tcx.typeck(def);
     let user_provided_sig = typeck_results.user_provided_sigs[&def];
     let captures = typeck_results.closure_min_captures_flattened(def);
-    let captures = tcx.arena.alloc_from_iter(captures);
+    let captures = tcx.mk_captures_from_iter(captures);
     let hir_id = tcx.local_def_id_to_hir_id(def);
     let kind_origin = typeck_results.closure_kind_origins().get(hir_id);
     ClosureTypeInfo { user_provided_sig, captures, kind_origin }
@@ -253,7 +253,7 @@ pub fn is_ancestor_or_same_capture(
 /// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
 /// for a particular capture as well as identifying the part of the source code
 /// that triggered this capture to occur.
-#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)]
+#[derive(Eq, PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable, Hash)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct CaptureInfo {
     /// Expr Id pointing to use that resulted in selecting the current capture kind
@@ -332,7 +332,7 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc
     curr_string
 }
 
-#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)]
+#[derive(Eq, Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable, Hash)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub enum BorrowKind {
     /// Data must be immutable and is aliasable.
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 0209c2dcc98..c0effe9804c 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -455,6 +455,12 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Lo
     }
 }
 
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for &'tcx ty::List<LocalDefId> {
+    fn decode(d: &mut D) -> Self {
+        RefDecodable::decode(d)
+    }
+}
+
 impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
     for ty::List<(VariantIdx, FieldIdx)>
 {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 2a6449a5246..e1a8adca9da 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -85,6 +85,7 @@ use std::ops::{Bound, Deref};
 #[allow(rustc::usage_of_ty_tykind)]
 impl<'tcx> Interner for TyCtxt<'tcx> {
     type DefId = DefId;
+    type DefiningOpaqueTypes = &'tcx ty::List<LocalDefId>;
     type AdtDef = ty::AdtDef<'tcx>;
     type GenericArgs = ty::GenericArgsRef<'tcx>;
     type GenericArg = ty::GenericArg<'tcx>;
@@ -168,6 +169,7 @@ pub struct CtxtInterners<'tcx> {
     predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>,
     fields: InternedSet<'tcx, List<FieldIdx>>,
     local_def_ids: InternedSet<'tcx, List<LocalDefId>>,
+    captures: InternedSet<'tcx, List<&'tcx ty::CapturedPlace<'tcx>>>,
     offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>,
 }
 
@@ -196,6 +198,7 @@ impl<'tcx> CtxtInterners<'tcx> {
             predefined_opaques_in_body: Default::default(),
             fields: Default::default(),
             local_def_ids: Default::default(),
+            captures: Default::default(),
             offset_of: Default::default(),
         }
     }
@@ -1912,6 +1915,7 @@ slice_interners!(
     bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
     fields: pub mk_fields(FieldIdx),
     local_def_ids: intern_local_def_ids(LocalDefId),
+    captures: intern_captures(&'tcx ty::CapturedPlace<'tcx>),
     offset_of: pub mk_offset_of((VariantIdx, FieldIdx)),
 );
 
@@ -2233,6 +2237,17 @@ impl<'tcx> TyCtxt<'tcx> {
         T::collect_and_apply(iter, |xs| self.mk_local_def_ids(xs))
     }
 
+    pub fn mk_captures_from_iter<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<
+                &'tcx ty::CapturedPlace<'tcx>,
+                &'tcx List<&'tcx ty::CapturedPlace<'tcx>>,
+            >,
+    {
+        T::collect_and_apply(iter, |xs| self.intern_captures(xs))
+    }
+
     pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
     where
         I: Iterator<Item = T>,
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 04e165c8a73..0db541899d2 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -55,6 +55,12 @@ struct ListSkeleton<H, T> {
     data: [T; 0],
 }
 
+impl<T> Default for &List<T> {
+    fn default() -> Self {
+        List::empty()
+    }
+}
+
 extern "C" {
     /// A dummy type used to force `List` to be unsized while not requiring
     /// references to it be wide pointers.
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 30c8fc5798f..6600b92fb31 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -69,7 +69,8 @@ impl<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> Canonicalizer<'a, Infc
 
         let (max_universe, variables) = canonicalizer.finalize();
 
-        Canonical { max_universe, variables, value }
+        let defining_opaque_types = infcx.defining_opaque_types();
+        Canonical { defining_opaque_types, max_universe, variables, value }
     }
 
     fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVars) {
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 7056288e758..0595e82b39e 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -1,5 +1,5 @@
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use crate::traits::{self, DefiningAnchor, ObligationCtxt, SelectionContext};
+use crate::traits::{self, ObligationCtxt, SelectionContext};
 
 use crate::traits::TraitEngineExt as _;
 use rustc_hir::def_id::DefId;
@@ -132,9 +132,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
         R: Debug + TypeFoldable<TyCtxt<'tcx>>,
         Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
     {
-        let (infcx, key, canonical_inference_vars) = self
-            .with_opaque_type_inference(DefiningAnchor::Bubble)
-            .build_with_canonical(DUMMY_SP, canonical_key);
+        let (infcx, key, canonical_inference_vars) =
+            self.build_with_canonical(DUMMY_SP, canonical_key);
         let ocx = ObligationCtxt::new(&infcx);
         let value = operation(&ocx, key)?;
         ocx.make_canonicalized_query_response(canonical_inference_vars, value)
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 4a4efb6884f..0b37163d597 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -68,7 +68,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             &mut orig_values,
             QueryInput {
                 goal,
-                anchor: self.infcx.defining_use_anchor,
                 predefined_opaques_in_body: self
                     .tcx()
                     .mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }),
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index 1739bd70e7b..0154aff12b6 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -1,5 +1,5 @@
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
 use rustc_infer::infer::at::ToTrace;
 use rustc_infer::infer::canonical::CanonicalVarValues;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -230,7 +230,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
             .infer_ctxt()
             .intercrate(intercrate)
             .with_next_trait_solver(true)
-            .with_opaque_type_inference(canonical_input.value.anchor)
             .build_with_canonical(DUMMY_SP, &canonical_input);
 
         let mut ecx = EvalCtxt {
@@ -936,8 +935,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         }
     }
 
-    pub(super) fn can_define_opaque_ty(&self, def_id: LocalDefId) -> bool {
-        self.infcx.opaque_type_origin(def_id).is_some()
+    pub(super) fn can_define_opaque_ty(&self, def_id: impl Into<DefId>) -> bool {
+        self.infcx.can_define_opaque_ty(def_id)
     }
 
     pub(super) fn insert_hidden_type(
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 8294a8a67b1..da5cd15a10d 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -316,5 +316,6 @@ fn response_no_constraints_raw<'tcx>(
             external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()),
             certainty,
         },
+        defining_opaque_types: Default::default(),
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 371668bf617..e522339358a 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -155,10 +155,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
             if matches!(goal.param_env.reveal(), Reveal::All)
                 || matches!(ecx.solver_mode(), SolverMode::Coherence)
-                || opaque_ty
-                    .def_id
-                    .as_local()
-                    .is_some_and(|def_id| ecx.can_define_opaque_ty(def_id))
+                || ecx.can_define_opaque_ty(opaque_ty.def_id)
             {
                 return Err(NoSolution);
             }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index faf218131b8..ae4cdb9258e 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -159,53 +159,70 @@ where
             .0);
         }
 
+        let mut error_info = None;
         let mut region_constraints = QueryRegionConstraints::default();
-        let (output, error_info, mut obligations, _) =
-            Q::fully_perform_into(self, infcx, &mut region_constraints, span).map_err(|_| {
-                infcx.dcx().span_delayed_bug(span, format!("error performing {self:?}"))
-            })?;
-
-        // Typically, instantiating NLL query results does not
-        // create obligations. However, in some cases there
-        // are unresolved type variables, and unify them *can*
-        // create obligations. In that case, we have to go
-        // fulfill them. We do this via a (recursive) query.
-        while !obligations.is_empty() {
-            trace!("{:#?}", obligations);
-            let mut progress = false;
-            for obligation in std::mem::take(&mut obligations) {
-                let obligation = infcx.resolve_vars_if_possible(obligation);
-                match ProvePredicate::fully_perform_into(
-                    obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
-                    infcx,
-                    &mut region_constraints,
-                    span,
-                ) {
-                    Ok(((), _, new, certainty)) => {
-                        obligations.extend(new);
-                        progress = true;
-                        if let Certainty::Ambiguous = certainty {
-                            obligations.push(obligation);
+
+        // HACK(type_alias_impl_trait): When moving an opaque type to hidden type mapping from the query to the current inferctxt,
+        // we sometimes end up with `Opaque<'a> = Opaque<'b>` instead of an actual hidden type. In that case we don't register a
+        // hidden type but just equate the lifetimes. Thus we need to scrape the region constraints even though we're also manually
+        // collecting region constraints via `region_constraints`.
+        let (mut output, _) = scrape_region_constraints(
+            infcx,
+            |_ocx| {
+                let (output, ei, mut obligations, _) =
+                    Q::fully_perform_into(self, infcx, &mut region_constraints, span)?;
+                error_info = ei;
+
+                // Typically, instantiating NLL query results does not
+                // create obligations. However, in some cases there
+                // are unresolved type variables, and unify them *can*
+                // create obligations. In that case, we have to go
+                // fulfill them. We do this via a (recursive) query.
+                while !obligations.is_empty() {
+                    trace!("{:#?}", obligations);
+                    let mut progress = false;
+                    for obligation in std::mem::take(&mut obligations) {
+                        let obligation = infcx.resolve_vars_if_possible(obligation);
+                        match ProvePredicate::fully_perform_into(
+                            obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
+                            infcx,
+                            &mut region_constraints,
+                            span,
+                        ) {
+                            Ok(((), _, new, certainty)) => {
+                                obligations.extend(new);
+                                progress = true;
+                                if let Certainty::Ambiguous = certainty {
+                                    obligations.push(obligation);
+                                }
+                            }
+                            Err(_) => obligations.push(obligation),
                         }
                     }
-                    Err(_) => obligations.push(obligation),
+                    if !progress {
+                        infcx.dcx().span_bug(
+                            span,
+                            format!("ambiguity processing {obligations:?} from {self:?}"),
+                        );
+                    }
                 }
-            }
-            if !progress {
-                infcx
-                    .dcx()
-                    .span_bug(span, format!("ambiguity processing {obligations:?} from {self:?}"));
-            }
-        }
-
-        Ok(TypeOpOutput {
-            output,
-            constraints: if region_constraints.is_empty() {
-                None
-            } else {
-                Some(infcx.tcx.arena.alloc(region_constraints))
+                Ok(output)
             },
-            error_info,
-        })
+            "fully_perform",
+            span,
+        )?;
+        output.error_info = error_info;
+        if let Some(constraints) = output.constraints {
+            region_constraints
+                .member_constraints
+                .extend(constraints.member_constraints.iter().cloned());
+            region_constraints.outlives.extend(constraints.outlives.iter().cloned());
+        }
+        output.constraints = if region_constraints.is_empty() {
+            None
+        } else {
+            Some(infcx.tcx.arena.alloc(region_constraints))
+        };
+        Ok(output)
     }
 }
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index ad18ef24984..06a5051956a 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -16,6 +16,8 @@ use crate::{Interner, PlaceholderLike, UniverseIndex};
 pub struct Canonical<I: Interner, V> {
     pub value: V,
     pub max_universe: UniverseIndex,
+    // FIXME(lcnr, oli-obk): try moving this into the query inputs instead
+    pub defining_opaque_types: I::DefiningOpaqueTypes,
     pub variables: I::CanonicalVars,
 }
 
@@ -44,8 +46,8 @@ impl<I: Interner, V> Canonical<I, V> {
     /// let b: Canonical<I, (T, Ty<I>)> = a.unchecked_map(|v| (v, ty));
     /// ```
     pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<I, W> {
-        let Canonical { max_universe, variables, value } = self;
-        Canonical { max_universe, variables, value: map_op(value) }
+        let Canonical { defining_opaque_types, max_universe, variables, value } = self;
+        Canonical { defining_opaque_types, max_universe, variables, value: map_op(value) }
     }
 
     /// Allows you to map the `value` of a canonical while keeping the same set of
@@ -54,8 +56,8 @@ impl<I: Interner, V> Canonical<I, V> {
     /// **WARNING:** This function is very easy to mis-use, hence the name! See
     /// the comment of [Canonical::unchecked_map] for more details.
     pub fn unchecked_rebind<W>(self, value: W) -> Canonical<I, W> {
-        let Canonical { max_universe, variables, value: _ } = self;
-        Canonical { max_universe, variables, value }
+        let Canonical { defining_opaque_types, max_universe, variables, value: _ } = self;
+        Canonical { defining_opaque_types, max_universe, variables, value }
     }
 }
 
@@ -63,28 +65,32 @@ impl<I: Interner, V: Eq> Eq for Canonical<I, V> {}
 
 impl<I: Interner, V: PartialEq> PartialEq for Canonical<I, V> {
     fn eq(&self, other: &Self) -> bool {
-        self.value == other.value
-            && self.max_universe == other.max_universe
-            && self.variables == other.variables
+        let Self { value, max_universe, variables, defining_opaque_types } = self;
+        *value == other.value
+            && *max_universe == other.max_universe
+            && *variables == other.variables
+            && *defining_opaque_types == other.defining_opaque_types
     }
 }
 
 impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { value, max_universe, variables, defining_opaque_types } = self;
         write!(
             f,
-            "Canonical {{ value: {}, max_universe: {:?}, variables: {:?} }}",
-            self.value, self.max_universe, self.variables
+            "Canonical {{ value: {value}, max_universe: {max_universe:?}, variables: {variables:?}, defining_opaque_types: {defining_opaque_types:?} }}",
         )
     }
 }
 
 impl<I: Interner, V: fmt::Debug> fmt::Debug for Canonical<I, V> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { value, max_universe, variables, defining_opaque_types } = self;
         f.debug_struct("Canonical")
-            .field("value", &self.value)
-            .field("max_universe", &self.max_universe)
-            .field("variables", &self.variables)
+            .field("value", &value)
+            .field("max_universe", &max_universe)
+            .field("variables", &variables)
+            .field("defining_opaque_types", &defining_opaque_types)
             .finish()
     }
 }
@@ -100,6 +106,7 @@ where
             value: self.value.try_fold_with(folder)?,
             max_universe: self.max_universe.try_fold_with(folder)?,
             variables: self.variables.try_fold_with(folder)?,
+            defining_opaque_types: self.defining_opaque_types,
         })
     }
 }
@@ -109,9 +116,11 @@ where
     I::CanonicalVars: TypeVisitable<I>,
 {
     fn visit_with<F: TypeVisitor<I>>(&self, folder: &mut F) -> F::Result {
-        try_visit!(self.value.visit_with(folder));
-        try_visit!(self.max_universe.visit_with(folder));
-        self.variables.visit_with(folder)
+        let Self { value, max_universe, variables, defining_opaque_types } = self;
+        try_visit!(value.visit_with(folder));
+        try_visit!(max_universe.visit_with(folder));
+        try_visit!(defining_opaque_types.visit_with(folder));
+        variables.visit_with(folder)
     }
 }
 
diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs
index 9c8e45b4338..9298360f749 100644
--- a/compiler/rustc_type_ir/src/debug.rs
+++ b/compiler/rustc_type_ir/src/debug.rs
@@ -43,6 +43,10 @@ impl<I: Interner> InferCtxtLike for NoInfcx<I> {
     fn probe_ct_var(&self, _vid: ConstVid) -> Option<I::Const> {
         None
     }
+
+    fn defining_opaque_types(&self) -> <Self::Interner as Interner>::DefiningOpaqueTypes {
+        Default::default()
+    }
 }
 
 pub trait DebugWithInfcx<I: Interner>: fmt::Debug {
diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs
index 28b71f0ea13..a53287c1987 100644
--- a/compiler/rustc_type_ir/src/infcx.rs
+++ b/compiler/rustc_type_ir/src/infcx.rs
@@ -37,4 +37,6 @@ pub trait InferCtxtLike {
 
     /// Resolve `ConstVid` to its inferred type, if it has been equated with a non-infer type.
     fn probe_ct_var(&self, vid: ConstVid) -> Option<<Self::Interner as Interner>::Const>;
+
+    fn defining_opaque_types(&self) -> <Self::Interner as Interner>::DefiningOpaqueTypes;
 }
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 27d9215f8d4..70f7e58be19 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -11,6 +11,7 @@ use crate::{
 
 pub trait Interner: Sized + Copy {
     type DefId: Copy + Debug + Hash + Eq;
+    type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>;
     type AdtDef: Copy + Debug + Hash + Eq;
 
     type GenericArgs: Copy
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 060a6fa903f..e14932ad99d 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -4132,7 +4132,6 @@ ui/type-alias-impl-trait/issue-52843.rs
 ui/type-alias-impl-trait/issue-53092-2.rs
 ui/type-alias-impl-trait/issue-53092.rs
 ui/type-alias-impl-trait/issue-53096.rs
-ui/type-alias-impl-trait/issue-53398-cyclic-types.rs
 ui/type-alias-impl-trait/issue-53598.rs
 ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
 ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs
diff --git a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
index 76938c14e1e..cb72ad3d253 100644
--- a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
@@ -1,36 +1,36 @@
 // MIR for `address_of_reborrow` after SimplifyCfg-initial
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:8:5: 8:18, inferred_ty: *const [i32; 10]
-| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:10:5: 10:25, inferred_ty: *const dyn std::marker::Send
-| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
-| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
-| 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
-| 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
-| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
-| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
-| 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
-| 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
-| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:19:5: 19:18, inferred_ty: *const [i32; 10]
-| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:21:5: 21:25, inferred_ty: *const dyn std::marker::Send
-| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
-| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
-| 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
-| 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
-| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
-| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
-| 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
-| 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
-| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:29:5: 29:16, inferred_ty: *mut [i32; 10]
-| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:31:5: 31:23, inferred_ty: *mut dyn std::marker::Send
-| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
-| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
-| 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
-| 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
-| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
-| 27: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
-| 28: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32]
-| 29: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32]
+| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:8:5: 8:18, inferred_ty: *const [i32; 10]
+| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:10:5: 10:25, inferred_ty: *const dyn std::marker::Send
+| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
+| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
+| 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
+| 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
+| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
+| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
+| 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
+| 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
+| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:19:5: 19:18, inferred_ty: *const [i32; 10]
+| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:21:5: 21:25, inferred_ty: *const dyn std::marker::Send
+| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
+| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
+| 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
+| 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
+| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
+| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
+| 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
+| 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
+| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:29:5: 29:16, inferred_ty: *mut [i32; 10]
+| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:31:5: 31:23, inferred_ty: *mut dyn std::marker::Send
+| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
+| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
+| 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
+| 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
+| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
+| 27: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
+| 28: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32]
+| 29: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32]
 |
 fn address_of_reborrow() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
index 5df6633880e..5c0d1e9b93f 100644
--- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after SimplifyCfg-initial
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(std::option::Option<std::boxed::Box<u32>>), max_universe: U0, variables: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
-| 1: user_ty: Canonical { value: Ty(std::option::Option<std::boxed::Box<u32>>), max_universe: U0, variables: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
+| 0: user_ty: Canonical { value: Ty(std::option::Option<std::boxed::Box<u32>>), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
+| 1: user_ty: Canonical { value: Ty(std::option::Option<std::boxed::Box<u32>>), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir
index 19a777cb03b..0f7917dbb5c 100644
--- a/tests/mir-opt/building/issue_101867.main.built.after.mir
+++ b/tests/mir-opt/building/issue_101867.main.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
-| 1: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
+| 0: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
+| 1: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
index e07c2b6fa9d..1855bb0787d 100644
--- a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
+++ b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
@@ -1,10 +1,10 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
-| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
-| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
-| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
+| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
+| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
+| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
+| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/issue_72181_1.main.built.after.mir b/tests/mir-opt/issue_72181_1.main.built.after.mir
index ae0dc9a0b6a..e8ad5cd8d16 100644
--- a/tests/mir-opt/issue_72181_1.main.built.after.mir
+++ b/tests/mir-opt/issue_72181_1.main.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void
-| 1: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void
+| 0: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void
+| 1: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir
index c8039dc4735..0b0bac73e9f 100644
--- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir
+++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir
index c8039dc4735..0b0bac73e9f 100644
--- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir
+++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/ui/impl-trait/different_where_bounds.rs b/tests/ui/impl-trait/different_where_bounds.rs
new file mode 100644
index 00000000000..87ae6db2822
--- /dev/null
+++ b/tests/ui/impl-trait/different_where_bounds.rs
@@ -0,0 +1,27 @@
+//! This test checks that the param env canonicalization cache
+//! does not end up with inconsistent values.
+
+//@ check-pass
+
+pub fn poison1() -> impl Sized
+where
+    (): 'static,
+{
+}
+pub fn poison2() -> impl Sized
+where
+    (): 'static,
+{
+    define_by_query((poison2, ()));
+}
+pub fn poison3() -> impl Sized
+where
+    (): 'static,
+{
+}
+
+trait Query {}
+impl<Out, F: Fn() -> Out> Query for (F, Out) {}
+fn define_by_query(_: impl Query) {}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr
deleted file mode 100644
index e4c8aec3973..00000000000
--- a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-note: no errors encountered even though delayed bugs were created
-
-note: those delayed bugs will now be shown as internal compiler errors
-
-error: internal compiler error: {OpaqueTypeKey { def_id: DefId(rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(foo::{opaque#0}) }) } }}
-   |
-   = 
-           
-
-error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(foo::{opaque#0}) }))), bound_vars: [] } } }
-  --> $DIR/equality-in-canonical-query.rs:21:5
-   |
-LL |     same_output(foo, rpit);
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-   |
-
-  --> $DIR/equality-in-canonical-query.rs:21:5
-   |
-LL |     same_output(foo, rpit);
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-query stack during panic:
-end of query stack
diff --git a/tests/ui/impl-trait/equality-in-canonical-query.rs b/tests/ui/impl-trait/equality-in-canonical-query.rs
index 6a32f4bec76..2b8f6ce1b07 100644
--- a/tests/ui/impl-trait/equality-in-canonical-query.rs
+++ b/tests/ui/impl-trait/equality-in-canonical-query.rs
@@ -1,15 +1,6 @@
 // issue: #116877
 //@ revisions: sized clone
-//@[sized] check-pass
-//@[clone] known-bug: #108498
-//@[clone] failure-status: 101
-//@[clone] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId("
-//@[clone] normalize-stderr-test: "(?m)note: we would appreciate a bug report.*\n\n" -> ""
-//@[clone] normalize-stderr-test: "(?m)note: rustc.*running on.*\n\n" -> ""
-//@[clone] normalize-stderr-test: "(?m)note: compiler flags.*\n\n" -> ""
-//@[clone] normalize-stderr-test: "(?m)note: delayed at.*$" -> ""
-//@[clone] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> ""
-//@[clone] normalize-stderr-test: "(?m)^ *at .*\n" -> ""
+//@ check-pass
 
 #[cfg(sized)] fn rpit() -> impl Sized {}
 #[cfg(clone)] fn rpit() -> impl Clone {}
diff --git a/tests/ui/impl-trait/nested-hkl-lifetime.rs b/tests/ui/impl-trait/nested-hkl-lifetime.rs
new file mode 100644
index 00000000000..089ceca6777
--- /dev/null
+++ b/tests/ui/impl-trait/nested-hkl-lifetime.rs
@@ -0,0 +1,32 @@
+//@ check-pass
+
+use std::iter::FromIterator;
+
+struct DynamicAlt<P>(P);
+
+impl<P> FromIterator<P> for DynamicAlt<P> {
+    fn from_iter<T: IntoIterator<Item = P>>(_iter: T) -> Self {
+        loop {}
+    }
+}
+
+fn owned_context<I, F>(_: F) -> impl FnMut(I) -> I {
+    |i| i
+}
+
+trait Parser<I> {}
+
+impl<T, I> Parser<I> for T where T: FnMut(I) -> I {}
+
+fn alt<I, P: Parser<I>>(_: DynamicAlt<P>) -> impl FnMut(I) -> I {
+    |i| i
+}
+
+fn rule_to_parser<'c>() -> impl Parser<&'c str> {
+    move |input| {
+        let v: Vec<()> = vec![];
+        alt(v.iter().map(|()| owned_context(rule_to_parser())).collect::<DynamicAlt<_>>())(input)
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.rs b/tests/ui/impl-trait/nested-rpit-hrtb.rs
index a696e1710f0..9b18aceb4a7 100644
--- a/tests/ui/impl-trait/nested-rpit-hrtb.rs
+++ b/tests/ui/impl-trait/nested-rpit-hrtb.rs
@@ -44,7 +44,7 @@ fn one_hrtb_mention_fn_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl Sized
 
 // This should resolve.
 fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {}
-//~^ ERROR type annotations needed: cannot satisfy `for<'a> &'a (): Qux<'b>`
+//~^ ERROR the trait bound `for<'a> &'a (): Qux<'b>` is not satisfied
 
 // This should resolve.
 fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {}
diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr
index 64f801ea685..2fa036f35fa 100644
--- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr
+++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr
@@ -86,13 +86,12 @@ note: lifetime declared here
 LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
    |                                            ^^
 
-error[E0283]: type annotations needed: cannot satisfy `for<'a> &'a (): Qux<'b>`
+error[E0277]: the trait bound `for<'a> &'a (): Qux<'b>` is not satisfied
   --> $DIR/nested-rpit-hrtb.rs:46:79
    |
 LL | fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {}
-   |                                                                               ^^^^^^^^^^^^
+   |                                                                               ^^^^^^^^^^^^ the trait `for<'a> Qux<'b>` is not implemented for `&'a ()`
    |
-   = note: cannot satisfy `for<'a> &'a (): Qux<'b>`
    = help: the trait `Qux<'_>` is implemented for `()`
    = help: for that trait implementation, expected `()`, found `&'a ()`
 
@@ -125,5 +124,5 @@ LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Si
 
 error: aborting due to 11 previous errors
 
-Some errors have detailed explanations: E0261, E0277, E0283, E0657.
+Some errors have detailed explanations: E0261, E0277, E0657.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/inference/issue-80409.no-compat.stderr b/tests/ui/inference/issue-80409.no-compat.stderr
index 523ca229b06..c772225be75 100644
--- a/tests/ui/inference/issue-80409.no-compat.stderr
+++ b/tests/ui/inference/issue-80409.no-compat.stderr
@@ -1,4 +1,4 @@
-error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ImpliedOutlivesBounds { ty: &'?2 mut StateContext<'?3, usize> } }
+error: internal compiler error: error performing operation: fully_perform
   --> $DIR/issue-80409.rs:49:30
    |
 LL |     builder.state().on_entry(|_| {});
diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs
deleted file mode 100644
index ae463b6ef5b..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(type_alias_impl_trait)]
-
-//@ check-pass
-
-type Foo = impl Fn() -> Foo;
-
-fn foo() -> Foo {
-    foo
-}
-
-fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr
deleted file mode 100644
index 1c36fda4ae1..00000000000
--- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-note: no errors encountered even though delayed bugs were created
-
-note: those delayed bugs will now be shown as internal compiler errors
-
-error: internal compiler error: {OpaqueTypeKey { def_id: DefId(get_rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }) } }}
-   |
-   = 
-           
-
-error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(get_rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }))), bound_vars: [] } } }
-  --> $DIR/rpit_tait_equality_in_canonical_query.rs:32:5
-   |
-LL |     query(get_rpit);
-   |     ^^^^^^^^^^^^^^^
-   |
-
-  --> $DIR/rpit_tait_equality_in_canonical_query.rs:32:5
-   |
-LL |     query(get_rpit);
-   |     ^^^^^^^^^^^^^^^
-
-query stack during panic:
-end of query stack
diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs
index 7524cebf9e6..6f50703aca2 100644
--- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs
+++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs
@@ -8,17 +8,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
-//@[next] check-pass
-
-//@[current] known-bug: #108498
-//@[current] failure-status: 101
-//@[current] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId("
-//@[current] normalize-stderr-test: "(?m)note: we would appreciate a bug report.*\n\n" -> ""
-//@[current] normalize-stderr-test: "(?m)note: rustc.*running on.*\n\n" -> ""
-//@[current] normalize-stderr-test: "(?m)note: compiler flags.*\n\n" -> ""
-//@[current] normalize-stderr-test: "(?m)note: delayed at.*$" -> ""
-//@[current] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> ""
-//@[current] normalize-stderr-test: "(?m)^ *at .*\n" -> ""
+//@ check-pass
 
 #![feature(type_alias_impl_trait)]
 
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs
index e5e7fb677ed..19986247d40 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs
@@ -1,12 +1,10 @@
 #![feature(type_alias_impl_trait)]
+//@ known-bug: #109268
 
 type Foo = impl Fn() -> Foo;
-//~^ ERROR: unconstrained opaque type
 
 fn crash(x: Foo) -> Foo {
     x
 }
 
-fn main() {
-
-}
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr
new file mode 100644
index 00000000000..ee8922b673e
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `<Foo as FnOnce<()>>::Output == Foo`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:6:21
+   |
+LL | fn crash(x: Foo) -> Foo {
+   |                     ^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs
index 7c7a1b405bc..761cc83af51 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs
@@ -1,11 +1,11 @@
 #![feature(type_alias_impl_trait)]
+//@ known-bug: #109268
 
 pub trait Bar<T> {
     type Item;
 }
 
 type Foo = impl Bar<Foo, Item = Foo>;
-//~^ ERROR: unconstrained opaque type
 
 fn crash(x: Foo) -> Foo {
     x
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr
new file mode 100644
index 00000000000..3d0f1d30ca2
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `<Foo as Bar<Foo>>::Item == Foo`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:10:21
+   |
+LL | fn crash(x: Foo) -> Foo {
+   |                     ^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs
new file mode 100644
index 00000000000..52942afd639
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs
@@ -0,0 +1,10 @@
+#![feature(type_alias_impl_trait)]
+//@ known-bug: #109268
+
+type Foo<'a> = impl Fn() -> Foo<'a>;
+
+fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> {
+    x
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr
new file mode 100644
index 00000000000..675689bac42
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `<Foo<'_> as FnOnce<()>>::Output == Foo<'a>`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:6:40
+   |
+LL | fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> {
+   |                                        ^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs
new file mode 100644
index 00000000000..e866b45a8e6
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs
@@ -0,0 +1,16 @@
+#![feature(type_alias_impl_trait)]
+//@ known-bug: trait-system-refactor-initiative#43
+
+trait Id {
+    type Assoc;
+}
+impl<T> Id for T {
+    type Assoc = T;
+}
+
+type Ty
+where
+    Ty: Id<Assoc = Ty>,
+= impl Sized;
+fn define() -> Ty {}
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr
new file mode 100644
index 00000000000..aedb78bf5e7
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr
@@ -0,0 +1,39 @@
+error[E0275]: overflow evaluating the requirement `Ty: Id`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:11:1
+   |
+LL | type Ty
+   | ^^^^^^^
+   |
+note: required by a bound on the type alias `Ty`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:13:9
+   |
+LL |     Ty: Id<Assoc = Ty>,
+   |         ^^^^^^^^^^^^^^ required by this bound
+
+error[E0275]: overflow evaluating the requirement `Ty: Id`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:15:19
+   |
+LL | fn define() -> Ty {}
+   |                   ^^
+   |
+note: required by a bound on the type alias `Ty`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:13:9
+   |
+LL |     Ty: Id<Assoc = Ty>,
+   |         ^^^^^^^^^^^^^^ required by this bound
+
+error[E0275]: overflow evaluating the requirement `Ty: Id`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:15:16
+   |
+LL | fn define() -> Ty {}
+   |                ^^
+   |
+note: required by a bound on the type alias `Ty`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:13:9
+   |
+LL |     Ty: Id<Assoc = Ty>,
+   |         ^^^^^^^^^^^^^^ required by this bound
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr
deleted file mode 100644
index 3d43fbe0dbc..00000000000
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unconstrained opaque type
-  --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:12
-   |
-LL | type Foo = impl Fn() -> Foo;
-   |            ^^^^^^^^^^^^^^^^
-   |
-   = note: `Foo` must be used in combination with a concrete type within the same module
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr
deleted file mode 100644
index e2dc887989b..00000000000
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unconstrained opaque type
-  --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:12
-   |
-LL | type Foo = impl Bar<Foo, Item = Foo>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `Foo` must be used in combination with a concrete type within the same module
-
-error: aborting due to 1 previous error
-