about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-06-12 15:58:32 +0000
committerbors <bors@rust-lang.org>2024-06-12 15:58:32 +0000
commit1d43fbbc7348f2bd9260d8532bffa02f5bd2c9ac (patch)
treebc04e04a2b07e4e511bb28453ca6adc0fc516191
parent0285dab54f87120367f5693174136aff24b74640 (diff)
parent5d22e7a8813f6a584eb7415cb78182b52ff71e12 (diff)
downloadrust-1d43fbbc7348f2bd9260d8532bffa02f5bd2c9ac.tar.gz
rust-1d43fbbc7348f2bd9260d8532bffa02f5bd2c9ac.zip
Auto merge of #126332 - GuillaumeGomez:rollup-bu1q4pz, r=GuillaumeGomez
Rollup of 9 pull requests

Successful merges:

 - #126039 (Promote `arm64ec-pc-windows-msvc` to tier 2)
 - #126075 (Remove `DebugWithInfcx` machinery)
 - #126228 (Provide correct parent for nested anon const)
 - #126232 (interpret: dyn trait metadata check: equate traits in a proper way)
 - #126242 (Simplify provider api to improve llvm ir)
 - #126294 (coverage: Replace the old span refiner with a single function)
 - #126295 (No uninitalized report in a pre-returned match arm)
 - #126312 (Update `rustc-perf` submodule)
 - #126322 (Follow up to splitting core's PanicInfo and std's PanicInfo)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs21
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs9
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs49
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs37
-rw-r--r--compiler/rustc_const_eval/src/interpret/traits.rs101
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs18
-rw-r--r--compiler/rustc_const_eval/src/interpret/visitor.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs26
-rw-r--r--compiler/rustc_middle/src/ty/list.rs10
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs103
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs239
-rw-r--r--compiler/rustc_type_ir/src/binder.rs15
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs50
-rw-r--r--compiler/rustc_type_ir/src/debug.rs146
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs10
-rw-r--r--compiler/rustc_type_ir/src/interner.rs10
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
-rw-r--r--compiler/rustc_type_ir/src/predicate.rs32
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs30
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs107
-rw-r--r--library/core/src/error.rs49
-rw-r--r--library/core/src/panic/panic_info.rs9
-rw-r--r--library/std/src/os/linux/raw.rs6
-rw-r--r--library/std/src/panic.rs5
-rw-r--r--src/ci/github-actions/jobs.yml1
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md11
-rw-r--r--src/tools/build-manifest/src/main.rs1
-rw-r--r--src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs4
-rw-r--r--src/tools/miri/tests/pass/issues/issue-miri-3541-dyn-vtable-trait-normalization.rs40
m---------src/tools/rustc-perf0
-rw-r--r--tests/coverage/assert-ne.cov-map13
-rw-r--r--tests/coverage/assert-ne.coverage23
-rw-r--r--tests/coverage/assert-ne.rs22
-rw-r--r--tests/coverage/loop-break.cov-map14
-rw-r--r--tests/coverage/loop-break.coverage14
-rw-r--r--tests/coverage/loop-break.rs13
-rw-r--r--tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir30
-rw-r--r--tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff2
-rw-r--r--tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.rs22
-rw-r--r--tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.stderr15
-rw-r--r--tests/ui/coherence/occurs-check/associated-type.next.stderr8
-rw-r--r--tests/ui/coherence/occurs-check/associated-type.old.stderr16
-rw-r--r--tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs20
-rw-r--r--tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr11
-rw-r--r--tests/ui/higher-ranked/structually-relate-aliases.stderr4
-rw-r--r--tests/ui/traits/next-solver/issue-118950-root-region.stderr8
51 files changed, 560 insertions, 850 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 821a9036654..f32ff57fe88 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -557,8 +557,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // for the branching codepaths that aren't covered, to point at them.
         let map = self.infcx.tcx.hir();
         let body = map.body_owned_by(self.mir_def_id());
-
-        let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
+        let mut visitor =
+            ConditionVisitor { tcx: self.infcx.tcx, spans: &spans, name: &name, errors: vec![] };
         visitor.visit_body(&body);
 
         let mut show_assign_sugg = false;
@@ -4372,13 +4372,14 @@ impl<'hir> Visitor<'hir> for BreakFinder {
 
 /// Given a set of spans representing statements initializing the relevant binding, visit all the
 /// function expressions looking for branching code paths that *do not* initialize the binding.
-struct ConditionVisitor<'b> {
+struct ConditionVisitor<'b, 'tcx> {
+    tcx: TyCtxt<'tcx>,
     spans: &'b [Span],
     name: &'b str,
     errors: Vec<(Span, String)>,
 }
 
-impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
+impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
     fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
         match ex.kind {
             hir::ExprKind::If(cond, body, None) => {
@@ -4464,6 +4465,12 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                                     ),
                                 ));
                             } else if let Some(guard) = &arm.guard {
+                                if matches!(
+                                    self.tcx.hir_node(arm.body.hir_id),
+                                    hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. })
+                                ) {
+                                    continue;
+                                }
                                 self.errors.push((
                                     arm.pat.span.to(guard.span),
                                     format!(
@@ -4473,6 +4480,12 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                                     ),
                                 ));
                             } else {
+                                if matches!(
+                                    self.tcx.hir_node(arm.body.hir_id),
+                                    hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. })
+                                ) {
+                                    continue;
+                                }
                                 self.errors.push((
                                     arm.pat.span,
                                     format!(
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 0a45bbb3edb..6961e13c239 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -387,7 +387,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         match (&src_pointee_ty.kind(), &dest_pointee_ty.kind()) {
             (&ty::Array(_, length), &ty::Slice(_)) => {
                 let ptr = self.read_pointer(src)?;
-                // u64 cast is from usize to u64, which is always good
                 let val = Immediate::new_slice(
                     ptr,
                     length.eval_target_usize(*self.tcx, self.param_env),
@@ -405,13 +404,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let (old_data, old_vptr) = val.to_scalar_pair();
                 let old_data = old_data.to_pointer(self)?;
                 let old_vptr = old_vptr.to_pointer(self)?;
-                let (ty, old_trait) = self.get_ptr_vtable(old_vptr)?;
-                if old_trait != data_a.principal() {
-                    throw_ub!(InvalidVTableTrait {
-                        expected_trait: data_a,
-                        vtable_trait: old_trait,
-                    });
-                }
+                let ty = self.get_ptr_vtable_ty(old_vptr, Some(data_a))?;
                 let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
                 self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
             }
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 7c2100fcbe3..e28cc05cc2a 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -765,10 +765,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 }
                 Ok(Some((full_size, full_align)))
             }
-            ty::Dynamic(_, _, ty::Dyn) => {
+            ty::Dynamic(expected_trait, _, ty::Dyn) => {
                 let vtable = metadata.unwrap_meta().to_pointer(self)?;
                 // Read size and align from vtable (already checks size).
-                Ok(Some(self.get_vtable_size_and_align(vtable)?))
+                Ok(Some(self.get_vtable_size_and_align(vtable, Some(expected_trait))?))
             }
 
             ty::Slice(_) | ty::Str => {
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 7f16d441606..1d54da267ee 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -432,12 +432,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
             sym::vtable_size => {
                 let ptr = self.read_pointer(&args[0])?;
-                let (size, _align) = self.get_vtable_size_and_align(ptr)?;
+                // `None` because we don't know which trait to expect here; any vtable is okay.
+                let (size, _align) = self.get_vtable_size_and_align(ptr, None)?;
                 self.write_scalar(Scalar::from_target_usize(size.bytes(), self), dest)?;
             }
             sym::vtable_align => {
                 let ptr = self.read_pointer(&args[0])?;
-                let (_size, align) = self.get_vtable_size_and_align(ptr)?;
+                // `None` because we don't know which trait to expect here; any vtable is okay.
+                let (_size, align) = self.get_vtable_size_and_align(ptr, None)?;
                 self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
             }
 
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 7eb73e9b52f..5461e9c6ad3 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -867,19 +867,26 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             .ok_or_else(|| err_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))).into())
     }
 
-    pub fn get_ptr_vtable(
+    /// Get the dynamic type of the given vtable pointer.
+    /// If `expected_trait` is `Some`, it must be a vtable for the given trait.
+    pub fn get_ptr_vtable_ty(
         &self,
         ptr: Pointer<Option<M::Provenance>>,
-    ) -> InterpResult<'tcx, (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>)> {
+        expected_trait: Option<&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>>,
+    ) -> InterpResult<'tcx, Ty<'tcx>> {
         trace!("get_ptr_vtable({:?})", ptr);
         let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr)?;
         if offset.bytes() != 0 {
             throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset)))
         }
-        match self.tcx.try_get_global_alloc(alloc_id) {
-            Some(GlobalAlloc::VTable(ty, trait_ref)) => Ok((ty, trait_ref)),
-            _ => throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset))),
+        let Some(GlobalAlloc::VTable(ty, vtable_trait)) = self.tcx.try_get_global_alloc(alloc_id)
+        else {
+            throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset)))
+        };
+        if let Some(expected_trait) = expected_trait {
+            self.check_vtable_for_type(vtable_trait, expected_trait)?;
         }
+        Ok(ty)
     }
 
     pub fn alloc_mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> {
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 046ff34e3d0..08d3165867c 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -9,7 +9,6 @@ use tracing::{instrument, trace};
 
 use rustc_ast::Mutability;
 use rustc_middle::mir;
-use rustc_middle::ty;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::Ty;
 use rustc_middle::{bug, span_bug};
@@ -1018,54 +1017,6 @@ where
         let layout = self.layout_of(raw.ty)?;
         Ok(self.ptr_to_mplace(ptr.into(), layout))
     }
-
-    /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
-    /// Aso returns the vtable.
-    pub(super) fn unpack_dyn_trait(
-        &self,
-        mplace: &MPlaceTy<'tcx, M::Provenance>,
-        expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, Pointer<Option<M::Provenance>>)> {
-        assert!(
-            matches!(mplace.layout.ty.kind(), ty::Dynamic(_, _, ty::Dyn)),
-            "`unpack_dyn_trait` only makes sense on `dyn*` types"
-        );
-        let vtable = mplace.meta().unwrap_meta().to_pointer(self)?;
-        let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
-        if expected_trait.principal() != vtable_trait {
-            throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
-        }
-        // This is a kind of transmute, from a place with unsized type and metadata to
-        // a place with sized type and no metadata.
-        let layout = self.layout_of(ty)?;
-        let mplace =
-            MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..mplace.mplace }, layout };
-        Ok((mplace, vtable))
-    }
-
-    /// Turn a `dyn* Trait` type into an value with the actual dynamic type.
-    /// Also returns the vtable.
-    pub(super) fn unpack_dyn_star<P: Projectable<'tcx, M::Provenance>>(
-        &self,
-        val: &P,
-        expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> InterpResult<'tcx, (P, Pointer<Option<M::Provenance>>)> {
-        assert!(
-            matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
-            "`unpack_dyn_star` only makes sense on `dyn*` types"
-        );
-        let data = self.project_field(val, 0)?;
-        let vtable = self.project_field(val, 1)?;
-        let vtable = self.read_pointer(&vtable.to_op(self)?)?;
-        let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
-        if expected_trait.principal() != vtable_trait {
-            throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
-        }
-        // `data` is already the right thing but has the wrong type. So we transmute it.
-        let layout = self.layout_of(ty)?;
-        let data = data.transmute(layout, self)?;
-        Ok((data, vtable))
-    }
 }
 
 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index cbfe25ca8df..8f76a148679 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -1,6 +1,7 @@
 use std::borrow::Cow;
 
 use either::Either;
+use rustc_middle::ty::TyCtxt;
 use tracing::trace;
 
 use rustc_middle::span_bug;
@@ -827,20 +828,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 };
 
                 // Obtain the underlying trait we are working on, and the adjusted receiver argument.
-                let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) =
+                let (dyn_trait, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) =
                     receiver_place.layout.ty.kind()
                 {
-                    let (recv, vptr) = self.unpack_dyn_star(&receiver_place, data)?;
-                    let (dyn_ty, _dyn_trait) = self.get_ptr_vtable(vptr)?;
+                    let recv = self.unpack_dyn_star(&receiver_place, data)?;
 
-                    (vptr, dyn_ty, recv.ptr())
+                    (data.principal(), recv.layout.ty, recv.ptr())
                 } else {
                     // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
                     // (For that reason we also cannot use `unpack_dyn_trait`.)
                     let receiver_tail = self
                         .tcx
                         .struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env);
-                    let ty::Dynamic(data, _, ty::Dyn) = receiver_tail.kind() else {
+                    let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
                         span_bug!(
                             self.cur_span(),
                             "dynamic call on non-`dyn` type {}",
@@ -851,25 +851,24 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
                     // Get the required information from the vtable.
                     let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
-                    let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
-                    if dyn_trait != data.principal() {
-                        throw_ub!(InvalidVTableTrait {
-                            expected_trait: data,
-                            vtable_trait: dyn_trait,
-                        });
-                    }
+                    let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
 
                     // It might be surprising that we use a pointer as the receiver even if this
                     // is a by-val case; this works because by-val passing of an unsized `dyn
                     // Trait` to a function is actually desugared to a pointer.
-                    (vptr, dyn_ty, receiver_place.ptr())
+                    (receiver_trait.principal(), dyn_ty, receiver_place.ptr())
                 };
 
                 // Now determine the actual method to call. We can do that in two different ways and
                 // compare them to ensure everything fits.
-                let Some(ty::VtblEntry::Method(fn_inst)) =
-                    self.get_vtable_entries(vptr)?.get(idx).copied()
-                else {
+                let vtable_entries = if let Some(dyn_trait) = dyn_trait {
+                    let trait_ref = dyn_trait.with_self_ty(*self.tcx, dyn_ty);
+                    let trait_ref = self.tcx.erase_regions(trait_ref);
+                    self.tcx.vtable_entries(trait_ref)
+                } else {
+                    TyCtxt::COMMON_VTABLE_ENTRIES
+                };
+                let Some(ty::VtblEntry::Method(fn_inst)) = vtable_entries.get(idx).copied() else {
                     // FIXME(fee1-dead) these could be variants of the UB info enum instead of this
                     throw_ub_custom!(fluent::const_eval_dyn_call_not_a_method);
                 };
@@ -898,7 +897,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let receiver_ty = Ty::new_mut_ptr(self.tcx.tcx, dyn_ty);
                 args[0] = FnArg::Copy(
                     ImmTy::from_immediate(
-                        Scalar::from_maybe_pointer(adjusted_receiver, self).into(),
+                        Scalar::from_maybe_pointer(adjusted_recv, self).into(),
                         self.layout_of(receiver_ty)?,
                     )
                     .into(),
@@ -974,11 +973,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         let place = match place.layout.ty.kind() {
             ty::Dynamic(data, _, ty::Dyn) => {
                 // Dropping a trait object. Need to find actual drop fn.
-                self.unpack_dyn_trait(&place, data)?.0
+                self.unpack_dyn_trait(&place, data)?
             }
             ty::Dynamic(data, _, ty::DynStar) => {
                 // Dropping a `dyn*`. Need to find actual drop fn.
-                self.unpack_dyn_star(&place, data)?.0
+                self.unpack_dyn_star(&place, data)?
             }
             _ => {
                 debug_assert_eq!(
diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs
index 244a6ba48a4..bd2c6519421 100644
--- a/compiler/rustc_const_eval/src/interpret/traits.rs
+++ b/compiler/rustc_const_eval/src/interpret/traits.rs
@@ -1,11 +1,14 @@
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::ObligationCause;
 use rustc_middle::mir::interpret::{InterpResult, Pointer};
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::{Align, Size};
+use rustc_trait_selection::traits::ObligationCtxt;
 use tracing::trace;
 
 use super::util::ensure_monomorphic_enough;
-use super::{InterpCx, Machine};
+use super::{throw_ub, InterpCx, MPlaceTy, Machine, MemPlaceMeta, OffsetMode, Projectable};
 
 impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     /// Creates a dynamic vtable for the given type and vtable origin. This is used only for
@@ -33,28 +36,90 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         Ok(vtable_ptr.into())
     }
 
-    /// Returns a high-level representation of the entries of the given vtable.
-    pub fn get_vtable_entries(
-        &self,
-        vtable: Pointer<Option<M::Provenance>>,
-    ) -> InterpResult<'tcx, &'tcx [ty::VtblEntry<'tcx>]> {
-        let (ty, poly_trait_ref) = self.get_ptr_vtable(vtable)?;
-        Ok(if let Some(poly_trait_ref) = poly_trait_ref {
-            let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty);
-            let trait_ref = self.tcx.erase_regions(trait_ref);
-            self.tcx.vtable_entries(trait_ref)
-        } else {
-            TyCtxt::COMMON_VTABLE_ENTRIES
-        })
-    }
-
     pub fn get_vtable_size_and_align(
         &self,
         vtable: Pointer<Option<M::Provenance>>,
+        expected_trait: Option<&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>>,
     ) -> InterpResult<'tcx, (Size, Align)> {
-        let (ty, _trait_ref) = self.get_ptr_vtable(vtable)?;
+        let ty = self.get_ptr_vtable_ty(vtable, expected_trait)?;
         let layout = self.layout_of(ty)?;
         assert!(layout.is_sized(), "there are no vtables for unsized types");
         Ok((layout.size, layout.align.abi))
     }
+
+    /// Check that the given vtable trait is valid for a pointer/reference/place with the given
+    /// expected trait type.
+    pub(super) fn check_vtable_for_type(
+        &self,
+        vtable_trait: Option<ty::PolyExistentialTraitRef<'tcx>>,
+        expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
+    ) -> InterpResult<'tcx> {
+        // Fast path: if they are equal, it's all fine.
+        if expected_trait.principal() == vtable_trait {
+            return Ok(());
+        }
+        if let (Some(expected_trait), Some(vtable_trait)) =
+            (expected_trait.principal(), vtable_trait)
+        {
+            // Slow path: spin up an inference context to check if these traits are sufficiently equal.
+            let infcx = self.tcx.infer_ctxt().build();
+            let ocx = ObligationCtxt::new(&infcx);
+            let cause = ObligationCause::dummy_with_span(self.cur_span());
+            // equate the two trait refs after normalization
+            let expected_trait = ocx.normalize(&cause, self.param_env, expected_trait);
+            let vtable_trait = ocx.normalize(&cause, self.param_env, vtable_trait);
+            if ocx.eq(&cause, self.param_env, expected_trait, vtable_trait).is_ok() {
+                if ocx.select_all_or_error().is_empty() {
+                    // All good.
+                    return Ok(());
+                }
+            }
+        }
+        throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
+    }
+
+    /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
+    pub(super) fn unpack_dyn_trait(
+        &self,
+        mplace: &MPlaceTy<'tcx, M::Provenance>,
+        expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
+    ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
+        assert!(
+            matches!(mplace.layout.ty.kind(), ty::Dynamic(_, _, ty::Dyn)),
+            "`unpack_dyn_trait` only makes sense on `dyn*` types"
+        );
+        let vtable = mplace.meta().unwrap_meta().to_pointer(self)?;
+        let ty = self.get_ptr_vtable_ty(vtable, Some(expected_trait))?;
+        // This is a kind of transmute, from a place with unsized type and metadata to
+        // a place with sized type and no metadata.
+        let layout = self.layout_of(ty)?;
+        let mplace = mplace.offset_with_meta(
+            Size::ZERO,
+            OffsetMode::Wrapping,
+            MemPlaceMeta::None,
+            layout,
+            self,
+        )?;
+        Ok(mplace)
+    }
+
+    /// Turn a `dyn* Trait` type into an value with the actual dynamic type.
+    pub(super) fn unpack_dyn_star<P: Projectable<'tcx, M::Provenance>>(
+        &self,
+        val: &P,
+        expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
+    ) -> InterpResult<'tcx, P> {
+        assert!(
+            matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
+            "`unpack_dyn_star` only makes sense on `dyn*` types"
+        );
+        let data = self.project_field(val, 0)?;
+        let vtable = self.project_field(val, 1)?;
+        let vtable = self.read_pointer(&vtable.to_op(self)?)?;
+        let ty = self.get_ptr_vtable_ty(vtable, Some(expected_trait))?;
+        // `data` is already the right thing but has the wrong type. So we transmute it.
+        let layout = self.layout_of(ty)?;
+        let data = data.transmute(layout, self)?;
+        Ok(data)
+    }
 }
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index f532f6bbe37..6f75bc2af4e 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -343,20 +343,16 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
         match tail.kind() {
             ty::Dynamic(data, _, ty::Dyn) => {
                 let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
-                // Make sure it is a genuine vtable pointer.
-                let (_dyn_ty, dyn_trait) = try_validation!(
-                    self.ecx.get_ptr_vtable(vtable),
+                // Make sure it is a genuine vtable pointer for the right trait.
+                try_validation!(
+                    self.ecx.get_ptr_vtable_ty(vtable, Some(data)),
                     self.path,
                     Ub(DanglingIntPointer(..) | InvalidVTablePointer(..)) =>
-                        InvalidVTablePtr { value: format!("{vtable}") }
+                        InvalidVTablePtr { value: format!("{vtable}") },
+                    Ub(InvalidVTableTrait { expected_trait, vtable_trait }) => {
+                        InvalidMetaWrongTrait { expected_trait, vtable_trait: *vtable_trait }
+                    },
                 );
-                // Make sure it is for the right trait.
-                if dyn_trait != data.principal() {
-                    throw_validation_failure!(
-                        self.path,
-                        InvalidMetaWrongTrait { expected_trait: data, vtable_trait: dyn_trait }
-                    );
-                }
             }
             ty::Slice(..) | ty::Str => {
                 let _len = meta.unwrap_meta().to_target_usize(self.ecx)?;
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index b812e89854b..71c057e549b 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -95,7 +95,7 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
                 // unsized values are never immediate, so we can assert_mem_place
                 let op = v.to_op(self.ecx())?;
                 let dest = op.assert_mem_place();
-                let inner_mplace = self.ecx().unpack_dyn_trait(&dest, data)?.0;
+                let inner_mplace = self.ecx().unpack_dyn_trait(&dest, data)?;
                 trace!("walk_value: dyn object layout: {:#?}", inner_mplace.layout);
                 // recurse with the inner type
                 return self.visit_field(v, 0, &inner_mplace.into());
@@ -104,7 +104,7 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
                 // DynStar types. Very different from a dyn type (but strangely part of the
                 // same variant in `TyKind`): These are pairs where the 2nd component is the
                 // vtable, and the first component is the data (which must be ptr-sized).
-                let data = self.ecx().unpack_dyn_star(v, data)?.0;
+                let data = self.ecx().unpack_dyn_star(v, data)?;
                 return self.visit_field(v, 0, &data);
             }
             // Slices do not need special handling here: they have `Array` field
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index abdf85ad707..303fa23dbc1 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -11,6 +11,7 @@ use rustc_session::lint;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::Span;
 
+#[instrument(level = "debug", skip(tcx))]
 pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
     use rustc_hir::*;
 
@@ -66,7 +67,22 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
         // FIXME(#43408) always enable this once `lazy_normalization` is
         // stable enough and does not need a feature gate anymore.
         Node::AnonConst(_) => {
-            let parent_def_id = tcx.hir().get_parent_item(hir_id);
+            let parent_did = tcx.parent(def_id.to_def_id());
+
+            // We don't do this unconditionally because the `DefId` parent of an anon const
+            // might be an implicitly created closure during `async fn` desugaring. This would
+            // have the wrong generics.
+            //
+            // i.e. `async fn foo<'a>() { let a = [(); { 1 + 2 }]; bar().await() }`
+            // would implicitly have a closure in its body that would be the parent of
+            // the `{ 1 + 2 }` anon const. This closure's generics is simply a witness
+            // instead of `['a]`.
+            let parent_did = if let DefKind::AnonConst = tcx.def_kind(parent_did) {
+                parent_did
+            } else {
+                tcx.hir().get_parent_item(hir_id).to_def_id()
+            };
+            debug!(?parent_did);
 
             let mut in_param_ty = false;
             for (_parent, node) in tcx.hir().parent_iter(hir_id) {
@@ -121,7 +137,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                     //
                     // This has some implications for how we get the predicates available to the anon const
                     // see `explicit_predicates_of` for more information on this
-                    let generics = tcx.generics_of(parent_def_id.to_def_id());
+                    let generics = tcx.generics_of(parent_did);
                     let param_def_idx = generics.param_def_id_to_index[&param_id.to_def_id()];
                     // In the above example this would be .params[..N#0]
                     let own_params = generics.params_to(param_def_idx as usize, tcx).to_owned();
@@ -147,7 +163,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                     //
                     // Note that we do not supply the parent generics when using
                     // `min_const_generics`.
-                    Some(parent_def_id.to_def_id())
+                    Some(parent_did)
                 }
             } else {
                 let parent_node = tcx.parent_hir_node(hir_id);
@@ -159,7 +175,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                     Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. })
                         if constant.hir_id() == hir_id =>
                     {
-                        Some(parent_def_id.to_def_id())
+                        Some(parent_did)
                     }
                     // Exclude `GlobalAsm` here which cannot have generics.
                     Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
@@ -171,7 +187,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                             _ => false,
                         }) =>
                     {
-                        Some(parent_def_id.to_def_id())
+                        Some(parent_did)
                     }
                     _ => None,
                 }
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 0db541899d2..71a93cc520d 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -1,5 +1,5 @@
 use super::flags::FlagComputation;
-use super::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, TyCtxt, TypeFlags, WithInfcx};
+use super::{DebruijnIndex, TypeFlags};
 use crate::arena::Arena;
 use rustc_data_structures::aligned::{align_of, Aligned};
 use rustc_serialize::{Encodable, Encoder};
@@ -162,14 +162,6 @@ impl<H, T: fmt::Debug> fmt::Debug for RawList<H, T> {
         (**self).fmt(f)
     }
 }
-impl<'tcx, H, T: DebugWithInfcx<TyCtxt<'tcx>>> DebugWithInfcx<TyCtxt<'tcx>> for RawList<H, T> {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        fmt::Debug::fmt(&this.map(|this| this.as_slice()), f)
-    }
-}
 
 impl<H, S: Encoder, T: Encodable<S>> Encodable<S> for RawList<H, T> {
     #[inline]
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 7ff1b799822..83f8de6b6f9 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -61,7 +61,6 @@ use rustc_span::{ExpnId, ExpnKind, Span};
 use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
 pub use rustc_type_ir::relate::VarianceDiagInfo;
-pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
 use tracing::{debug, instrument};
 pub use vtable::*;
 
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index cc6b1d57f87..71e2e3e9f99 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -13,7 +13,7 @@ use rustc_ast_ir::visit::VisitorResult;
 use rustc_hir::def::Namespace;
 use rustc_span::source_map::Spanned;
 use rustc_target::abi::TyAndLayout;
-use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx};
+use rustc_type_ir::ConstKind;
 
 use std::fmt::{self, Debug};
 
@@ -83,14 +83,6 @@ impl fmt::Debug for ty::LateParamRegion {
     }
 }
 
-impl<'tcx> ty::DebugWithInfcx<TyCtxt<'tcx>> for Ty<'tcx> {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        this.data.fmt(f)
-    }
-}
 impl<'tcx> fmt::Debug for Ty<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         with_no_trimmed_paths!(fmt::Debug::fmt(self.kind(), f))
@@ -121,70 +113,33 @@ impl<'tcx> fmt::Debug for ty::Clause<'tcx> {
     }
 }
 
-impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for Pattern<'tcx> {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        match &**this.data {
-            ty::PatternKind::Range { start, end, include_end } => f
-                .debug_struct("Pattern::Range")
-                .field("start", start)
-                .field("end", end)
-                .field("include_end", include_end)
-                .finish(),
-        }
-    }
-}
-
 impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
-impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::consts::Expr<'tcx> {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        match this.data.kind {
+        match self.kind {
             ty::ExprKind::Binop(op) => {
-                let (lhs_ty, rhs_ty, lhs, rhs) = this.data.binop_args();
-                write!(
-                    f,
-                    "({op:?}: ({:?}: {:?}), ({:?}: {:?}))",
-                    &this.wrap(lhs),
-                    &this.wrap(lhs_ty),
-                    &this.wrap(rhs),
-                    &this.wrap(rhs_ty),
-                )
+                let (lhs_ty, rhs_ty, lhs, rhs) = self.binop_args();
+                write!(f, "({op:?}: ({:?}: {:?}), ({:?}: {:?}))", lhs, lhs_ty, rhs, rhs_ty,)
             }
             ty::ExprKind::UnOp(op) => {
-                let (rhs_ty, rhs) = this.data.unop_args();
-                write!(f, "({op:?}: ({:?}: {:?}))", &this.wrap(rhs), &this.wrap(rhs_ty))
+                let (rhs_ty, rhs) = self.unop_args();
+                write!(f, "({op:?}: ({:?}: {:?}))", rhs, rhs_ty)
             }
             ty::ExprKind::FunctionCall => {
-                let (func_ty, func, args) = this.data.call_args();
+                let (func_ty, func, args) = self.call_args();
                 let args = args.collect::<Vec<_>>();
-                write!(f, "({:?}: {:?})(", &this.wrap(func), &this.wrap(func_ty))?;
+                write!(f, "({:?}: {:?})(", func, func_ty)?;
                 for arg in args.iter().rev().skip(1).rev() {
-                    write!(f, "{:?}, ", &this.wrap(arg))?;
+                    write!(f, "{:?}, ", arg)?;
                 }
                 if let Some(arg) = args.last() {
-                    write!(f, "{:?}", &this.wrap(arg))?;
+                    write!(f, "{:?}", arg)?;
                 }
 
                 write!(f, ")")
             }
             ty::ExprKind::Cast(kind) => {
-                let (value_ty, value, to_ty) = this.data.cast_args();
-                write!(
-                    f,
-                    "({kind:?}: ({:?}: {:?}), {:?})",
-                    &this.wrap(value),
-                    &this.wrap(value_ty),
-                    &this.wrap(to_ty)
-                )
+                let (value_ty, value, to_ty) = self.cast_args();
+                write!(f, "({kind:?}: ({:?}: {:?}), {:?})", value, value_ty, to_ty)
             }
         }
     }
@@ -192,20 +147,12 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::consts::Expr<'tcx> {
 
 impl<'tcx> fmt::Debug for ty::Const<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
-impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::Const<'tcx> {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
         // If this is a value, we spend some effort to make it look nice.
-        if let ConstKind::Value(_, _) = this.data.kind() {
+        if let ConstKind::Value(_, _) = self.kind() {
             return ty::tls::with(move |tcx| {
                 // Somehow trying to lift the valtree results in lifetime errors, so we lift the
                 // entire constant.
-                let lifted = tcx.lift(*this.data).unwrap();
+                let lifted = tcx.lift(*self).unwrap();
                 let ConstKind::Value(ty, valtree) = lifted.kind() else {
                     bug!("we checked that this is a valtree")
                 };
@@ -215,7 +162,7 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::Const<'tcx> {
             });
         }
         // Fall back to something verbose.
-        write!(f, "{kind:?}", kind = &this.map(|data| data.kind()))
+        write!(f, "{:?}", self.kind())
     }
 }
 
@@ -247,32 +194,12 @@ impl<'tcx> fmt::Debug for GenericArg<'tcx> {
         }
     }
 }
-impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for GenericArg<'tcx> {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        match this.data.unpack() {
-            GenericArgKind::Lifetime(lt) => write!(f, "{:?}", &this.wrap(lt)),
-            GenericArgKind::Const(ct) => write!(f, "{:?}", &this.wrap(ct)),
-            GenericArgKind::Type(ty) => write!(f, "{:?}", &this.wrap(ty)),
-        }
-    }
-}
 
 impl<'tcx> fmt::Debug for Region<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", self.kind())
     }
 }
-impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for Region<'tcx> {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        write!(f, "{:?}", &this.map(|data| data.kind()))
-    }
-}
 
 ///////////////////////////////////////////////////////////////////////////
 // Atomic structs
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 743f1cc24be..bb6a666ff73 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,6 +1,5 @@
-use rustc_middle::bug;
 use rustc_middle::mir;
-use rustc_span::{BytePos, Span};
+use rustc_span::Span;
 
 use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
 use crate::coverage::mappings;
@@ -23,7 +22,7 @@ pub(super) fn extract_refined_covspans(
     let sorted_span_buckets =
         from_mir::mir_to_initial_sorted_coverage_spans(mir_body, hir_info, basic_coverage_blocks);
     for bucket in sorted_span_buckets {
-        let refined_spans = SpansRefiner::refine_sorted_spans(bucket);
+        let refined_spans = refine_sorted_spans(bucket);
         code_mappings.extend(refined_spans.into_iter().map(|RefinedCovspan { span, bcb }| {
             // Each span produced by the refiner represents an ordinary code region.
             mappings::CodeMapping { span, bcb }
@@ -32,58 +31,6 @@ pub(super) fn extract_refined_covspans(
 }
 
 #[derive(Debug)]
-struct CurrCovspan {
-    span: Span,
-    bcb: BasicCoverageBlock,
-}
-
-impl CurrCovspan {
-    fn new(span: Span, bcb: BasicCoverageBlock) -> Self {
-        Self { span, bcb }
-    }
-
-    fn into_prev(self) -> PrevCovspan {
-        let Self { span, bcb } = self;
-        PrevCovspan { span, bcb, merged_spans: vec![span] }
-    }
-}
-
-#[derive(Debug)]
-struct PrevCovspan {
-    span: Span,
-    bcb: BasicCoverageBlock,
-    /// List of all the original spans from MIR that have been merged into this
-    /// span. Mainly used to precisely skip over gaps when truncating a span.
-    merged_spans: Vec<Span>,
-}
-
-impl PrevCovspan {
-    fn is_mergeable(&self, other: &CurrCovspan) -> bool {
-        self.bcb == other.bcb
-    }
-
-    fn merge_from(&mut self, other: &CurrCovspan) {
-        debug_assert!(self.is_mergeable(other));
-        self.span = self.span.to(other.span);
-        self.merged_spans.push(other.span);
-    }
-
-    fn cutoff_statements_at(mut self, cutoff_pos: BytePos) -> Option<RefinedCovspan> {
-        self.merged_spans.retain(|span| span.hi() <= cutoff_pos);
-        if let Some(max_hi) = self.merged_spans.iter().map(|span| span.hi()).max() {
-            self.span = self.span.with_hi(max_hi);
-        }
-
-        if self.merged_spans.is_empty() { None } else { Some(self.into_refined()) }
-    }
-
-    fn into_refined(self) -> RefinedCovspan {
-        let Self { span, bcb, merged_spans: _ } = self;
-        RefinedCovspan { span, bcb }
-    }
-}
-
-#[derive(Debug)]
 struct RefinedCovspan {
     span: Span,
     bcb: BasicCoverageBlock,
@@ -100,164 +47,50 @@ impl RefinedCovspan {
     }
 }
 
-/// Converts the initial set of coverage spans (one per MIR `Statement` or `Terminator`) into a
-/// minimal set of coverage spans, using the BCB CFG to determine where it is safe and useful to:
-///
-///  * Remove duplicate source code coverage regions
-///  * Merge spans that represent continuous (both in source code and control flow), non-branching
-///    execution
-struct SpansRefiner {
-    /// The initial set of coverage spans, sorted by `Span` (`lo` and `hi`) and by relative
-    /// dominance between the `BasicCoverageBlock`s of equal `Span`s.
-    sorted_spans_iter: std::vec::IntoIter<SpanFromMir>,
-
-    /// The current coverage span to compare to its `prev`, to possibly merge, discard,
-    /// or cause `prev` to be modified or discarded.
-    /// If `curr` is not discarded or merged, it becomes `prev` for the next iteration.
-    some_curr: Option<CurrCovspan>,
-
-    /// The coverage span from a prior iteration; typically assigned from that iteration's `curr`.
-    /// If that `curr` was discarded, `prev` retains its value from the previous iteration.
-    some_prev: Option<PrevCovspan>,
-
-    /// The final coverage spans to add to the coverage map. A `Counter` or `Expression`
-    /// will also be injected into the MIR for each BCB that has associated spans.
-    refined_spans: Vec<RefinedCovspan>,
-}
-
-impl SpansRefiner {
-    /// Takes the initial list of (sorted) spans extracted from MIR, and "refines"
-    /// them by merging compatible adjacent spans, removing redundant spans,
-    /// and carving holes in spans when they overlap in unwanted ways.
-    fn refine_sorted_spans(sorted_spans: Vec<SpanFromMir>) -> Vec<RefinedCovspan> {
-        let sorted_spans_len = sorted_spans.len();
-        let this = Self {
-            sorted_spans_iter: sorted_spans.into_iter(),
-            some_curr: None,
-            some_prev: None,
-            refined_spans: Vec::with_capacity(sorted_spans_len),
-        };
-
-        this.to_refined_spans()
-    }
-
-    /// Iterate through the sorted coverage spans, and return the refined list of merged and
-    /// de-duplicated spans.
-    fn to_refined_spans(mut self) -> Vec<RefinedCovspan> {
-        while self.next_coverage_span() {
-            // For the first span we don't have `prev` set, so most of the
-            // span-processing steps don't make sense yet.
-            if self.some_prev.is_none() {
-                debug!("  initial span");
-                continue;
-            }
-
-            // The remaining cases assume that `prev` and `curr` are set.
-            let prev = self.prev();
-            let curr = self.curr();
-
-            if prev.is_mergeable(curr) {
-                debug!(?prev, "curr will be merged into prev");
-                let curr = self.take_curr();
-                self.prev_mut().merge_from(&curr);
-            } else if prev.span.hi() <= curr.span.lo() {
-                debug!(
-                    "  different bcbs and disjoint spans, so keep curr for next iter, and add prev={prev:?}",
-                );
-                let prev = self.take_prev().into_refined();
-                self.refined_spans.push(prev);
-            } else {
-                self.cutoff_prev_at_overlapping_curr();
-            }
-        }
-
-        // There is usually a final span remaining in `prev` after the loop ends,
-        // so add it to the output as well.
-        if let Some(prev) = self.some_prev.take() {
-            debug!("    AT END, adding last prev={prev:?}");
-            self.refined_spans.push(prev.into_refined());
-        }
-
-        // Do one last merge pass, to simplify the output.
-        self.refined_spans.dedup_by(|b, a| {
-            if a.is_mergeable(b) {
-                debug!(?a, ?b, "merging list-adjacent refined spans");
-                a.merge_from(b);
-                true
-            } else {
+/// Takes one of the buckets of (sorted) spans extracted from MIR, and "refines"
+/// those spans by removing spans that overlap in unwanted ways, and by merging
+/// compatible adjacent spans.
+#[instrument(level = "debug")]
+fn refine_sorted_spans(sorted_spans: Vec<SpanFromMir>) -> Vec<RefinedCovspan> {
+    // Holds spans that have been read from the input vector, but haven't yet
+    // been committed to the output vector.
+    let mut pending = vec![];
+    let mut refined = vec![];
+
+    for curr in sorted_spans {
+        pending.retain(|prev: &SpanFromMir| {
+            if prev.span.hi() <= curr.span.lo() {
+                // There's no overlap between the previous/current covspans,
+                // so move the previous one into the refined list.
+                refined.push(RefinedCovspan { span: prev.span, bcb: prev.bcb });
                 false
+            } else {
+                // Otherwise, retain the previous covspan only if it has the
+                // same BCB. This tends to discard long outer spans that enclose
+                // smaller inner spans with different control flow.
+                prev.bcb == curr.bcb
             }
         });
-
-        self.refined_spans
-    }
-
-    #[track_caller]
-    fn curr(&self) -> &CurrCovspan {
-        self.some_curr.as_ref().unwrap_or_else(|| bug!("some_curr is None (curr)"))
-    }
-
-    /// If called, then the next call to `next_coverage_span()` will *not* update `prev` with the
-    /// `curr` coverage span.
-    #[track_caller]
-    fn take_curr(&mut self) -> CurrCovspan {
-        self.some_curr.take().unwrap_or_else(|| bug!("some_curr is None (take_curr)"))
-    }
-
-    #[track_caller]
-    fn prev(&self) -> &PrevCovspan {
-        self.some_prev.as_ref().unwrap_or_else(|| bug!("some_prev is None (prev)"))
-    }
-
-    #[track_caller]
-    fn prev_mut(&mut self) -> &mut PrevCovspan {
-        self.some_prev.as_mut().unwrap_or_else(|| bug!("some_prev is None (prev_mut)"))
+        pending.push(curr);
     }
 
-    #[track_caller]
-    fn take_prev(&mut self) -> PrevCovspan {
-        self.some_prev.take().unwrap_or_else(|| bug!("some_prev is None (take_prev)"))
+    // Drain the rest of the pending list into the refined list.
+    for prev in pending {
+        refined.push(RefinedCovspan { span: prev.span, bcb: prev.bcb });
     }
 
-    /// Advance `prev` to `curr` (if any), and `curr` to the next coverage span in sorted order.
-    fn next_coverage_span(&mut self) -> bool {
-        if let Some(curr) = self.some_curr.take() {
-            self.some_prev = Some(curr.into_prev());
-        }
-        if let Some(SpanFromMir { span, bcb, .. }) = self.sorted_spans_iter.next() {
-            // This code only sees sorted spans after hole-carving, so there should
-            // be no way for `curr` to start before `prev`.
-            if let Some(prev) = &self.some_prev {
-                debug_assert!(prev.span.lo() <= span.lo());
-            }
-            self.some_curr = Some(CurrCovspan::new(span, bcb));
-            debug!(?self.some_prev, ?self.some_curr, "next_coverage_span");
+    // Do one last merge pass, to simplify the output.
+    debug!(?refined, "before merge");
+    refined.dedup_by(|b, a| {
+        if a.is_mergeable(b) {
+            debug!(?a, ?b, "merging list-adjacent refined spans");
+            a.merge_from(b);
             true
         } else {
             false
         }
-    }
+    });
+    debug!(?refined, "after merge");
 
-    /// `curr` overlaps `prev`. If `prev`s span extends left of `curr`s span, keep _only_
-    /// statements that end before `curr.lo()` (if any), and add the portion of the
-    /// combined span for those statements. Any other statements have overlapping spans
-    /// that can be ignored because `curr` and/or other upcoming statements/spans inside
-    /// the overlap area will produce their own counters. This disambiguation process
-    /// avoids injecting multiple counters for overlapping spans, and the potential for
-    /// double-counting.
-    fn cutoff_prev_at_overlapping_curr(&mut self) {
-        debug!(
-            "  different bcbs, overlapping spans, so ignore/drop pending and only add prev \
-            if it has statements that end before curr; prev={:?}",
-            self.prev()
-        );
-
-        let curr_span = self.curr().span;
-        if let Some(prev) = self.take_prev().cutoff_statements_at(curr_span.lo()) {
-            debug!("after cutoff, adding {prev:?}");
-            self.refined_spans.push(prev);
-        } else {
-            debug!("prev was eliminated by cutoff");
-        }
-    }
+    refined
 }
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index 9a2c9059967..e50d59ba5f0 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -8,12 +8,11 @@ use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
 use rustc_serialize::Decodable;
 use tracing::debug;
 
-use crate::debug::{DebugWithInfcx, WithInfcx};
 use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
 use crate::inherent::*;
 use crate::lift::Lift;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
-use crate::{self as ty, InferCtxtLike, Interner, SsoHashSet};
+use crate::{self as ty, Interner, SsoHashSet};
 
 /// Binder is a binder for higher-ranked lifetimes or types. It is part of the
 /// compiler's representation for things like `for<'a> Fn(&'a isize)`
@@ -56,18 +55,6 @@ where
     }
 }
 
-impl<I: Interner, T: DebugWithInfcx<I>> DebugWithInfcx<I> for ty::Binder<I, T> {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        f.debug_tuple("Binder")
-            .field(&this.map(|data| data.as_ref().skip_binder()))
-            .field(&this.data.bound_vars())
-            .finish()
-    }
-}
-
 macro_rules! impl_binder_encode_decode {
     ($($t:ty),+ $(,)?) => {
         $(
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 84d48e14c24..f1683f5449f 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -5,7 +5,7 @@ use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
 use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
 use std::fmt;
 
-use crate::{self as ty, DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
+use crate::{self as ty, DebruijnIndex, Interner};
 
 use self::ConstKind::*;
 
@@ -61,28 +61,19 @@ impl<I: Interner> PartialEq for ConstKind<I> {
 
 impl<I: Interner> fmt::Debug for ConstKind<I> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
-
-impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
         use ConstKind::*;
 
-        match this.data {
+        match self {
             Param(param) => write!(f, "{param:?}"),
-            Infer(var) => write!(f, "{:?}", &this.wrap(var)),
+            Infer(var) => write!(f, "{:?}", &var),
             Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var),
             Placeholder(placeholder) => write!(f, "{placeholder:?}"),
             Unevaluated(uv) => {
-                write!(f, "{:?}", &this.wrap(uv))
+                write!(f, "{:?}", &uv)
             }
-            Value(ty, valtree) => write!(f, "({valtree:?}: {:?})", &this.wrap(ty)),
+            Value(ty, valtree) => write!(f, "({valtree:?}: {:?})", &ty),
             Error(_) => write!(f, "{{const error}}"),
-            Expr(expr) => write!(f, "{:?}", &this.wrap(expr)),
+            Expr(expr) => write!(f, "{:?}", &expr),
         }
     }
 }
@@ -112,17 +103,9 @@ impl<I: Interner> UnevaluatedConst<I> {
 
 impl<I: Interner> fmt::Debug for UnevaluatedConst<I> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
-impl<I: Interner> DebugWithInfcx<I> for UnevaluatedConst<I> {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
         f.debug_struct("UnevaluatedConst")
-            .field("def", &this.data.def)
-            .field("args", &this.wrap(this.data.args))
+            .field("def", &self.def)
+            .field("args", &self.args)
             .finish()
     }
 }
@@ -175,23 +158,6 @@ impl fmt::Debug for InferConst {
         }
     }
 }
-impl<I: Interner> DebugWithInfcx<I> for InferConst {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        match *this.data {
-            InferConst::Var(vid) => match this.infcx.universe_of_ct(vid) {
-                None => write!(f, "{:?}", this.data),
-                Some(universe) => write!(f, "?{}_{}c", vid.index(), universe.index()),
-            },
-            InferConst::EffectVar(vid) => write!(f, "?{}e", vid.index()),
-            InferConst::Fresh(_) => {
-                unreachable!()
-            }
-        }
-    }
-}
 
 #[cfg(feature = "nightly")]
 impl<CTX> HashStable<CTX> for InferConst {
diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs
deleted file mode 100644
index c206f3ccdb5..00000000000
--- a/compiler/rustc_type_ir/src/debug.rs
+++ /dev/null
@@ -1,146 +0,0 @@
-use crate::{
-    ConstVid, EffectVid, FloatVid, InferCtxtLike, IntVid, Interner, RegionVid, TyVid, UniverseIndex,
-};
-
-use core::fmt;
-use std::marker::PhantomData;
-
-pub struct NoInfcx<I>(PhantomData<I>);
-
-impl<I: Interner> InferCtxtLike for NoInfcx<I> {
-    type Interner = I;
-
-    fn interner(&self) -> Self::Interner {
-        unreachable!()
-    }
-
-    fn universe_of_ty(&self, _ty: TyVid) -> Option<UniverseIndex> {
-        None
-    }
-
-    fn universe_of_lt(&self, _lt: RegionVid) -> Option<UniverseIndex> {
-        None
-    }
-
-    fn universe_of_ct(&self, _ct: ConstVid) -> Option<UniverseIndex> {
-        None
-    }
-
-    fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> I::Ty {
-        panic!("cannot resolve {vid:?}")
-    }
-
-    fn opportunistic_resolve_int_var(&self, vid: IntVid) -> I::Ty {
-        panic!("cannot resolve {vid:?}")
-    }
-
-    fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> I::Ty {
-        panic!("cannot resolve {vid:?}")
-    }
-
-    fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> I::Const {
-        panic!("cannot resolve {vid:?}")
-    }
-
-    fn opportunistic_resolve_effect_var(&self, vid: EffectVid) -> I::Const {
-        panic!("cannot resolve {vid:?}")
-    }
-
-    fn opportunistic_resolve_lt_var(&self, vid: crate::RegionVid) -> I::Region {
-        panic!("cannot resolve {vid:?}")
-    }
-
-    fn defining_opaque_types(&self) -> I::DefiningOpaqueTypes {
-        Default::default()
-    }
-}
-
-pub trait DebugWithInfcx<I: Interner>: fmt::Debug {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result;
-}
-
-impl<I: Interner, T: DebugWithInfcx<I> + ?Sized> DebugWithInfcx<I> for &'_ T {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result {
-        <T as DebugWithInfcx<I>>::fmt(this.map(|&data| data), f)
-    }
-}
-
-impl<I: Interner, T: DebugWithInfcx<I>> DebugWithInfcx<I> for [T] {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result {
-        match f.alternate() {
-            true => {
-                write!(f, "[\n")?;
-                for element in this.data.iter() {
-                    write!(f, "{:?},\n", &this.wrap(element))?;
-                }
-                write!(f, "]")
-            }
-            false => {
-                write!(f, "[")?;
-                if this.data.len() > 0 {
-                    for element in &this.data[..(this.data.len() - 1)] {
-                        write!(f, "{:?}, ", &this.wrap(element))?;
-                    }
-                    if let Some(element) = this.data.last() {
-                        write!(f, "{:?}", &this.wrap(element))?;
-                    }
-                }
-                write!(f, "]")
-            }
-        }
-    }
-}
-
-pub struct WithInfcx<'a, Infcx: InferCtxtLike, T> {
-    pub data: T,
-    pub infcx: &'a Infcx,
-}
-
-impl<Infcx: InferCtxtLike, T: Copy> Copy for WithInfcx<'_, Infcx, T> {}
-
-impl<Infcx: InferCtxtLike, T: Clone> Clone for WithInfcx<'_, Infcx, T> {
-    fn clone(&self) -> Self {
-        Self { data: self.data.clone(), infcx: self.infcx }
-    }
-}
-
-impl<'a, I: Interner, T> WithInfcx<'a, NoInfcx<I>, T> {
-    pub fn with_no_infcx(data: T) -> Self {
-        Self { data, infcx: &NoInfcx(PhantomData) }
-    }
-}
-
-impl<'a, Infcx: InferCtxtLike, T> WithInfcx<'a, Infcx, T> {
-    pub fn new(data: T, infcx: &'a Infcx) -> Self {
-        Self { data, infcx }
-    }
-
-    pub fn wrap<U>(self, u: U) -> WithInfcx<'a, Infcx, U> {
-        WithInfcx { data: u, infcx: self.infcx }
-    }
-
-    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> WithInfcx<'a, Infcx, U> {
-        WithInfcx { data: f(self.data), infcx: self.infcx }
-    }
-
-    pub fn as_ref(&self) -> WithInfcx<'a, Infcx, &T> {
-        WithInfcx { data: &self.data, infcx: self.infcx }
-    }
-}
-
-impl<Infcx: InferCtxtLike, T: DebugWithInfcx<Infcx::Interner>> fmt::Debug
-    for WithInfcx<'_, Infcx, T>
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        DebugWithInfcx::fmt(self.as_ref(), f)
-    }
-}
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 205a1e5f100..2fc765f1c8f 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -12,11 +12,11 @@ use rustc_ast_ir::Mutability;
 use crate::fold::{TypeFoldable, TypeSuperFoldable};
 use crate::relate::Relate;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
-use crate::{self as ty, CollectAndApply, DebugWithInfcx, Interner, UpcastFrom};
+use crate::{self as ty, CollectAndApply, Interner, UpcastFrom};
 
 pub trait Ty<I: Interner<Ty = Self>>:
     Copy
-    + DebugWithInfcx<I>
+    + Debug
     + Hash
     + Eq
     + Into<I::GenericArg>
@@ -116,7 +116,7 @@ pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq + TypeVis
 
 pub trait Region<I: Interner<Region = Self>>:
     Copy
-    + DebugWithInfcx<I>
+    + Debug
     + Hash
     + Eq
     + Into<I::GenericArg>
@@ -134,7 +134,7 @@ pub trait Region<I: Interner<Region = Self>>:
 
 pub trait Const<I: Interner<Const = Self>>:
     Copy
-    + DebugWithInfcx<I>
+    + Debug
     + Hash
     + Eq
     + Into<I::GenericArg>
@@ -166,7 +166,7 @@ pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
 
 pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
     Copy
-    + DebugWithInfcx<I>
+    + Debug
     + Hash
     + Eq
     + IntoIterator<Item = I::GenericArg>
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index ad1d2753b28..b7f412ecb8e 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -9,7 +9,7 @@ use crate::ir_print::IrPrint;
 use crate::relate::Relate;
 use crate::solve::inspect::CanonicalGoalEvaluationStep;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
-use crate::{self as ty, DebugWithInfcx};
+use crate::{self as ty};
 
 pub trait Interner:
     Sized
@@ -32,7 +32,7 @@ pub trait Interner:
     type GenericArgs: GenericArgs<Self>;
     type GenericArgsSlice: Copy + Debug + Hash + Eq + Deref<Target = [Self::GenericArg]>;
     type GenericArg: Copy
-        + DebugWithInfcx<Self>
+        + Debug
         + Hash
         + Eq
         + IntoKind<Kind = ty::GenericArgKind<Self>>
@@ -74,9 +74,9 @@ pub trait Interner:
 
     // Things stored inside of tys
     type ErrorGuaranteed: Copy + Debug + Hash + Eq;
-    type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Eq + Relate<Self>;
+    type BoundExistentialPredicates: Copy + Debug + Hash + Eq + Relate<Self>;
     type AllocId: Copy + Debug + Hash + Eq;
-    type Pat: Copy + Debug + Hash + Eq + DebugWithInfcx<Self> + Relate<Self>;
+    type Pat: Copy + Debug + Hash + Eq + Debug + Relate<Self>;
     type Safety: Safety<Self> + TypeFoldable<Self> + Relate<Self>;
     type Abi: Abi<Self> + TypeFoldable<Self> + Relate<Self>;
 
@@ -86,7 +86,7 @@ pub trait Interner:
     type ParamConst: Copy + Debug + Hash + Eq + ParamLike;
     type BoundConst: Copy + Debug + Hash + Eq + BoundVarLike<Self>;
     type ValueConst: Copy + Debug + Hash + Eq;
-    type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Eq + Relate<Self>;
+    type ExprConst: Copy + Debug + Hash + Eq + Relate<Self>;
 
     // Kinds of regions
     type Region: Region<Self>;
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 7072b3de07d..a76e278cc05 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -42,7 +42,6 @@ mod macros;
 mod binder;
 mod canonical;
 mod const_kind;
-mod debug;
 mod flags;
 mod generic_arg;
 mod infcx;
@@ -59,7 +58,6 @@ pub use canonical::*;
 #[cfg(feature = "nightly")]
 pub use codec::*;
 pub use const_kind::*;
-pub use debug::{DebugWithInfcx, WithInfcx};
 pub use flags::*;
 pub use generic_arg::*;
 pub use infcx::InferCtxtLike;
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index 63a4c2e9d1f..c0713dc50d2 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -9,7 +9,7 @@ use crate::inherent::*;
 use crate::lift::Lift;
 use crate::upcast::Upcast;
 use crate::visit::TypeVisitableExt as _;
-use crate::{self as ty, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
+use crate::{self as ty, Interner};
 
 /// `A: 'region`
 #[derive(derivative::Derivative)]
@@ -248,16 +248,6 @@ pub enum ExistentialPredicate<I: Interner> {
     AutoTrait(I::DefId),
 }
 
-// FIXME: Implement this the right way after
-impl<I: Interner> DebugWithInfcx<I> for ExistentialPredicate<I> {
-    fn fmt<Infcx: rustc_type_ir::InferCtxtLike<Interner = I>>(
-        this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result {
-        fmt::Debug::fmt(&this.data, f)
-    }
-}
-
 impl<I: Interner> ty::Binder<I, ExistentialPredicate<I>> {
     /// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`),
     /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self`
@@ -459,7 +449,8 @@ impl AliasTermKind {
     Copy(bound = ""),
     Hash(bound = ""),
     PartialEq(bound = ""),
-    Eq(bound = "")
+    Eq(bound = ""),
+    Debug(bound = "")
 )]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
@@ -493,23 +484,6 @@ pub struct AliasTerm<I: Interner> {
     _use_alias_term_new_instead: (),
 }
 
-impl<I: Interner> std::fmt::Debug for AliasTerm<I> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
-impl<I: Interner> DebugWithInfcx<I> for AliasTerm<I> {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut std::fmt::Formatter<'_>,
-    ) -> std::fmt::Result {
-        f.debug_struct("AliasTerm")
-            .field("args", &this.map(|data| data.args))
-            .field("def_id", &this.data.def_id)
-            .finish()
-    }
-}
-
 impl<I: Interner> AliasTerm<I> {
     pub fn new(
         interner: I,
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index 48ade273289..37c9532ad89 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -4,7 +4,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
 use std::fmt;
 
-use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
+use crate::{DebruijnIndex, Interner};
 
 use self::RegionKind::*;
 
@@ -18,18 +18,6 @@ rustc_index::newtype_index! {
     pub struct RegionVid {}
 }
 
-impl<I: Interner> DebugWithInfcx<I> for RegionVid {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        match this.infcx.universe_of_lt(*this.data) {
-            Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()),
-            None => write!(f, "{:?}", this.data),
-        }
-    }
-}
-
 /// Representation of regions. Note that the NLL checker uses a distinct
 /// representation of regions. For this reason, it internally replaces all the
 /// regions with inference variables -- the index of the variable is then used
@@ -230,12 +218,9 @@ impl<I: Interner> PartialEq for RegionKind<I> {
     }
 }
 
-impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        match this.data {
+impl<I: Interner> fmt::Debug for RegionKind<I> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
             ReEarlyParam(data) => write!(f, "{data:?}"),
 
             ReBound(binder_id, bound_region) => {
@@ -247,7 +232,7 @@ impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
 
             ReStatic => f.write_str("'static"),
 
-            ReVar(vid) => write!(f, "{:?}", &this.wrap(vid)),
+            ReVar(vid) => write!(f, "{:?}", &vid),
 
             RePlaceholder(placeholder) => write!(f, "{placeholder:?}"),
 
@@ -260,11 +245,6 @@ impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
         }
     }
 }
-impl<I: Interner> fmt::Debug for RegionKind<I> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
 
 #[cfg(feature = "nightly")]
 // This is not a derived impl because a derive would require `I: HashStable`
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 71f3862226d..8b4ad2f5ed0 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -10,7 +10,7 @@ use std::fmt;
 pub use self::closure::*;
 use self::TyKind::*;
 use crate::inherent::*;
-use crate::{self as ty, DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
+use crate::{self as ty, DebruijnIndex, Interner};
 
 use rustc_ast_ir::Mutability;
 
@@ -341,12 +341,10 @@ impl<I: Interner> PartialEq for TyKind<I> {
     }
 }
 
-impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result {
-        match this.data {
+// This is manually implemented because a derive would require `I: Debug`
+impl<I: Interner> fmt::Debug for TyKind<I> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
             Bool => write!(f, "bool"),
             Char => write!(f, "char"),
             Int(i) => write!(f, "{i:?}"),
@@ -369,27 +367,23 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
             }
             Foreign(d) => f.debug_tuple("Foreign").field(d).finish(),
             Str => write!(f, "str"),
-            Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)),
-            Pat(t, p) => write!(f, "pattern_type!({:?} is {:?})", &this.wrap(t), &this.wrap(p)),
-            Slice(t) => write!(f, "[{:?}]", &this.wrap(t)),
-            RawPtr(ty, mutbl) => write!(f, "*{} {:?}", mutbl.ptr_str(), this.wrap(ty)),
-            Ref(r, t, m) => write!(f, "&{:?} {}{:?}", this.wrap(r), m.prefix_str(), this.wrap(t)),
-            FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&this.wrap(s)).finish(),
-            FnPtr(s) => write!(f, "{:?}", &this.wrap(s)),
+            Array(t, c) => write!(f, "[{:?}; {:?}]", &t, &c),
+            Pat(t, p) => write!(f, "pattern_type!({:?} is {:?})", &t, &p),
+            Slice(t) => write!(f, "[{:?}]", &t),
+            RawPtr(ty, mutbl) => write!(f, "*{} {:?}", mutbl.ptr_str(), ty),
+            Ref(r, t, m) => write!(f, "&{:?} {}{:?}", r, m.prefix_str(), t),
+            FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&s).finish(),
+            FnPtr(s) => write!(f, "{:?}", &s),
             Dynamic(p, r, repr) => match repr {
-                DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &this.wrap(p), &this.wrap(r)),
+                DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &p, &r),
                 DynKind::DynStar => {
-                    write!(f, "dyn* {:?} + {:?}", &this.wrap(p), &this.wrap(r))
+                    write!(f, "dyn* {:?} + {:?}", &p, &r)
                 }
             },
-            Closure(d, s) => f.debug_tuple("Closure").field(d).field(&this.wrap(s)).finish(),
-            CoroutineClosure(d, s) => {
-                f.debug_tuple("CoroutineClosure").field(d).field(&this.wrap(s)).finish()
-            }
-            Coroutine(d, s) => f.debug_tuple("Coroutine").field(d).field(&this.wrap(s)).finish(),
-            CoroutineWitness(d, s) => {
-                f.debug_tuple("CoroutineWitness").field(d).field(&this.wrap(s)).finish()
-            }
+            Closure(d, s) => f.debug_tuple("Closure").field(d).field(&s).finish(),
+            CoroutineClosure(d, s) => f.debug_tuple("CoroutineClosure").field(d).field(&s).finish(),
+            Coroutine(d, s) => f.debug_tuple("Coroutine").field(d).field(&s).finish(),
+            CoroutineWitness(d, s) => f.debug_tuple("CoroutineWitness").field(d).field(&s).finish(),
             Never => write!(f, "!"),
             Tuple(t) => {
                 write!(f, "(")?;
@@ -398,7 +392,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
                     if count > 0 {
                         write!(f, ", ")?;
                     }
-                    write!(f, "{:?}", &this.wrap(ty))?;
+                    write!(f, "{:?}", &ty)?;
                     count += 1;
                 }
                 // unary tuples need a trailing comma
@@ -407,23 +401,16 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
                 }
                 write!(f, ")")
             }
-            Alias(i, a) => f.debug_tuple("Alias").field(i).field(&this.wrap(a)).finish(),
+            Alias(i, a) => f.debug_tuple("Alias").field(i).field(&a).finish(),
             Param(p) => write!(f, "{p:?}"),
             Bound(d, b) => crate::debug_bound_var(f, *d, b),
             Placeholder(p) => write!(f, "{p:?}"),
-            Infer(t) => write!(f, "{:?}", this.wrap(t)),
+            Infer(t) => write!(f, "{:?}", t),
             TyKind::Error(_) => write!(f, "{{type error}}"),
         }
     }
 }
 
-// This is manually implemented because a derive would require `I: Debug`
-impl<I: Interner> fmt::Debug for TyKind<I> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
-
 /// Represents the projection of an associated, opaque, or lazy-type-alias type.
 ///
 /// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
@@ -435,7 +422,8 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
     Copy(bound = ""),
     Hash(bound = ""),
     PartialEq(bound = ""),
-    Eq(bound = "")
+    Eq(bound = ""),
+    Debug(bound = "")
 )]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
@@ -555,23 +543,6 @@ impl<I: Interner> AliasTy<I> {
     }
 }
 
-impl<I: Interner> fmt::Debug for AliasTy<I> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
-impl<I: Interner> DebugWithInfcx<I> for AliasTy<I> {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result {
-        f.debug_struct("AliasTy")
-            .field("args", &this.map(|data| data.args))
-            .field("def_id", &this.data.def_id)
-            .finish()
-    }
-}
-
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
 pub enum IntTy {
@@ -968,24 +939,6 @@ impl fmt::Debug for InferTy {
     }
 }
 
-impl<I: Interner> DebugWithInfcx<I> for InferTy {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result {
-        match this.data {
-            InferTy::TyVar(vid) => {
-                if let Some(universe) = this.infcx.universe_of_ty(*vid) {
-                    write!(f, "?{}_{}t", vid.index(), universe.index())
-                } else {
-                    write!(f, "{:?}", this.data)
-                }
-            }
-            _ => write!(f, "{:?}", this.data),
-        }
-    }
-}
-
 #[derive(derivative::Derivative)]
 #[derivative(
     Clone(bound = ""),
@@ -1078,15 +1031,7 @@ impl<I: Interner> ty::Binder<I, FnSig<I>> {
 
 impl<I: Interner> fmt::Debug for FnSig<I> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
-impl<I: Interner> DebugWithInfcx<I> for FnSig<I> {
-    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result {
-        let sig = this.data;
+        let sig = self;
         let FnSig { inputs_and_output: _, c_variadic, safety, abi } = sig;
 
         write!(f, "{}", safety.prefix_str())?;
@@ -1100,7 +1045,7 @@ impl<I: Interner> DebugWithInfcx<I> for FnSig<I> {
             if i > 0 {
                 write!(f, ", ")?;
             }
-            write!(f, "{:?}", &this.wrap(ty))?;
+            write!(f, "{:?}", &ty)?;
         }
         if *c_variadic {
             if inputs.is_empty() {
@@ -1113,7 +1058,7 @@ impl<I: Interner> DebugWithInfcx<I> for FnSig<I> {
 
         match output.kind() {
             Tuple(list) if list.is_empty() => Ok(()),
-            _ => write!(f, " -> {:?}", &this.wrap(sig.output())),
+            _ => write!(f, " -> {:?}", sig.output()),
         }
     }
 }
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index da18fdc6e1d..042a8c9925f 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -404,9 +404,9 @@ fn request_by_type_tag<'a, I>(err: &'a (impl Error + ?Sized)) -> Option<I::Reifi
 where
     I: tags::Type<'a>,
 {
-    let mut tagged = TaggedOption::<'a, I>(None);
+    let mut tagged = Tagged { tag_id: TypeId::of::<I>(), value: TaggedOption::<'a, I>(None) };
     err.provide(tagged.as_request());
-    tagged.0
+    tagged.value.0
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -507,16 +507,9 @@ where
 ///
 #[unstable(feature = "error_generic_member_access", issue = "99301")]
 #[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
-pub struct Request<'a>(dyn Erased<'a> + 'a);
+pub struct Request<'a>(Tagged<dyn Erased<'a> + 'a>);
 
 impl<'a> Request<'a> {
-    /// Create a new `&mut Request` from a `&mut dyn Erased` trait object.
-    fn new<'b>(erased: &'b mut (dyn Erased<'a> + 'a)) -> &'b mut Request<'a> {
-        // SAFETY: transmuting `&mut (dyn Erased<'a> + 'a)` to `&mut Request<'a>` is safe since
-        // `Request` is repr(transparent).
-        unsafe { &mut *(erased as *mut dyn Erased<'a> as *mut Request<'a>) }
-    }
-
     /// Provide a value or other type with only static lifetimes.
     ///
     /// # Examples
@@ -940,27 +933,28 @@ pub(crate) mod tags {
 #[repr(transparent)]
 pub(crate) struct TaggedOption<'a, I: tags::Type<'a>>(pub Option<I::Reified>);
 
-impl<'a, I: tags::Type<'a>> TaggedOption<'a, I> {
+impl<'a, I: tags::Type<'a>> Tagged<TaggedOption<'a, I>> {
     pub(crate) fn as_request(&mut self) -> &mut Request<'a> {
-        Request::new(self as &mut (dyn Erased<'a> + 'a))
+        let erased = self as &mut Tagged<dyn Erased<'a> + 'a>;
+        // SAFETY: transmuting `&mut Tagged<dyn Erased<'a> + 'a>` to `&mut Request<'a>` is safe since
+        // `Request` is repr(transparent).
+        unsafe { &mut *(erased as *mut Tagged<dyn Erased<'a>> as *mut Request<'a>) }
     }
 }
 
 /// Represents a type-erased but identifiable object.
 ///
 /// This trait is exclusively implemented by the `TaggedOption` type.
-unsafe trait Erased<'a>: 'a {
-    /// The `TypeId` of the erased type.
-    fn tag_id(&self) -> TypeId;
-}
+unsafe trait Erased<'a>: 'a {}
 
-unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> {
-    fn tag_id(&self) -> TypeId {
-        TypeId::of::<I>()
-    }
+unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> {}
+
+struct Tagged<E: ?Sized> {
+    tag_id: TypeId,
+    value: E,
 }
 
-impl<'a> dyn Erased<'a> + 'a {
+impl<'a> Tagged<dyn Erased<'a> + 'a> {
     /// Returns some reference to the dynamic value if it is tagged with `I`,
     /// or `None` otherwise.
     #[inline]
@@ -968,9 +962,9 @@ impl<'a> dyn Erased<'a> + 'a {
     where
         I: tags::Type<'a>,
     {
-        if self.tag_id() == TypeId::of::<I>() {
+        if self.tag_id == TypeId::of::<I>() {
             // SAFETY: Just checked whether we're pointing to an I.
-            Some(unsafe { &*(self as *const Self).cast::<TaggedOption<'a, I>>() })
+            Some(&unsafe { &*(self as *const Self).cast::<Tagged<TaggedOption<'a, I>>>() }.value)
         } else {
             None
         }
@@ -983,9 +977,12 @@ impl<'a> dyn Erased<'a> + 'a {
     where
         I: tags::Type<'a>,
     {
-        if self.tag_id() == TypeId::of::<I>() {
-            // SAFETY: Just checked whether we're pointing to an I.
-            Some(unsafe { &mut *(self as *mut Self).cast::<TaggedOption<'a, I>>() })
+        if self.tag_id == TypeId::of::<I>() {
+            Some(
+                // SAFETY: Just checked whether we're pointing to an I.
+                &mut unsafe { &mut *(self as *mut Self).cast::<Tagged<TaggedOption<'a, I>>>() }
+                    .value,
+            )
         } else {
             None
         }
diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs
index df8f441bf35..78cf1d2e98e 100644
--- a/library/core/src/panic/panic_info.rs
+++ b/library/core/src/panic/panic_info.rs
@@ -29,9 +29,8 @@ impl<'a> PanicInfo<'a> {
         PanicInfo { location, message, can_unwind, force_no_backtrace }
     }
 
-    /// If the `panic!` macro from the `core` crate (not from `std`)
-    /// was used with a formatting string and some additional arguments,
-    /// returns that message ready to be used for example with [`fmt::write`]
+    /// The message that was given to the `panic!` macro,
+    /// ready to be formatted with e.g. [`fmt::write`].
     #[must_use]
     #[unstable(feature = "panic_info_message", issue = "66745")]
     pub fn message(&self) -> fmt::Arguments<'_> {
@@ -72,7 +71,7 @@ impl<'a> PanicInfo<'a> {
 
     /// Returns the payload associated with the panic.
     ///
-    /// On `core::panic::PanicInfo`, this method never returns anything useful.
+    /// On this type, `core::panic::PanicInfo`, this method never returns anything useful.
     /// It only exists because of compatibility with [`std::panic::PanicHookInfo`],
     /// which used to be the same type.
     ///
@@ -80,7 +79,7 @@ impl<'a> PanicInfo<'a> {
     ///
     /// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
     /// [`std::panic::PanicHookInfo::payload`]: ../../std/panic/struct.PanicHookInfo.html#method.payload
-    #[deprecated(since = "1.77.0", note = "this never returns anything useful")]
+    #[deprecated(since = "1.81.0", note = "this never returns anything useful")]
     #[stable(feature = "panic_hooks", since = "1.10.0")]
     #[allow(deprecated, deprecated_in_future)]
     pub fn payload(&self) -> &(dyn crate::any::Any + Send) {
diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs
index c29dd62bc06..d53674d3c5f 100644
--- a/library/std/src/os/linux/raw.rs
+++ b/library/std/src/os/linux/raw.rs
@@ -244,7 +244,11 @@ mod arch {
     pub use libc::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t};
 }
 
-#[cfg(target_arch = "aarch64")]
+#[cfg(any(
+    target_arch = "aarch64",
+    // Arm64EC is Windows-only, but docs are always build as Linux, so re-use AArch64 for Arm64EC.
+    all(doc, target_arch = "arm64ec")
+))]
 mod arch {
     use crate::os::raw::{c_int, c_long};
 
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 5282c00fcca..c5d1a893ee8 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -202,10 +202,7 @@ impl fmt::Display for PanicHookInfo<'_> {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         formatter.write_str("panicked at ")?;
         self.location.fmt(formatter)?;
-        if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
-            formatter.write_str(":\n")?;
-            formatter.write_str(payload)?;
-        } else if let Some(payload) = self.payload.downcast_ref::<String>() {
+        if let Some(payload) = self.payload_as_str() {
             formatter.write_str(":\n")?;
             formatter.write_str(payload)?;
         }
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 1db763735e6..010e1b8fd51 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -428,6 +428,7 @@ auto:
       RUST_CONFIGURE_ARGS: >-
         --build=x86_64-pc-windows-msvc
         --host=aarch64-pc-windows-msvc
+        --target=aarch64-pc-windows-msvc,arm64ec-pc-windows-msvc
         --enable-full-tools
         --enable-profiler
       SCRIPT: python x.py dist bootstrap --include-default-paths
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index da97de1f716..c672cff7452 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -146,6 +146,7 @@ target | std | notes
 [`arm-linux-androideabi`](platform-support/android.md) | ✓ | Armv6 Android
 `arm-unknown-linux-musleabi` | ✓ | Armv6 Linux with musl 1.2.3
 `arm-unknown-linux-musleabihf` | ✓ | Armv6 Linux with musl 1.2.3, hardfloat
+[`arm64ec-pc-windows-msvc`](platform-support/arm64ec-pc-windows-msvc.md) | ✓ | Arm64EC Windows MSVC
 [`armebv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian
 [`armebv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian, hardfloat
 `armv5te-unknown-linux-gnueabi` | ✓ | Armv5TE Linux (kernel 4.4, glibc 2.23)
@@ -240,7 +241,6 @@ target | std | host | notes
 -------|:---:|:----:|-------
 [`arm64e-apple-ios`](platform-support/arm64e-apple-ios.md) | ✓ | | ARM64e Apple iOS
 [`arm64e-apple-darwin`](platform-support/arm64e-apple-darwin.md)  | ✓ | ✓ | ARM64e Apple Darwin
-[`arm64ec-pc-windows-msvc`](platform-support/arm64ec-pc-windows-msvc.md) | ? | | Arm64EC Windows MSVC
 [`aarch64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ |  | Apple Catalyst on ARM64
 [`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ✓ |  | ARM64 tvOS
 [`aarch64-apple-tvos-sim`](platform-support/apple-tvos.md) | ✓ |  | ARM64 tvOS Simulator
diff --git a/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md
index 2e827535862..dcabd21a83e 100644
--- a/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md
+++ b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md
@@ -1,6 +1,6 @@
 # `arm64ec-pc-windows-msvc`
 
-**Tier: 3**
+**Tier: 2**
 
 Arm64EC ("Emulation Compatible") for mixed architecture (AArch64 and x86_64)
 applications on AArch64 Windows 11. See <https://learn.microsoft.com/en-us/windows/arm/arm64ec>.
@@ -21,6 +21,9 @@ Only supported backend is LLVM 18 or above:
 * 18.1.4 fixed linking issue for some intrinsics implemented in
   `compiler_builtins`.
 
+Visual Studio 2022 (or above) with the "ARM64/ARM64EC built tools" component and
+the Windows 11 SDK are required.
+
 ### Reusing code from other architectures - x86_64 or AArch64?
 
 Arm64EC uses `arm64ec` as its `target_arch`, but it is possible to reuse
@@ -62,10 +65,8 @@ target = [ "arm64ec-pc-windows-msvc" ]
 
 ## Building Rust programs
 
-Rust does not yet ship pre-compiled artifacts for this target. To compile for
-this target, you will either need to build Rust with the target enabled (see
-"Building the target" above), or build your own copy using `build-std` or
-similar.
+These targets are distributed through `rustup`, and otherwise require no
+special configuration.
 
 ## Testing
 
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index bed76263b45..9f33e431274 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -71,6 +71,7 @@ static TARGETS: &[&str] = &[
     "arm-unknown-linux-gnueabihf",
     "arm-unknown-linux-musleabi",
     "arm-unknown-linux-musleabihf",
+    "arm64ec-pc-windows-msvc",
     "armv5te-unknown-linux-gnueabi",
     "armv5te-unknown-linux-musleabi",
     "armv7-linux-androideabi",
diff --git a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs
index f71df9a1c90..982d57b7372 100644
--- a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs
+++ b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs
@@ -1,5 +1,5 @@
-// Validation stops this too early.
-//@compile-flags: -Zmiri-disable-validation
+// Validation and SB stop this too early.
+//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
 
 trait T1 {
     #[allow(dead_code)]
diff --git a/src/tools/miri/tests/pass/issues/issue-miri-3541-dyn-vtable-trait-normalization.rs b/src/tools/miri/tests/pass/issues/issue-miri-3541-dyn-vtable-trait-normalization.rs
new file mode 100644
index 00000000000..c46031de2d8
--- /dev/null
+++ b/src/tools/miri/tests/pass/issues/issue-miri-3541-dyn-vtable-trait-normalization.rs
@@ -0,0 +1,40 @@
+#![feature(ptr_metadata)]
+// This test is the result of minimizing the `emplacable` crate to reproduce
+// <https://github.com/rust-lang/miri/issues/3541>.
+
+use std::{ops::FnMut, ptr::Pointee};
+
+pub type EmplacerFn<'a, T> = dyn for<'b> FnMut(<T as Pointee>::Metadata) + 'a;
+
+#[repr(transparent)]
+pub struct Emplacer<'a, T>(EmplacerFn<'a, T>)
+where
+    T: ?Sized;
+
+impl<'a, T> Emplacer<'a, T>
+where
+    T: ?Sized,
+{
+    pub unsafe fn from_fn<'b>(emplacer_fn: &'b mut EmplacerFn<'a, T>) -> &'b mut Self {
+        // This used to trigger:
+        // constructing invalid value: wrong trait in wide pointer vtable: expected
+        // `std::ops::FnMut(<[std::boxed::Box<i32>] as std::ptr::Pointee>::Metadata)`, but encountered
+        // `std::ops::FnMut<(usize,)>`.
+        unsafe { &mut *((emplacer_fn as *mut EmplacerFn<'a, T>) as *mut Self) }
+    }
+}
+
+pub fn box_new_with<T>()
+where
+    T: ?Sized,
+{
+    let emplacer_closure = &mut |_meta| {
+        unreachable!();
+    };
+
+    unsafe { Emplacer::<T>::from_fn(emplacer_closure) };
+}
+
+fn main() {
+    box_new_with::<[Box<i32>]>();
+}
diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf
-Subproject 72daa50ce2350f5a9b5ae6dc3ad6babccd14ec0
+Subproject c64bb60dd1636922b1ccbb82867bed934a99dbc
diff --git a/tests/coverage/assert-ne.cov-map b/tests/coverage/assert-ne.cov-map
new file mode 100644
index 00000000000..6d9906fd7f5
--- /dev/null
+++ b/tests/coverage/assert-ne.cov-map
@@ -0,0 +1,13 @@
+Function name: assert_ne::main
+Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 08, 01, 03, 1c, 05, 04, 0d, 00, 13, 02, 02, 0d, 00, 13, 09, 03, 05, 01, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 1
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+Number of file 0 mappings: 4
+- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28)
+- Code(Counter(1)) at (prev + 4, 13) to (start + 0, 19)
+- Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19)
+    = (c0 - c1)
+- Code(Counter(2)) at (prev + 3, 5) to (start + 1, 2)
+
diff --git a/tests/coverage/assert-ne.coverage b/tests/coverage/assert-ne.coverage
new file mode 100644
index 00000000000..236a8fd1385
--- /dev/null
+++ b/tests/coverage/assert-ne.coverage
@@ -0,0 +1,23 @@
+   LL|       |//@ edition: 2021
+   LL|       |
+   LL|       |use core::hint::black_box;
+   LL|       |
+   LL|       |#[derive(Debug, PartialEq)]
+   LL|       |struct Foo(u32);
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    assert_ne!(
+   LL|      1|        Foo(5), // Make sure this expression's span isn't lost.
+   LL|      1|        if black_box(false) {
+   LL|      0|            Foo(0) //
+   LL|       |        } else {
+   LL|      1|            Foo(1) //
+   LL|       |        }
+   LL|       |    );
+   LL|      1|    ()
+   LL|      1|}
+   LL|       |
+   LL|       |// This test is a short fragment extracted from `issue-84561.rs`, highlighting
+   LL|       |// a particular span of code that can easily be lost if overlapping spans are
+   LL|       |// processed incorrectly.
+
diff --git a/tests/coverage/assert-ne.rs b/tests/coverage/assert-ne.rs
new file mode 100644
index 00000000000..8a8fe089804
--- /dev/null
+++ b/tests/coverage/assert-ne.rs
@@ -0,0 +1,22 @@
+//@ edition: 2021
+
+use core::hint::black_box;
+
+#[derive(Debug, PartialEq)]
+struct Foo(u32);
+
+fn main() {
+    assert_ne!(
+        Foo(5), // Make sure this expression's span isn't lost.
+        if black_box(false) {
+            Foo(0) //
+        } else {
+            Foo(1) //
+        }
+    );
+    ()
+}
+
+// This test is a short fragment extracted from `issue-84561.rs`, highlighting
+// a particular span of code that can easily be lost if overlapping spans are
+// processed incorrectly.
diff --git a/tests/coverage/loop-break.cov-map b/tests/coverage/loop-break.cov-map
new file mode 100644
index 00000000000..890d5d84539
--- /dev/null
+++ b/tests/coverage/loop-break.cov-map
@@ -0,0 +1,14 @@
+Function name: loop_break::main
+Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 03, 01, 00, 0b, 03, 02, 0c, 00, 27, 01, 01, 0d, 00, 12, 05, 01, 0a, 00, 0b, 01, 02, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 1
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+Number of file 0 mappings: 5
+- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 11)
+- Code(Expression(0, Add)) at (prev + 2, 12) to (start + 0, 39)
+    = (c0 + c1)
+- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 18)
+- Code(Counter(1)) at (prev + 1, 10) to (start + 0, 11)
+- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2)
+
diff --git a/tests/coverage/loop-break.coverage b/tests/coverage/loop-break.coverage
new file mode 100644
index 00000000000..1b7c64fb68d
--- /dev/null
+++ b/tests/coverage/loop-break.coverage
@@ -0,0 +1,14 @@
+   LL|       |//@ edition: 2021
+   LL|       |
+   LL|      1|fn main() {
+   LL|       |    loop {
+   LL|      1|        if core::hint::black_box(true) {
+   LL|      1|            break;
+   LL|      0|        }
+   LL|       |    }
+   LL|      1|}
+   LL|       |
+   LL|       |// This test is a lightly-modified version of `tests/mir-opt/coverage/instrument_coverage.rs`.
+   LL|       |// If this test needs to be blessed, then the mir-opt version probably needs to
+   LL|       |// be blessed too!
+
diff --git a/tests/coverage/loop-break.rs b/tests/coverage/loop-break.rs
new file mode 100644
index 00000000000..9a842225e83
--- /dev/null
+++ b/tests/coverage/loop-break.rs
@@ -0,0 +1,13 @@
+//@ edition: 2021
+
+fn main() {
+    loop {
+        if core::hint::black_box(true) {
+            break;
+        }
+    }
+}
+
+// This test is a lightly-modified version of `tests/mir-opt/coverage/instrument_coverage.rs`.
+// If this test needs to be blessed, then the mir-opt version probably needs to
+// be blessed too!
diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
index d2a0fb0cb3c..c0f16ee7ec0 100644
--- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
+++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
@@ -5,12 +5,15 @@
             ty: Coroutine(
                 DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
                 [
-                (),
-                std::future::ResumeTy,
-                (),
-                (),
-                CoroutineWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []),
-                (),
+                    (),
+                    std::future::ResumeTy,
+                    (),
+                    (),
+                    CoroutineWitness(
+                        DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
+                        [],
+                    ),
+                    (),
                 ],
             ),
             source_info: SourceInfo {
@@ -23,12 +26,15 @@
             ty: Coroutine(
                 DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
                 [
-                (),
-                std::future::ResumeTy,
-                (),
-                (),
-                CoroutineWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []),
-                (),
+                    (),
+                    std::future::ResumeTy,
+                    (),
+                    (),
+                    CoroutineWitness(
+                        DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
+                        [],
+                    ),
+                    (),
                 ],
             ),
             source_info: SourceInfo {
diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
index 01876b494c5..a594c44c316 100644
--- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
@@ -9,7 +9,7 @@
   
 +     coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Add, rhs: Counter(1) };
 +     coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:10:1 - 10:11;
-+     coverage Code(Expression(0)) => $DIR/instrument_coverage.rs:11:5 - 12:17;
++     coverage Code(Expression(0)) => $DIR/instrument_coverage.rs:12:12 - 12:17;
 +     coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:13:13 - 13:18;
 +     coverage Code(Counter(1)) => $DIR/instrument_coverage.rs:14:10 - 14:11;
 +     coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:16:1 - 16:2;
diff --git a/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.rs b/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.rs
new file mode 100644
index 00000000000..1974bbf9fe7
--- /dev/null
+++ b/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.rs
@@ -0,0 +1,22 @@
+enum E {
+    A,
+    B,
+    C,
+}
+
+fn foo(e: E) {
+    let bar;
+
+    match e {
+        E::A if true => return,
+        E::A => return,
+        E::B => {}
+        E::C => {
+            bar = 5;
+        }
+    }
+
+    let _baz = bar; //~ ERROR E0381
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.stderr b/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.stderr
new file mode 100644
index 00000000000..eb7d0f8b204
--- /dev/null
+++ b/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.stderr
@@ -0,0 +1,15 @@
+error[E0381]: used binding `bar` is possibly-uninitialized
+  --> $DIR/uninitalized-in-match-arm-issue-126133.rs:19:16
+   |
+LL |     let bar;
+   |         --- binding declared here but left uninitialized
+...
+LL |         E::B => {}
+   |         ---- if this pattern is matched, `bar` is not initialized
+...
+LL |     let _baz = bar;
+   |                ^^^ `bar` used here but it is possibly-uninitialized
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr
index d809a6948f3..f32bb1301da 100644
--- a/tests/ui/coherence/occurs-check/associated-type.next.stderr
+++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr
@@ -1,7 +1,7 @@
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
 error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())`
   --> $DIR/associated-type.rs:31:1
    |
diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr
index 329086ab7df..d26f7665ee7 100644
--- a/tests/ui/coherence/occurs-check/associated-type.old.stderr
+++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr
@@ -1,11 +1,11 @@
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), _use_alias_ty_new_instead: () }
 error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)`
   --> $DIR/associated-type.rs:31:1
    |
diff --git a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs
new file mode 100644
index 00000000000..899db191ae7
--- /dev/null
+++ b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs
@@ -0,0 +1,20 @@
+// Given an anon const `a`: `{ N }` and some anon const `b` which references the
+// first anon const: `{ [1; a] }`. `b` should not have any generics as it is not
+// a simple `N` argument nor is it a repeat expr count.
+//
+// On the other hand `b` *is* a repeat expr count and so it should inherit its
+// parents generics as part of the `const_evaluatable_unchecked` fcw (#76200).
+//
+// In this specific case however `b`'s parent should be `a` and so it should wind
+// up not having any generics after all. If `a` were to inherit its generics from
+// the enclosing item then the reference to `a` from `b` would contain generic
+// parameters not usable by `b` which would cause us to ICE.
+
+fn bar<const N: usize>() {}
+
+fn foo<const N: usize>() {
+    bar::<{ [1; N] }>();
+    //~^ ERROR: generic parameters may not be used in const operations
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr
new file mode 100644
index 00000000000..64548cc5a30
--- /dev/null
+++ b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr
@@ -0,0 +1,11 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/repeat_expr_hack_gives_right_generics.rs:16:17
+   |
+LL |     bar::<{ [1; N] }>();
+   |                 ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr
index 2f1dfd19c48..e1cffa0fc37 100644
--- a/tests/ui/higher-ranked/structually-relate-aliases.stderr
+++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr
@@ -1,5 +1,5 @@
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), _use_alias_ty_new_instead: () }
 error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
   --> $DIR/structually-relate-aliases.rs:13:36
    |
diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr
index 17da1f52479..04c44276195 100644
--- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr
+++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr
@@ -25,10 +25,10 @@ help: this trait has no implementations, consider adding one
 LL | trait ToUnit<'a> {
    | ^^^^^^^^^^^^^^^^
 
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), _use_alias_ty_new_instead: () }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), _use_alias_ty_new_instead: () }
 error[E0119]: conflicting implementations of trait `Overlap<fn(_)>` for type `fn(_)`
   --> $DIR/issue-118950-root-region.rs:19:1
    |