about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-31 05:44:17 +0000
committerbors <bors@rust-lang.org>2024-03-31 05:44:17 +0000
commitd5de305fef8065d3af726537db2513a884ed2bcc (patch)
tree70ea36b7fd5f777449cc0622edc1f960490a2747 /compiler
parent723acede108580cdd6a848342ef3049f687f197e (diff)
parenteb8e8c06b6c6ab90b6ecbed1ac3820304c53ef01 (diff)
Auto merge of #3435 - rust-lang:rustup-2024-03-31, r=saethlin
Automatic Rustup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch4
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/copy.rs1
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs160
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs47
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs13
-rw-r--r--compiler/rustc_lint/src/lints.rs18
-rw-r--r--compiler/rustc_lint/src/types.rs38
-rw-r--r--compiler/rustc_middle/src/ty/region.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs7
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs14
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs89
-rw-r--r--compiler/rustc_session/messages.ftl2
-rw-r--r--compiler/rustc_session/src/errors.rs4
-rw-r--r--compiler/rustc_session/src/session.rs5
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs153
-rw-r--r--compiler/rustc_type_ir/src/fold.rs51
-rw-r--r--compiler/rustc_type_ir/src/interner.rs13
-rw-r--r--compiler/rustc_type_ir/src/new.rs2
19 files changed, 348 insertions, 279 deletions
diff --git a/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch
index 914ae986b50..36d0789d2a2 100644
--- a/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch
+++ b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch
@@ -14,7 +14,7 @@ index d0a119c..76fdece 100644
 @@ -89,7 +89,6 @@
  #![feature(never_type)]
  #![feature(unwrap_infallible)]
- #![feature(pointer_is_aligned)]
+ #![feature(pointer_is_aligned_to)]
 -#![feature(portable_simd)]
  #![feature(ptr_metadata)]
  #![feature(lazy_cell)]
@@ -27,6 +27,6 @@ index d0a119c..76fdece 100644
  mod slice;
  mod str;
  mod str_lossy;
--- 
+--
 2.42.1
 
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
index ff4208def31..8b9e834b60b 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
@@ -243,6 +243,7 @@ where
     T: Tag,
 {
     #[inline]
+    #[allow(ambiguous_wide_pointer_comparisons)]
     fn eq(&self, other: &Self) -> bool {
         self.packed == other.packed
     }
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 9bf4d63267a..d8a90d62dac 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -295,6 +295,8 @@ hir_analysis_not_supported_delegation =
     {$descr} is not supported yet
     .label = callee defined here
 
+hir_analysis_only_current_traits_adt = `{$name}` is not defined in the current crate
+
 hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types
 
 hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index ca8a635ab5e..1770f7b4e91 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -4,7 +4,7 @@
 use crate::errors;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
-use rustc_middle::ty::{self, AliasKind, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, AliasKind, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
 use rustc_trait_selection::traits::{self, IsFirstInputType};
@@ -283,9 +283,14 @@ fn emit_orphan_check_error<'tcx>(
     let self_ty = trait_ref.self_ty();
     Err(match err {
         traits::OrphanCheckErr::NonLocalInputType(tys) => {
-            let (mut opaque, mut foreign, mut name, mut pointer, mut ty_diag) =
-                (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new());
-            let mut sugg = None;
+            let mut diag = tcx.dcx().create_err(match self_ty.kind() {
+                ty::Adt(..) => errors::OnlyCurrentTraits::Outside { span: sp, note: () },
+                _ if self_ty.is_primitive() => {
+                    errors::OnlyCurrentTraits::Primitive { span: sp, note: () }
+                }
+                _ => errors::OnlyCurrentTraits::Arbitrary { span: sp, note: () },
+            });
+
             for &(mut ty, is_target_ty) in &tys {
                 let span = if matches!(is_target_ty, IsFirstInputType::Yes) {
                     // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
@@ -296,113 +301,86 @@ fn emit_orphan_check_error<'tcx>(
                 };
 
                 ty = tcx.erase_regions(ty);
-                ty = match ty.kind() {
-                    // Remove the type arguments from the output, as they are not relevant.
-                    // You can think of this as the reverse of `resolve_vars_if_possible`.
-                    // That way if we had `Vec<MyType>`, we will properly attribute the
-                    // problem to `Vec<T>` and avoid confusing the user if they were to see
-                    // `MyType` in the error.
-                    ty::Adt(def, _) => Ty::new_adt(tcx, *def, ty::List::empty()),
-                    _ => ty,
-                };
-
-                fn push_to_foreign_or_name<'tcx>(
-                    is_foreign: bool,
-                    foreign: &mut Vec<errors::OnlyCurrentTraitsForeign>,
-                    name: &mut Vec<errors::OnlyCurrentTraitsName<'tcx>>,
-                    span: Span,
-                    sname: &'tcx str,
-                ) {
-                    if is_foreign {
-                        foreign.push(errors::OnlyCurrentTraitsForeign { span })
-                    } else {
-                        name.push(errors::OnlyCurrentTraitsName { span, name: sname });
-                    }
-                }
 
                 let is_foreign =
                     !trait_ref.def_id.is_local() && matches!(is_target_ty, IsFirstInputType::No);
 
                 match *ty.kind() {
                     ty::Slice(_) => {
-                        push_to_foreign_or_name(
-                            is_foreign,
-                            &mut foreign,
-                            &mut name,
-                            span,
-                            "slices",
-                        );
+                        if is_foreign {
+                            diag.subdiagnostic(
+                                tcx.dcx(),
+                                errors::OnlyCurrentTraitsForeign { span },
+                            );
+                        } else {
+                            diag.subdiagnostic(
+                                tcx.dcx(),
+                                errors::OnlyCurrentTraitsName { span, name: "slices" },
+                            );
+                        }
                     }
                     ty::Array(..) => {
-                        push_to_foreign_or_name(
-                            is_foreign,
-                            &mut foreign,
-                            &mut name,
-                            span,
-                            "arrays",
-                        );
+                        if is_foreign {
+                            diag.subdiagnostic(
+                                tcx.dcx(),
+                                errors::OnlyCurrentTraitsForeign { span },
+                            );
+                        } else {
+                            diag.subdiagnostic(
+                                tcx.dcx(),
+                                errors::OnlyCurrentTraitsName { span, name: "arrays" },
+                            );
+                        }
                     }
                     ty::Tuple(..) => {
-                        push_to_foreign_or_name(
-                            is_foreign,
-                            &mut foreign,
-                            &mut name,
-                            span,
-                            "tuples",
-                        );
+                        if is_foreign {
+                            diag.subdiagnostic(
+                                tcx.dcx(),
+                                errors::OnlyCurrentTraitsForeign { span },
+                            );
+                        } else {
+                            diag.subdiagnostic(
+                                tcx.dcx(),
+                                errors::OnlyCurrentTraitsName { span, name: "tuples" },
+                            );
+                        }
                     }
                     ty::Alias(ty::Opaque, ..) => {
-                        opaque.push(errors::OnlyCurrentTraitsOpaque { span })
+                        diag.subdiagnostic(tcx.dcx(), errors::OnlyCurrentTraitsOpaque { span });
                     }
                     ty::RawPtr(ptr_ty, mutbl) => {
                         if !self_ty.has_param() {
-                            let mut_key = mutbl.prefix_str();
-                            sugg = Some(errors::OnlyCurrentTraitsPointerSugg {
-                                wrapper_span: self_ty_span,
-                                struct_span: full_impl_span.shrink_to_lo(),
-                                mut_key,
-                                ptr_ty,
-                            });
+                            diag.subdiagnostic(
+                                tcx.dcx(),
+                                errors::OnlyCurrentTraitsPointerSugg {
+                                    wrapper_span: self_ty_span,
+                                    struct_span: full_impl_span.shrink_to_lo(),
+                                    mut_key: mutbl.prefix_str(),
+                                    ptr_ty,
+                                },
+                            );
                         }
-                        pointer.push(errors::OnlyCurrentTraitsPointer { span, pointer: ty });
+                        diag.subdiagnostic(
+                            tcx.dcx(),
+                            errors::OnlyCurrentTraitsPointer { span, pointer: ty },
+                        );
+                    }
+                    ty::Adt(adt_def, _) => {
+                        diag.subdiagnostic(
+                            tcx.dcx(),
+                            errors::OnlyCurrentTraitsAdt {
+                                span,
+                                name: tcx.def_path_str(adt_def.did()),
+                            },
+                        );
+                    }
+                    _ => {
+                        diag.subdiagnostic(tcx.dcx(), errors::OnlyCurrentTraitsTy { span, ty });
                     }
-                    _ => ty_diag.push(errors::OnlyCurrentTraitsTy { span, ty }),
                 }
             }
 
-            let err_struct = match self_ty.kind() {
-                ty::Adt(..) => errors::OnlyCurrentTraits::Outside {
-                    span: sp,
-                    note: (),
-                    opaque,
-                    foreign,
-                    name,
-                    pointer,
-                    ty: ty_diag,
-                    sugg,
-                },
-                _ if self_ty.is_primitive() => errors::OnlyCurrentTraits::Primitive {
-                    span: sp,
-                    note: (),
-                    opaque,
-                    foreign,
-                    name,
-                    pointer,
-                    ty: ty_diag,
-                    sugg,
-                },
-                _ => errors::OnlyCurrentTraits::Arbitrary {
-                    span: sp,
-                    note: (),
-                    opaque,
-                    foreign,
-                    name,
-                    pointer,
-                    ty: ty_diag,
-                    sugg,
-                },
-            };
-            tcx.dcx().emit_err(err_struct)
+            diag.emit()
         }
         traits::OrphanCheckErr::UncoveredTy(param_ty, local_type) => {
             let mut sp = sp;
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index fb919714afd..2d4742fa1dc 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1376,7 +1376,7 @@ pub struct TyParamSome<'a> {
 }
 
 #[derive(Diagnostic)]
-pub enum OnlyCurrentTraits<'a> {
+pub enum OnlyCurrentTraits {
     #[diag(hir_analysis_only_current_traits_outside, code = E0117)]
     Outside {
         #[primary_span]
@@ -1384,18 +1384,6 @@ pub enum OnlyCurrentTraits<'a> {
         span: Span,
         #[note(hir_analysis_only_current_traits_note)]
         note: (),
-        #[subdiagnostic]
-        opaque: Vec<OnlyCurrentTraitsOpaque>,
-        #[subdiagnostic]
-        foreign: Vec<OnlyCurrentTraitsForeign>,
-        #[subdiagnostic]
-        name: Vec<OnlyCurrentTraitsName<'a>>,
-        #[subdiagnostic]
-        pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
-        #[subdiagnostic]
-        ty: Vec<OnlyCurrentTraitsTy<'a>>,
-        #[subdiagnostic]
-        sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
     },
     #[diag(hir_analysis_only_current_traits_primitive, code = E0117)]
     Primitive {
@@ -1404,18 +1392,6 @@ pub enum OnlyCurrentTraits<'a> {
         span: Span,
         #[note(hir_analysis_only_current_traits_note)]
         note: (),
-        #[subdiagnostic]
-        opaque: Vec<OnlyCurrentTraitsOpaque>,
-        #[subdiagnostic]
-        foreign: Vec<OnlyCurrentTraitsForeign>,
-        #[subdiagnostic]
-        name: Vec<OnlyCurrentTraitsName<'a>>,
-        #[subdiagnostic]
-        pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
-        #[subdiagnostic]
-        ty: Vec<OnlyCurrentTraitsTy<'a>>,
-        #[subdiagnostic]
-        sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
     },
     #[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)]
     Arbitrary {
@@ -1424,18 +1400,6 @@ pub enum OnlyCurrentTraits<'a> {
         span: Span,
         #[note(hir_analysis_only_current_traits_note)]
         note: (),
-        #[subdiagnostic]
-        opaque: Vec<OnlyCurrentTraitsOpaque>,
-        #[subdiagnostic]
-        foreign: Vec<OnlyCurrentTraitsForeign>,
-        #[subdiagnostic]
-        name: Vec<OnlyCurrentTraitsName<'a>>,
-        #[subdiagnostic]
-        pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
-        #[subdiagnostic]
-        ty: Vec<OnlyCurrentTraitsTy<'a>>,
-        #[subdiagnostic]
-        sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
     },
 }
 
@@ -1445,7 +1409,6 @@ pub struct OnlyCurrentTraitsOpaque {
     #[primary_span]
     pub span: Span,
 }
-
 #[derive(Subdiagnostic)]
 #[label(hir_analysis_only_current_traits_foreign)]
 pub struct OnlyCurrentTraitsForeign {
@@ -1478,6 +1441,14 @@ pub struct OnlyCurrentTraitsTy<'a> {
 }
 
 #[derive(Subdiagnostic)]
+#[label(hir_analysis_only_current_traits_adt)]
+pub struct OnlyCurrentTraitsAdt {
+    #[primary_span]
+    pub span: Span,
+    pub name: String,
+}
+
+#[derive(Subdiagnostic)]
 #[multipart_suggestion(
     hir_analysis_only_current_traits_pointer_sugg,
     applicability = "maybe-incorrect"
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index ebc5e11a561..8ea1a88be5d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1916,18 +1916,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat: &'tcx hir::Pat<'tcx>,
         ty: Ty<'tcx>,
     ) {
-        struct V<'tcx> {
-            tcx: TyCtxt<'tcx>,
+        struct V {
             pat_hir_ids: Vec<hir::HirId>,
         }
 
-        impl<'tcx> Visitor<'tcx> for V<'tcx> {
-            type NestedFilter = rustc_middle::hir::nested_filter::All;
-
-            fn nested_visit_map(&mut self) -> Self::Map {
-                self.tcx.hir()
-            }
-
+        impl<'tcx> Visitor<'tcx> for V {
             fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
                 self.pat_hir_ids.push(p.hir_id);
                 hir::intravisit::walk_pat(self, p);
@@ -1938,7 +1931,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let err = Ty::new_error(self.tcx, guar);
             self.write_ty(hir_id, err);
             self.write_ty(pat.hir_id, err);
-            let mut visitor = V { tcx: self.tcx, pat_hir_ids: vec![] };
+            let mut visitor = V { pat_hir_ids: vec![] };
             hir::intravisit::walk_pat(&mut visitor, pat);
             // Mark all the subpatterns as `{type error}` as well. This allows errors for specific
             // subpatterns to be silenced.
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index cf3890dc61c..a034bebc85e 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1632,11 +1632,13 @@ pub struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> {
     pub ne: &'a str,
     pub deref_left: &'a str,
     pub deref_right: &'a str,
+    pub l_modifiers: &'a str,
+    pub r_modifiers: &'a str,
     #[suggestion_part(code = "{ne}std::ptr::eq({deref_left}")]
     pub left: Span,
-    #[suggestion_part(code = ", {deref_right}")]
+    #[suggestion_part(code = "{l_modifiers}, {deref_right}")]
     pub middle: Span,
-    #[suggestion_part(code = ")")]
+    #[suggestion_part(code = "{r_modifiers})")]
     pub right: Span,
 }
 
@@ -1652,11 +1654,13 @@ pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
         ne: &'a str,
         deref_left: &'a str,
         deref_right: &'a str,
+        l_modifiers: &'a str,
+        r_modifiers: &'a str,
         #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")]
         left: Span,
-        #[suggestion_part(code = ", {deref_right}")]
+        #[suggestion_part(code = "{l_modifiers}, {deref_right}")]
         middle: Span,
-        #[suggestion_part(code = ")")]
+        #[suggestion_part(code = "{r_modifiers})")]
         right: Span,
     },
     #[multipart_suggestion(
@@ -1670,13 +1674,15 @@ pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
         deref_right: &'a str,
         paren_left: &'a str,
         paren_right: &'a str,
+        l_modifiers: &'a str,
+        r_modifiers: &'a str,
         #[suggestion_part(code = "({deref_left}")]
         left_before: Option<Span>,
-        #[suggestion_part(code = "{paren_left}.cast::<()>()")]
+        #[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")]
         left_after: Span,
         #[suggestion_part(code = "({deref_right}")]
         right_before: Option<Span>,
-        #[suggestion_part(code = "{paren_right}.cast::<()>()")]
+        #[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")]
         right_after: Span,
     },
 }
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 68cc024d9c7..534eb60eeb0 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -670,7 +670,11 @@ fn lint_wide_pointer<'tcx>(
     l: &'tcx hir::Expr<'tcx>,
     r: &'tcx hir::Expr<'tcx>,
 ) {
-    let ptr_unsized = |mut ty: Ty<'tcx>| -> Option<(usize, bool)> {
+    let ptr_unsized = |mut ty: Ty<'tcx>| -> Option<(
+        /* number of refs */ usize,
+        /* modifiers */ String,
+        /* is dyn */ bool,
+    )> {
         let mut refs = 0;
         // here we remove any "implicit" references and count the number
         // of them to correctly suggest the right number of deref
@@ -678,11 +682,20 @@ fn lint_wide_pointer<'tcx>(
             ty = *inner_ty;
             refs += 1;
         }
-        match ty.kind() {
-            ty::RawPtr(ty, _) => (!ty.is_sized(cx.tcx, cx.param_env))
-                .then(|| (refs, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn)))),
-            _ => None,
-        }
+
+        // get the inner type of a pointer (or akin)
+        let mut modifiers = String::new();
+        ty = match ty.kind() {
+            ty::RawPtr(ty, _) => *ty,
+            ty::Adt(def, args) if cx.tcx.is_diagnostic_item(sym::NonNull, def.did()) => {
+                modifiers.push_str(".as_ptr()");
+                args.type_at(0)
+            }
+            _ => return None,
+        };
+
+        (!ty.is_sized(cx.tcx, cx.param_env))
+            .then(|| (refs, modifiers, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn))))
     };
 
     // the left and right operands can have references, remove any explicit references
@@ -696,10 +709,10 @@ fn lint_wide_pointer<'tcx>(
         return;
     };
 
-    let Some((l_ty_refs, l_inner_ty_is_dyn)) = ptr_unsized(l_ty) else {
+    let Some((l_ty_refs, l_modifiers, l_inner_ty_is_dyn)) = ptr_unsized(l_ty) else {
         return;
     };
-    let Some((r_ty_refs, r_inner_ty_is_dyn)) = ptr_unsized(r_ty) else {
+    let Some((r_ty_refs, r_modifiers, r_inner_ty_is_dyn)) = ptr_unsized(r_ty) else {
         return;
     };
 
@@ -724,6 +737,9 @@ fn lint_wide_pointer<'tcx>(
     let deref_left = &*"*".repeat(l_ty_refs);
     let deref_right = &*"*".repeat(r_ty_refs);
 
+    let l_modifiers = &*l_modifiers;
+    let r_modifiers = &*r_modifiers;
+
     cx.emit_span_lint(
         AMBIGUOUS_WIDE_POINTER_COMPARISONS,
         e.span,
@@ -733,6 +749,8 @@ fn lint_wide_pointer<'tcx>(
                     ne,
                     deref_left,
                     deref_right,
+                    l_modifiers,
+                    r_modifiers,
                     left,
                     middle,
                     right,
@@ -743,6 +761,8 @@ fn lint_wide_pointer<'tcx>(
                     ne,
                     deref_left,
                     deref_right,
+                    l_modifiers,
+                    r_modifiers,
                     left,
                     middle,
                     right,
@@ -751,6 +771,8 @@ fn lint_wide_pointer<'tcx>(
                 AmbiguousWidePointerComparisonsAddrSuggestion::Cast {
                     deref_left,
                     deref_right,
+                    l_modifiers,
+                    r_modifiers,
                     paren_left: if l_ty_refs != 0 { ")" } else { "" },
                     paren_right: if r_ty_refs != 0 { ")" } else { "" },
                     left_before: (l_ty_refs != 0).then_some(l_span.shrink_to_lo()),
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index 867faf63261..b92800a1728 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -140,6 +140,10 @@ impl<'tcx> rustc_type_ir::new::Region<TyCtxt<'tcx>> for Region<'tcx> {
     fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
         Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon })
     }
+
+    fn new_static(tcx: TyCtxt<'tcx>) -> Self {
+        tcx.lifetimes.re_static
+    }
 }
 
 /// Region utilities
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 57a675e4453..b5e619f1e2a 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1624,6 +1624,13 @@ impl<'tcx> Ty<'tcx> {
 
     #[inline]
     pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
+        debug_assert_eq!(
+            tcx.generics_of(def.did()).count(),
+            args.len(),
+            "wrong number of args for ADT: {:#?} vs {:#?}",
+            tcx.generics_of(def.did()).params,
+            args
+        );
         Ty::new(tcx, Adt(def, args))
     }
 
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index b66dd83b7ec..690879b9488 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -650,12 +650,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 }
             }
 
-            // FIXME(#29623): return `Some(1)` when the values are different.
-            (TestKind::Eq { value: test_val, .. }, TestCase::Constant { value: case_val })
-                if test_val == case_val =>
-            {
-                fully_matched = true;
-                Some(TestBranch::Success)
+            (TestKind::Eq { value: test_val, .. }, TestCase::Constant { value: case_val }) => {
+                if test_val == case_val {
+                    fully_matched = true;
+                    Some(TestBranch::Success)
+                } else {
+                    fully_matched = false;
+                    Some(TestBranch::Failure)
+                }
             }
 
             (
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 16d8453ea24..1899517c0e2 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -296,10 +296,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
         Region::new_anon_bound(self.interner(), self.binder_index, var)
     }
 
-    fn fold_ty(&mut self, t: I::Ty) -> I::Ty
-    where
-        I::Ty: TypeSuperFoldable<I>,
-    {
+    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
         let kind = match t.kind() {
             ty::Infer(i) => match i {
                 ty::TyVar(vid) => {
@@ -378,47 +375,48 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
         Ty::new_anon_bound(self.interner(), self.binder_index, var)
     }
 
-    fn fold_const(&mut self, c: I::Const) -> I::Const
-    where
-        I::Const: TypeSuperFoldable<I>,
-    {
+    fn fold_const(&mut self, c: I::Const) -> I::Const {
+        // We could canonicalize all consts with static types, but the only ones we
+        // *really* need to worry about are the ones that we end up putting into `CanonicalVarKind`
+        // since canonical vars can't reference other canonical vars.
+        let ty = c
+            .ty()
+            .fold_with(&mut RegionsToStatic { interner: self.interner(), binder: ty::INNERMOST });
         let kind = match c.kind() {
-            ty::ConstKind::Infer(i) => {
-                // FIXME: we should fold the ty too eventually
-                match i {
-                    ty::InferConst::Var(vid) => {
-                        assert_eq!(
-                            self.infcx.root_ct_var(vid),
-                            vid,
-                            "region vid should have been resolved fully before canonicalization"
-                        );
-                        assert_eq!(
-                            self.infcx.probe_ct_var(vid),
-                            None,
-                            "region vid should have been resolved fully before canonicalization"
-                        );
-                        CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), c.ty())
-                    }
-                    ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
-                    ty::InferConst::Fresh(_) => todo!(),
+            ty::ConstKind::Infer(i) => match i {
+                ty::InferConst::Var(vid) => {
+                    assert_eq!(
+                        self.infcx.root_ct_var(vid),
+                        vid,
+                        "region vid should have been resolved fully before canonicalization"
+                    );
+                    assert_eq!(
+                        self.infcx.probe_ct_var(vid),
+                        None,
+                        "region vid should have been resolved fully before canonicalization"
+                    );
+                    CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), ty)
                 }
-            }
+                ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
+                ty::InferConst::Fresh(_) => todo!(),
+            },
             ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
                     PlaceholderLike::new(placeholder.universe(), self.variables.len().into()),
-                    c.ty(),
+                    ty,
                 ),
                 CanonicalizeMode::Response { .. } => {
-                    CanonicalVarKind::PlaceholderConst(placeholder, c.ty())
+                    CanonicalVarKind::PlaceholderConst(placeholder, ty)
                 }
             },
             ty::ConstKind::Param(_) => match self.canonicalize_mode {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
                     PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()),
-                    c.ty(),
+                    ty,
                 ),
                 CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"),
             },
+            // FIXME: See comment above -- we could fold the region separately or something.
             ty::ConstKind::Bound(_, _)
             | ty::ConstKind::Unevaluated(_)
             | ty::ConstKind::Value(_)
@@ -435,6 +433,35 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
             }),
         );
 
-        Const::new_anon_bound(self.interner(), self.binder_index, var, c.ty())
+        Const::new_anon_bound(self.interner(), self.binder_index, var, ty)
+    }
+}
+
+struct RegionsToStatic<I> {
+    interner: I,
+    binder: ty::DebruijnIndex,
+}
+
+impl<I: Interner> TypeFolder<I> for RegionsToStatic<I> {
+    fn interner(&self) -> I {
+        self.interner
+    }
+
+    fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
+    where
+        T: TypeFoldable<I>,
+        I::Binder<T>: TypeSuperFoldable<I>,
+    {
+        self.binder.shift_in(1);
+        let t = t.fold_with(self);
+        self.binder.shift_out(1);
+        t
+    }
+
+    fn fold_region(&mut self, r: I::Region) -> I::Region {
+        match r.kind() {
+            ty::ReBound(db, _) if self.binder > db => r,
+            _ => Region::new_static(self.interner()),
+        }
     }
 }
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index 179fd79bef7..b8dacc6968d 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -96,6 +96,8 @@ session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto` or `-Cli
 
 session_sanitizer_cfi_requires_single_codegen_unit = `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1`
 
+session_sanitizer_kcfi_requires_panic_abort = `-Z sanitizer=kcfi` requires `-C panic=abort`
+
 session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
 
 session_sanitizers_not_supported = {$us} sanitizers are not supported for this target
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 0a855f87586..2e4c7d14ecd 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -146,6 +146,10 @@ pub(crate) struct SanitizerCfiGeneralizePointersRequiresCfi;
 pub(crate) struct SanitizerCfiNormalizeIntegersRequiresCfi;
 
 #[derive(Diagnostic)]
+#[diag(session_sanitizer_kcfi_requires_panic_abort)]
+pub(crate) struct SanitizerKcfiRequiresPanicAbort;
+
+#[derive(Diagnostic)]
 #[diag(session_split_lto_unit_requires_lto)]
 pub(crate) struct SplitLtoUnitRequiresLto;
 
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 85428303382..55fff4421ae 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1211,6 +1211,11 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         sess.dcx().emit_err(errors::SanitizerCfiRequiresLto);
     }
 
+    // KCFI requires panic=abort
+    if sess.is_sanitizer_kcfi_enabled() && sess.panic_strategy() != PanicStrategy::Abort {
+        sess.dcx().emit_err(errors::SanitizerKcfiRequiresPanicAbort);
+    }
+
     // LLVM CFI using rustc LTO requires a single codegen unit.
     if sess.is_sanitizer_cfi_enabled()
         && sess.lto() == config::Lto::Fat
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 7fd5cfeb48b..5963bd7c5f1 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -10,6 +10,7 @@
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
+use rustc_hir::lang_items::LangItem;
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{
@@ -641,9 +642,7 @@ fn encode_ty<'tcx>(
         }
 
         // Function types
-        ty::FnDef(def_id, args)
-        | ty::Closure(def_id, args)
-        | ty::CoroutineClosure(def_id, args) => {
+        ty::FnDef(def_id, args) | ty::Closure(def_id, args) => {
             // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
             // as vendor extended type.
             let mut s = String::new();
@@ -654,6 +653,18 @@ fn encode_ty<'tcx>(
             typeid.push_str(&s);
         }
 
+        ty::CoroutineClosure(def_id, args) => {
+            // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
+            // as vendor extended type.
+            let mut s = String::new();
+            let name = encode_ty_name(tcx, *def_id);
+            let _ = write!(s, "u{}{}", name.len(), &name);
+            let parent_args = tcx.mk_args(args.as_coroutine_closure().parent_args());
+            s.push_str(&encode_args(tcx, parent_args, dict, options));
+            compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
+            typeid.push_str(&s);
+        }
+
         ty::Coroutine(def_id, args, ..) => {
             // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
             // as vendor extended type.
@@ -1140,45 +1151,102 @@ pub fn typeid_for_instance<'tcx>(
         let predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(predicate)]);
         let self_ty = Ty::new_dynamic(tcx, predicates, tcx.lifetimes.re_erased, ty::Dyn);
         instance.args = tcx.mk_args_trait(self_ty, List::empty());
-    } else if matches!(instance.def, ty::InstanceDef::Virtual(..)) {
-        instance.args = strip_receiver_auto(tcx, instance.args);
+    } else if let ty::InstanceDef::Virtual(def_id, _) = instance.def {
+        let upcast_ty = match tcx.trait_of_item(def_id) {
+            Some(trait_id) => trait_object_ty(
+                tcx,
+                ty::Binder::dummy(ty::TraitRef::from_method(tcx, trait_id, instance.args)),
+            ),
+            // drop_in_place won't have a defining trait, skip the upcast
+            None => instance.args.type_at(0),
+        };
+        let stripped_ty = strip_receiver_auto(tcx, upcast_ty);
+        instance.args = tcx.mk_args_trait(stripped_ty, instance.args.into_iter().skip(1));
+    } else if let ty::InstanceDef::VTableShim(def_id) = instance.def
+        && let Some(trait_id) = tcx.trait_of_item(def_id)
+    {
+        // VTableShims may have a trait method, but a concrete Self. This is not suitable for a vtable,
+        // as the caller will not know the concrete Self.
+        let trait_ref = ty::TraitRef::new(tcx, trait_id, instance.args);
+        let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref));
+        instance.args = tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
     }
 
-    if !options.contains(EncodeTyOptions::NO_SELF_TYPE_ERASURE)
-        && let Some(impl_id) = tcx.impl_of_method(instance.def_id())
-        && let Some(trait_ref) = tcx.impl_trait_ref(impl_id)
-    {
-        let impl_method = tcx.associated_item(instance.def_id());
-        let method_id = impl_method
-            .trait_item_def_id
-            .expect("Part of a trait implementation, but not linked to the def_id?");
-        let trait_method = tcx.associated_item(method_id);
-        let trait_id = trait_ref.skip_binder().def_id;
-        if traits::is_vtable_safe_method(tcx, trait_id, trait_method)
-            && tcx.object_safety_violations(trait_id).is_empty()
+    if !options.contains(EncodeTyOptions::NO_SELF_TYPE_ERASURE) {
+        if let Some(impl_id) = tcx.impl_of_method(instance.def_id())
+            && let Some(trait_ref) = tcx.impl_trait_ref(impl_id)
         {
-            // Trait methods will have a Self polymorphic parameter, where the concreteized
-            // implementatation will not. We need to walk back to the more general trait method
-            let trait_ref = tcx.instantiate_and_normalize_erasing_regions(
-                instance.args,
-                ty::ParamEnv::reveal_all(),
-                trait_ref,
-            );
+            let impl_method = tcx.associated_item(instance.def_id());
+            let method_id = impl_method
+                .trait_item_def_id
+                .expect("Part of a trait implementation, but not linked to the def_id?");
+            let trait_method = tcx.associated_item(method_id);
+            let trait_id = trait_ref.skip_binder().def_id;
+            if traits::is_vtable_safe_method(tcx, trait_id, trait_method)
+                && tcx.object_safety_violations(trait_id).is_empty()
+            {
+                // Trait methods will have a Self polymorphic parameter, where the concreteized
+                // implementatation will not. We need to walk back to the more general trait method
+                let trait_ref = tcx.instantiate_and_normalize_erasing_regions(
+                    instance.args,
+                    ty::ParamEnv::reveal_all(),
+                    trait_ref,
+                );
+                let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref));
+
+                // At the call site, any call to this concrete function through a vtable will be
+                // `Virtual(method_id, idx)` with appropriate arguments for the method. Since we have the
+                // original method id, and we've recovered the trait arguments, we can make the callee
+                // instance we're computing the alias set for match the caller instance.
+                //
+                // Right now, our code ignores the vtable index everywhere, so we use 0 as a placeholder.
+                // If we ever *do* start encoding the vtable index, we will need to generate an alias set
+                // based on which vtables we are putting this method into, as there will be more than one
+                // index value when supertraits are involved.
+                instance.def = ty::InstanceDef::Virtual(method_id, 0);
+                let abstract_trait_args =
+                    tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
+                instance.args = instance.args.rebase_onto(tcx, impl_id, abstract_trait_args);
+            }
+        } else if tcx.is_closure_like(instance.def_id()) {
+            // We're either a closure or a coroutine. Our goal is to find the trait we're defined on,
+            // instantiate it, and take the type of its only method as our own.
+            let closure_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
+            let (trait_id, inputs) = match closure_ty.kind() {
+                ty::Closure(..) => {
+                    let closure_args = instance.args.as_closure();
+                    let trait_id = tcx.fn_trait_kind_to_def_id(closure_args.kind()).unwrap();
+                    let tuple_args =
+                        tcx.instantiate_bound_regions_with_erased(closure_args.sig()).inputs()[0];
+                    (trait_id, tuple_args)
+                }
+                ty::Coroutine(..) => (
+                    tcx.require_lang_item(LangItem::Coroutine, None),
+                    instance.args.as_coroutine().resume_ty(),
+                ),
+                ty::CoroutineClosure(..) => (
+                    tcx.require_lang_item(LangItem::FnOnce, None),
+                    tcx.instantiate_bound_regions_with_erased(
+                        instance.args.as_coroutine_closure().coroutine_closure_sig(),
+                    )
+                    .tupled_inputs_ty,
+                ),
+                x => bug!("Unexpected type kind for closure-like: {x:?}"),
+            };
+            let trait_ref = ty::TraitRef::new(tcx, trait_id, [closure_ty, inputs]);
             let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref));
+            let abstract_args = tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
+            // There should be exactly one method on this trait, and it should be the one we're
+            // defining.
+            let call = tcx
+                .associated_items(trait_id)
+                .in_definition_order()
+                .find(|it| it.kind == ty::AssocKind::Fn)
+                .expect("No call-family function on closure-like Fn trait?")
+                .def_id;
 
-            // At the call site, any call to this concrete function through a vtable will be
-            // `Virtual(method_id, idx)` with appropriate arguments for the method. Since we have the
-            // original method id, and we've recovered the trait arguments, we can make the callee
-            // instance we're computing the alias set for match the caller instance.
-            //
-            // Right now, our code ignores the vtable index everywhere, so we use 0 as a placeholder.
-            // If we ever *do* start encoding the vtable index, we will need to generate an alias set
-            // based on which vtables we are putting this method into, as there will be more than one
-            // index value when supertraits are involved.
-            instance.def = ty::InstanceDef::Virtual(method_id, 0);
-            let abstract_trait_args =
-                tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
-            instance.args = instance.args.rebase_onto(tcx, impl_id, abstract_trait_args);
+            instance.def = ty::InstanceDef::Virtual(call, 0);
+            instance.args = abstract_args;
         }
     }
 
@@ -1191,15 +1259,11 @@ pub fn typeid_for_instance<'tcx>(
     typeid_for_fnabi(tcx, fn_abi, options)
 }
 
-fn strip_receiver_auto<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    args: ty::GenericArgsRef<'tcx>,
-) -> ty::GenericArgsRef<'tcx> {
-    let ty = args.type_at(0);
+fn strip_receiver_auto<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     let ty::Dynamic(preds, lifetime, kind) = ty.kind() else {
         bug!("Tried to strip auto traits from non-dynamic type {ty}");
     };
-    let new_rcvr = if preds.principal().is_some() {
+    if preds.principal().is_some() {
         let filtered_preds =
             tcx.mk_poly_existential_predicates_from_iter(preds.into_iter().filter(|pred| {
                 !matches!(pred.skip_binder(), ty::ExistentialPredicate::AutoTrait(..))
@@ -1210,8 +1274,7 @@ fn strip_receiver_auto<'tcx>(
         // about it. This technically discards the knowledge that it was a type that was made
         // into a trait object at some point, but that's not a lot.
         tcx.types.unit
-    };
-    tcx.mk_args_trait(new_rcvr, args.into_iter().skip(1))
+    }
 }
 
 #[instrument(skip(tcx), ret)]
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index 8d402588398..01bb3d73dbd 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -136,31 +136,21 @@ pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = Never> {
         t.super_fold_with(self)
     }
 
-    fn fold_ty(&mut self, t: I::Ty) -> I::Ty
-    where
-        I::Ty: TypeSuperFoldable<I>,
-    {
+    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
         t.super_fold_with(self)
     }
 
     // The default region folder is a no-op because `Region` is non-recursive
-    // and has no `super_fold_with` method to call. That also explains the
-    // lack of `I::Region: TypeSuperFoldable<I>` bound on this method.
+    // and has no `super_fold_with` method to call.
     fn fold_region(&mut self, r: I::Region) -> I::Region {
         r
     }
 
-    fn fold_const(&mut self, c: I::Const) -> I::Const
-    where
-        I::Const: TypeSuperFoldable<I>,
-    {
+    fn fold_const(&mut self, c: I::Const) -> I::Const {
         c.super_fold_with(self)
     }
 
-    fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate
-    where
-        I::Predicate: TypeSuperFoldable<I>,
-    {
+    fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
         p.super_fold_with(self)
     }
 }
@@ -185,31 +175,21 @@ pub trait FallibleTypeFolder<I: Interner>: Sized {
         t.try_super_fold_with(self)
     }
 
-    fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Self::Error>
-    where
-        I::Ty: TypeSuperFoldable<I>,
-    {
+    fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Self::Error> {
         t.try_super_fold_with(self)
     }
 
     // The default region folder is a no-op because `Region` is non-recursive
-    // and has no `super_fold_with` method to call. That also explains the
-    // lack of `I::Region: TypeSuperFoldable<I>` bound on this method.
+    // and has no `super_fold_with` method to call.
     fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, Self::Error> {
         Ok(r)
     }
 
-    fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Self::Error>
-    where
-        I::Const: TypeSuperFoldable<I>,
-    {
+    fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Self::Error> {
         c.try_super_fold_with(self)
     }
 
-    fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Self::Error>
-    where
-        I::Predicate: TypeSuperFoldable<I>,
-    {
+    fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Self::Error> {
         p.try_super_fold_with(self)
     }
 }
@@ -234,10 +214,7 @@ where
         Ok(self.fold_binder(t))
     }
 
-    fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Never>
-    where
-        I::Ty: TypeSuperFoldable<I>,
-    {
+    fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Never> {
         Ok(self.fold_ty(t))
     }
 
@@ -245,17 +222,11 @@ where
         Ok(self.fold_region(r))
     }
 
-    fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Never>
-    where
-        I::Const: TypeSuperFoldable<I>,
-    {
+    fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Never> {
         Ok(self.fold_const(c))
     }
 
-    fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Never>
-    where
-        I::Predicate: TypeSuperFoldable<I>,
-    {
+    fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Never> {
         Ok(self.fold_predicate(p))
     }
 }
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index ae1e1902f14..7a2885dd3bb 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -2,13 +2,14 @@ use smallvec::SmallVec;
 use std::fmt::Debug;
 use std::hash::Hash;
 
+use crate::fold::TypeSuperFoldable;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
 use crate::{
     new, BoundVar, BoundVars, CanonicalVarInfo, ConstKind, DebugWithInfcx, RegionKind, TyKind,
     UniverseIndex,
 };
 
-pub trait Interner: Sized {
+pub trait Interner: Sized + Copy {
     type DefId: Copy + Debug + Hash + Eq;
     type AdtDef: Copy + Debug + Hash + Eq;
 
@@ -34,6 +35,7 @@ pub trait Interner: Sized {
         + Into<Self::GenericArg>
         + IntoKind<Kind = TyKind<Self>>
         + TypeSuperVisitable<Self>
+        + TypeSuperFoldable<Self>
         + Flags
         + new::Ty<Self>;
     type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
@@ -57,6 +59,7 @@ pub trait Interner: Sized {
         + IntoKind<Kind = ConstKind<Self>>
         + ConstTy<Self>
         + TypeSuperVisitable<Self>
+        + TypeSuperFoldable<Self>
         + Flags
         + new::Const<Self>;
     type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Eq;
@@ -82,7 +85,13 @@ pub trait Interner: Sized {
     type PlaceholderRegion: Copy + Debug + Hash + Eq + PlaceholderLike;
 
     // Predicates
-    type Predicate: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
+    type Predicate: Copy
+        + Debug
+        + Hash
+        + Eq
+        + TypeSuperVisitable<Self>
+        + TypeSuperFoldable<Self>
+        + Flags;
     type TraitPredicate: Copy + Debug + Hash + Eq;
     type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
     type TypeOutlivesPredicate: Copy + Debug + Hash + Eq;
diff --git a/compiler/rustc_type_ir/src/new.rs b/compiler/rustc_type_ir/src/new.rs
index e7e695e5908..1572a641d06 100644
--- a/compiler/rustc_type_ir/src/new.rs
+++ b/compiler/rustc_type_ir/src/new.rs
@@ -6,6 +6,8 @@ pub trait Ty<I: Interner<Ty = Self>> {
 
 pub trait Region<I: Interner<Region = Self>> {
     fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
+
+    fn new_static(interner: I) -> Self;
 }
 
 pub trait Const<I: Interner<Const = Self>> {