about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_abi/src/extern_abi.rs4
-rw-r--r--compiler/rustc_abi/src/lib.rs2
-rw-r--r--compiler/rustc_ast/src/ast.rs11
-rw-r--r--compiler/rustc_ast/src/expand/autodiff_attrs.rs6
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs5
-rw-r--r--compiler/rustc_ast/src/visit.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/block.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs12
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs1
-rw-r--r--compiler/rustc_ast_lowering/src/stability.rs4
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs14
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs13
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs7
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs10
-rw-r--r--compiler/rustc_borrowck/src/lib.rs258
-rw-r--r--compiler/rustc_borrowck/src/nll.rs27
-rw-r--r--compiler/rustc_borrowck/src/opaque_types.rs55
-rw-r--r--compiler/rustc_borrowck/src/polonius/dump.rs8
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs47
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs14
-rw-r--r--compiler/rustc_borrowck/src/root_cx.rs101
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs15
-rw-r--r--compiler/rustc_borrowck/src/type_check/opaque_types.rs2
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs22
-rw-r--r--compiler/rustc_builtin_macros/src/autodiff.rs125
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/builder/autodiff.rs24
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs299
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs42
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs170
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs79
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs32
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/mod.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0622.md10
-rw-r--r--compiler/rustc_error_messages/src/lib.rs2
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs8
-rw-r--r--compiler/rustc_errors/src/lib.rs70
-rw-r--r--compiler/rustc_expand/src/build.rs2
-rw-r--r--compiler/rustc_feature/src/accepted.rs4
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs14
-rw-r--r--compiler/rustc_hir/src/hir.rs10
-rw-r--r--compiler/rustc_hir/src/intravisit.rs2
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl3
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs148
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs113
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs32
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs58
-rw-r--r--compiler/rustc_hir_analysis/src/constrained_generic_params.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs56
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs21
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs10
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs11
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs8
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs2
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs2
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs28
-rw-r--r--compiler/rustc_infer/src/infer/outlives/env.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/for_liveness.rs2
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs2
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs2
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs4
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_lint/src/builtin.rs30
-rw-r--r--compiler/rustc_lint/src/impl_trait_overcaptures.rs4
-rw-r--r--compiler/rustc_lint/src/levels.rs117
-rw-r--r--compiler/rustc_lint/src/lints.rs2
-rw-r--r--compiler/rustc_lint/src/unused.rs3
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs2
-rw-r--r--compiler/rustc_middle/src/arena.rs2
-rw-r--r--compiler/rustc_middle/src/mir/query.rs158
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs2
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs6
-rw-r--r--compiler/rustc_middle/src/query/erase.rs4
-rw-r--r--compiler/rustc_middle/src/query/mod.rs16
-rw-r--r--compiler/rustc_middle/src/thir.rs25
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs3
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs2
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs2
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs4
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs2
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs4
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs15
-rw-r--r--compiler/rustc_middle/src/ty/region.rs37
-rw-r--r--compiler/rustc_middle/src/ty/significant_drop_order.rs22
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs2
-rw-r--r--compiler/rustc_middle/src/ty/util.rs7
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs6
-rw-r--r--compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/into.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/match_pair.rs33
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs149
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs4
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs74
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs9
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/move_check.rs33
-rw-r--r--compiler/rustc_next_trait_solver/src/lib.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs32
-rw-r--r--compiler/rustc_parse/src/parser/item.rs4
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs20
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs14
-rw-r--r--compiler/rustc_passes/src/check_attr.rs2
-rw-r--r--compiler/rustc_passes/src/input_stats.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs7
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs42
-rw-r--r--compiler/rustc_resolve/src/late.rs13
-rw-r--r--compiler/rustc_smir/src/rustc_internal/internal.rs1
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs1
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs2
-rw-r--r--compiler/rustc_target/src/callconv/loongarch.rs10
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs13
-rw-r--r--compiler/rustc_target/src/callconv/riscv.rs10
-rw-r--r--compiler/rustc_target/src/callconv/x86.rs11
-rw-r--r--compiler/rustc_target/src/spec/mod.rs11
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs12
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs76
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs2
-rw-r--r--compiler/rustc_trait_selection/src/errors/note_and_explain.rs2
-rw-r--r--compiler/rustc_trait_selection/src/opaque_types.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs36
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs90
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs44
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs6
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs4
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs33
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs20
-rw-r--r--compiler/rustc_ty_utils/src/sig_types.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs57
-rw-r--r--compiler/rustc_type_ir/Cargo.toml1
-rw-r--r--compiler/rustc_type_ir/src/data_structures/mod.rs1
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs33
-rw-r--r--compiler/rustc_type_ir/src/interner.rs2
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
-rw-r--r--compiler/rustc_type_ir/src/solve/mod.rs7
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs8
176 files changed, 2091 insertions, 1575 deletions
diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs
index 4d70afd4e0b..55f4845d216 100644
--- a/compiler/rustc_abi/src/extern_abi.rs
+++ b/compiler/rustc_abi/src/extern_abi.rs
@@ -60,7 +60,6 @@ pub enum ExternAbi {
     System {
         unwind: bool,
     },
-    RustIntrinsic,
     RustCall,
     /// *Not* a stable ABI, just directly use the Rust types to describe the ABI for LLVM. Even
     /// normally ABI-compatible Rust types can become ABI-incompatible with this ABI!
@@ -128,7 +127,6 @@ abi_impls! {
             RiscvInterruptS =><= "riscv-interrupt-s",
             RustCall =><= "rust-call",
             RustCold =><= "rust-cold",
-            RustIntrinsic =><= "rust-intrinsic",
             Stdcall { unwind: false } =><= "stdcall",
             Stdcall { unwind: true } =><= "stdcall-unwind",
             System { unwind: false } =><= "system",
@@ -199,7 +197,7 @@ impl ExternAbi {
     /// - are subject to change between compiler versions
     pub fn is_rustic_abi(self) -> bool {
         use ExternAbi::*;
-        matches!(self, Rust | RustCall | RustIntrinsic | RustCold)
+        matches!(self, Rust | RustCall | RustCold)
     }
 
     pub fn supports_varargs(self) -> bool {
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 843d5ca61dd..59b74d29221 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1829,7 +1829,7 @@ pub struct PointeeInfo {
     pub safe: Option<PointerKind>,
     /// If `safe` is `Some`, then the pointer is either null or dereferenceable for this many bytes.
     /// On a function argument, "dereferenceable" here means "dereferenceable for the entire duration
-    /// of this function call", i.e. it is UB for the memory that this pointer points to to be freed
+    /// of this function call", i.e. it is UB for the memory that this pointer points to be freed
     /// while this function is still running.
     /// The size can be zero if the pointer is not dereferenceable.
     pub size: Size,
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 97e6879c33e..3fb88c9599d 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -563,6 +563,7 @@ impl Pat {
     /// This is intended for use by diagnostics.
     pub fn to_ty(&self) -> Option<P<Ty>> {
         let kind = match &self.kind {
+            PatKind::Missing => unreachable!(),
             // In a type expression `_` is an inference variable.
             PatKind::Wild => TyKind::Infer,
             // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
@@ -625,7 +626,8 @@ impl Pat {
             | PatKind::Guard(s, _) => s.walk(it),
 
             // These patterns do not contain subpatterns, skip.
-            PatKind::Wild
+            PatKind::Missing
+            | PatKind::Wild
             | PatKind::Rest
             | PatKind::Never
             | PatKind::Expr(_)
@@ -676,6 +678,7 @@ impl Pat {
     /// Return a name suitable for diagnostics.
     pub fn descr(&self) -> Option<String> {
         match &self.kind {
+            PatKind::Missing => unreachable!(),
             PatKind::Wild => Some("_".to_string()),
             PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")),
             PatKind::Ref(pat, mutbl) => pat.descr().map(|d| format!("&{}{d}", mutbl.prefix_str())),
@@ -769,6 +772,9 @@ pub enum RangeSyntax {
 // Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub enum PatKind {
+    /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`.
+    Missing,
+
     /// Represents a wildcard pattern (`_`).
     Wild,
 
@@ -1169,6 +1175,7 @@ pub enum MacStmtStyle {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Local {
     pub id: NodeId,
+    pub super_: Option<Span>,
     pub pat: P<Pat>,
     pub ty: Option<P<Ty>>,
     pub kind: LocalKind,
@@ -3926,7 +3933,7 @@ mod size_asserts {
     static_assert_size!(Item, 144);
     static_assert_size!(ItemKind, 80);
     static_assert_size!(LitKind, 24);
-    static_assert_size!(Local, 80);
+    static_assert_size!(Local, 96);
     static_assert_size!(MetaItemLit, 40);
     static_assert_size!(Param, 40);
     static_assert_size!(Pat, 72);
diff --git a/compiler/rustc_ast/src/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs
index f01c781f46c..13a7c5a1805 100644
--- a/compiler/rustc_ast/src/expand/autodiff_attrs.rs
+++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs
@@ -92,6 +92,12 @@ pub struct AutoDiffAttrs {
     pub input_activity: Vec<DiffActivity>,
 }
 
+impl AutoDiffAttrs {
+    pub fn has_primal_ret(&self) -> bool {
+        matches!(self.ret_activity, DiffActivity::Active | DiffActivity::Dual)
+    }
+}
+
 impl DiffMode {
     pub fn is_rev(&self) -> bool {
         matches!(self, DiffMode::Reverse)
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index f7d13acdfc4..b083e878905 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -704,7 +704,8 @@ fn walk_parenthesized_parameter_data<T: MutVisitor>(vis: &mut T, args: &mut Pare
 }
 
 fn walk_local<T: MutVisitor>(vis: &mut T, local: &mut P<Local>) {
-    let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut();
+    let Local { id, super_, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut();
+    visit_opt(super_, |sp| vis.visit_span(sp));
     vis.visit_id(id);
     visit_attrs(vis, attrs);
     vis.visit_pat(pat);
@@ -1587,7 +1588,7 @@ pub fn walk_pat<T: MutVisitor>(vis: &mut T, pat: &mut P<Pat>) {
     vis.visit_id(id);
     match kind {
         PatKind::Err(_guar) => {}
-        PatKind::Wild | PatKind::Rest | PatKind::Never => {}
+        PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
         PatKind::Ident(_binding_mode, ident, sub) => {
             vis.visit_ident(ident);
             visit_opt(sub, |sub| vis.visit_pat(sub));
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 1ef92ff8898..79193fcec63 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -323,7 +323,7 @@ pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::R
 }
 
 pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) -> V::Result {
-    let Local { id: _, pat, ty, kind, span: _, colon_sp: _, attrs, tokens: _ } = local;
+    let Local { id: _, super_: _, pat, ty, kind, span: _, colon_sp: _, attrs, tokens: _ } = local;
     walk_list!(visitor, visit_attribute, attrs);
     try_visit!(visitor.visit_pat(pat));
     visit_opt!(visitor, visit_ty, ty);
@@ -750,7 +750,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res
             try_visit!(visitor.visit_pat(subpattern));
             try_visit!(visitor.visit_expr(guard_condition));
         }
-        PatKind::Wild | PatKind::Rest | PatKind::Never => {}
+        PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
         PatKind::Err(_guar) => {}
         PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
             walk_list!(visitor, visit_pat, elems);
diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs
index 1d9ca6bb9c8..c3222b79e55 100644
--- a/compiler/rustc_ast_lowering/src/block.rs
+++ b/compiler/rustc_ast_lowering/src/block.rs
@@ -95,6 +95,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
     fn lower_local(&mut self, l: &Local) -> &'hir hir::LetStmt<'hir> {
         // Let statements are allowed to have impl trait in bindings.
+        let super_ = l.super_;
         let ty = l.ty.as_ref().map(|t| {
             self.lower_ty(t, self.impl_trait_in_bindings_ctxt(ImplTraitPosition::Variable))
         });
@@ -109,7 +110,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let span = self.lower_span(l.span);
         let source = hir::LocalSource::Normal;
         self.lower_attrs(hir_id, &l.attrs, l.span);
-        self.arena.alloc(hir::LetStmt { hir_id, ty, pat, init, els, span, source })
+        self.arena.alloc(hir::LetStmt { hir_id, super_, ty, pat, init, els, span, source })
     }
 
     fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index d5d6dcd8d63..6aa6a18ee9a 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1496,18 +1496,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
     fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] {
         self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
-            PatKind::Ident(_, ident, _) => {
-                if ident.name != kw::Empty {
-                    Some(self.lower_ident(ident))
-                } else {
-                    None
-                }
-            }
+            PatKind::Missing => None,
+            PatKind::Ident(_, ident, _) => Some(self.lower_ident(ident)),
             PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))),
             _ => {
                 self.dcx().span_delayed_bug(
                     param.pat.span,
-                    "non-ident/wild param pat must trigger an error",
+                    "non-missing/ident/wild param pat must trigger an error",
                 );
                 None
             }
@@ -2223,6 +2218,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             self.attrs.insert(hir_id.local_id, a);
         }
         let local = hir::LetStmt {
+            super_: None,
             hir_id,
             init,
             pat,
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 07cc64a1358..f94d788a9b0 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -26,6 +26,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             let pat_hir_id = self.lower_node_id(pattern.id);
             let node = loop {
                 match &pattern.kind {
+                    PatKind::Missing => break hir::PatKind::Missing,
                     PatKind::Wild => break hir::PatKind::Wild,
                     PatKind::Never => break hir::PatKind::Never,
                     PatKind::Ident(binding_mode, ident, sub) => {
diff --git a/compiler/rustc_ast_lowering/src/stability.rs b/compiler/rustc_ast_lowering/src/stability.rs
index a2004bbb39f..eb052ba1c6d 100644
--- a/compiler/rustc_ast_lowering/src/stability.rs
+++ b/compiler/rustc_ast_lowering/src/stability.rs
@@ -79,10 +79,6 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> {
         | ExternAbi::SysV64 { .. }
         | ExternAbi::System { .. }
         | ExternAbi::EfiApi => Ok(()),
-        // implementation details
-        ExternAbi::RustIntrinsic => {
-            Err(UnstableAbi { abi, feature: sym::intrinsics, explain: GateReason::ImplDetail })
-        }
         ExternAbi::Unadjusted => {
             Err(UnstableAbi { abi, feature: sym::abi_unadjusted, explain: GateReason::ImplDetail })
         }
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 9916de8b7b1..dc77e7b2834 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -244,7 +244,7 @@ impl<'a> AstValidator<'a> {
     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
         for Param { pat, .. } in &decl.inputs {
             match pat.kind {
-                PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {}
+                PatKind::Missing | PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {}
                 PatKind::Ident(BindingMode::MUT, ident, None) => {
                     report_err(pat.span, Some(ident), true)
                 }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 3dbfc191f8f..90caad1c845 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1336,6 +1336,9 @@ impl<'a> State<'a> {
                 self.print_outer_attributes(&loc.attrs);
                 self.space_if_not_bol();
                 self.ibox(INDENT_UNIT);
+                if loc.super_.is_some() {
+                    self.word_nbsp("super");
+                }
                 self.word_nbsp("let");
 
                 self.ibox(INDENT_UNIT);
@@ -1622,9 +1625,9 @@ impl<'a> State<'a> {
     fn print_pat(&mut self, pat: &ast::Pat) {
         self.maybe_print_comment(pat.span.lo());
         self.ann.pre(self, AnnNode::Pat(pat));
-        /* Pat isn't normalized, but the beauty of it
-        is that it doesn't matter */
+        /* Pat isn't normalized, but the beauty of it is that it doesn't matter */
         match &pat.kind {
+            PatKind::Missing => unreachable!(),
             PatKind::Wild => self.word("_"),
             PatKind::Never => self.word("!"),
             PatKind::Ident(BindingMode(by_ref, mutbl), ident, sub) => {
@@ -1946,12 +1949,7 @@ impl<'a> State<'a> {
                 if let Some(eself) = input.to_self() {
                     self.print_explicit_self(&eself);
                 } else {
-                    let invalid = if let PatKind::Ident(_, ident, _) = input.pat.kind {
-                        ident.name == kw::Empty
-                    } else {
-                        false
-                    };
-                    if !invalid {
+                    if !matches!(input.pat.kind, PatKind::Missing) {
                         self.print_pat(&input.pat);
                         self.word(":");
                         self.space();
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index 45cdd232564..1f087b09234 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -15,6 +15,7 @@ pub use super::polonius::legacy::{
     RichLocation, RustcFacts,
 };
 pub use super::region_infer::RegionInferenceContext;
+use crate::{BorrowCheckRootCtxt, do_mir_borrowck};
 
 /// Options determining the output behavior of [`get_body_with_borrowck_facts`].
 ///
@@ -97,8 +98,9 @@ pub struct BodyWithBorrowckFacts<'tcx> {
 /// *   Polonius is highly unstable, so expect regular changes in its signature or other details.
 pub fn get_body_with_borrowck_facts(
     tcx: TyCtxt<'_>,
-    def: LocalDefId,
+    def_id: LocalDefId,
     options: ConsumerOptions,
 ) -> BodyWithBorrowckFacts<'_> {
-    *super::do_mir_borrowck(tcx, def, Some(options)).1.unwrap()
+    let mut root_cx = BorrowCheckRootCtxt::new(tcx, def_id);
+    *do_mir_borrowck(&mut root_cx, def_id, Some(options)).1.unwrap()
 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index aa968a1e40f..134f30ed6f5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -406,8 +406,8 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
             // started MIR borrowchecking with, so the region
             // constraints have already been taken. Use the data from
             // our `mbcx` instead.
-            |vid| mbcx.regioncx.var_infos[vid].origin,
-            |vid| mbcx.regioncx.var_infos[vid].universe,
+            |vid| RegionVariableOrigin::Nll(mbcx.regioncx.definitions[vid].origin),
+            |vid| mbcx.regioncx.definitions[vid].universe,
         )
     }
 }
@@ -487,7 +487,7 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
     let (sub_region, cause) = info?;
 
     debug!(?sub_region, "cause = {:#?}", cause);
-    let error = match (error_region, *sub_region) {
+    let error = match (error_region, sub_region.kind()) {
         (Some(error_region), ty::ReVar(vid)) => RegionResolutionError::SubSupConflict(
             vid,
             region_var_origin(vid),
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 899e145c2c0..eb664f1d4f2 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -8,9 +8,7 @@ use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify};
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::{self as hir, CoroutineKind, LangItem};
 use rustc_index::IndexSlice;
-use rustc_infer::infer::{
-    BoundRegionConversionTime, NllRegionVariableOrigin, RegionVariableOrigin,
-};
+use rustc_infer::infer::{BoundRegionConversionTime, NllRegionVariableOrigin};
 use rustc_infer::traits::SelectionError;
 use rustc_middle::bug;
 use rustc_middle::mir::{
@@ -587,7 +585,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         // this by hooking into the pretty printer and telling it to label the
         // lifetimes without names with the value `'0`.
         if let ty::Ref(region, ..) = ty.kind() {
-            match **region {
+            match region.kind() {
                 ty::ReBound(_, ty::BoundRegion { kind: br, .. })
                 | ty::RePlaceholder(ty::PlaceholderRegion {
                     bound: ty::BoundRegion { kind: br, .. },
@@ -607,7 +605,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, Namespace::TypeNS);
 
         let region = if let ty::Ref(region, ..) = ty.kind() {
-            match **region {
+            match region.kind() {
                 ty::ReBound(_, ty::BoundRegion { kind: br, .. })
                 | ty::RePlaceholder(ty::PlaceholderRegion {
                     bound: ty::BoundRegion { kind: br, .. },
@@ -633,9 +631,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     ) {
         let predicate_span = path.iter().find_map(|constraint| {
             let outlived = constraint.sub;
-            if let Some(origin) = self.regioncx.var_infos.get(outlived)
-                && let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(_)) =
-                    origin.origin
+            if let Some(origin) = self.regioncx.definitions.get(outlived)
+                && let NllRegionVariableOrigin::Placeholder(_) = origin.origin
                 && let ConstraintCategory::Predicate(span) = constraint.category
             {
                 Some(span)
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index d1d783c22e3..8d530b51636 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -190,7 +190,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        fold_regions(tcx, ty, |region, _| match *region {
+        fold_regions(tcx, ty, |region, _| match region.kind() {
             ty::ReVar(vid) => self.to_error_region(vid).unwrap_or(region),
             _ => region,
         })
@@ -198,7 +198,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
     /// Returns `true` if a closure is inferred to be an `FnMut` closure.
     fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
-        if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).as_deref()
+        if let Some(r) = self.to_error_region(fr)
+            && let ty::ReLateParam(late_param) = r.kind()
             && let ty::LateParamRegionKind::ClosureEnv = late_param.kind
             && let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty
         {
@@ -832,7 +833,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         if let (Some(f), Some(outlived_f)) =
             (self.to_error_region(fr), self.to_error_region(outlived_fr))
         {
-            if *outlived_f != ty::ReStatic {
+            if outlived_f.kind() != ty::ReStatic {
                 return;
             }
             let suitable_region = self.infcx.tcx.is_suitable_region(self.mir_def_id(), f);
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 45f5eaa514b..b08c10983bb 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -288,7 +288,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
         let tcx = self.infcx.tcx;
 
         debug!("give_region_a_name: error_region = {:?}", error_region);
-        match *error_region {
+        match error_region.kind() {
             ty::ReEarlyParam(ebr) => ebr.has_name().then(|| {
                 let def_id = tcx.generics_of(self.mir_def_id()).region_param(ebr, tcx).def_id;
                 let span = tcx.hir_span_if_local(def_id).unwrap_or(DUMMY_SP);
@@ -896,7 +896,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
         &self,
         fr: RegionVid,
     ) -> Option<RegionName> {
-        let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else {
+        let ty::ReEarlyParam(region) = self.to_error_region(fr)?.kind() else {
             return None;
         };
         if region.has_name() {
@@ -912,7 +912,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
 
         let found = tcx
             .any_free_region_meets(&tcx.type_of(region_parent).instantiate_identity(), |r| {
-                *r == ty::ReEarlyParam(region)
+                r.kind() == ty::ReEarlyParam(region)
             });
 
         Some(RegionName {
@@ -931,7 +931,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
         &self,
         fr: RegionVid,
     ) -> Option<RegionName> {
-        let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else {
+        let ty::ReEarlyParam(region) = self.to_error_region(fr)?.kind() else {
             return None;
         };
         if region.has_name() {
@@ -1007,7 +1007,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
                             if data.projection_term.self_ty() == ty => {}
                         _ => return false,
                     }
-                    tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyParam(region))
+                    tcx.any_free_region_meets(pred, |r| r.kind() == ty::ReEarlyParam(region))
                 })
             } else {
                 false
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 240bd20053b..64ad1c96856 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -9,6 +9,7 @@
 #![feature(file_buffered)]
 #![feature(if_let_guard)]
 #![feature(let_chains)]
+#![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
@@ -21,6 +22,7 @@ use std::cell::RefCell;
 use std::marker::PhantomData;
 use std::ops::{ControlFlow, Deref};
 
+use root_cx::BorrowCheckRootCtxt;
 use rustc_abi::FieldIdx;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::graph::dominators::Dominators;
@@ -35,7 +37,9 @@ use rustc_infer::infer::{
 };
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
+use rustc_middle::ty::{
+    self, ParamEnv, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypingMode, fold_regions,
+};
 use rustc_middle::{bug, span_bug};
 use rustc_mir_dataflow::impls::{
     EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
@@ -45,7 +49,7 @@ use rustc_mir_dataflow::move_paths::{
 };
 use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results};
 use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER, UNUSED_MUT};
-use rustc_span::{Span, Symbol};
+use rustc_span::{ErrorGuaranteed, Span, Symbol};
 use smallvec::SmallVec;
 use tracing::{debug, instrument};
 
@@ -73,7 +77,6 @@ mod def_use;
 mod diagnostics;
 mod member_constraints;
 mod nll;
-mod opaque_types;
 mod path_utils;
 mod place_ext;
 mod places_conflict;
@@ -81,6 +84,7 @@ mod polonius;
 mod prefixes;
 mod region_infer;
 mod renumber;
+mod root_cx;
 mod session_diagnostics;
 mod type_check;
 mod universal_regions;
@@ -102,44 +106,202 @@ pub fn provide(providers: &mut Providers) {
     *providers = Providers { mir_borrowck, ..*providers };
 }
 
-fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
+/// Provider for `query mir_borrowck`. Similar to `typeck`, this must
+/// only be called for typeck roots which will then borrowck all
+/// nested bodies as well.
+fn mir_borrowck(
+    tcx: TyCtxt<'_>,
+    def: LocalDefId,
+) -> Result<&ConcreteOpaqueTypes<'_>, ErrorGuaranteed> {
+    assert!(!tcx.is_typeck_child(def.to_def_id()));
     let (input_body, _) = tcx.mir_promoted(def);
+    debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
+
     let input_body: &Body<'_> = &input_body.borrow();
-    if input_body.should_skip() || input_body.tainted_by_errors.is_some() {
-        debug!("Skipping borrowck because of injected body or tainted body");
-        // Let's make up a borrowck result! Fun times!
-        let result = BorrowCheckResult {
-            concrete_opaque_types: FxIndexMap::default(),
-            closure_requirements: None,
-            used_mut_upvars: SmallVec::new(),
-            tainted_by_errors: input_body.tainted_by_errors,
-        };
-        return tcx.arena.alloc(result);
+    if let Some(guar) = input_body.tainted_by_errors {
+        debug!("Skipping borrowck because of tainted body");
+        Err(guar)
+    } else if input_body.should_skip() {
+        debug!("Skipping borrowck because of injected body");
+        let opaque_types = ConcreteOpaqueTypes(Default::default());
+        Ok(tcx.arena.alloc(opaque_types))
+    } else {
+        let mut root_cx = BorrowCheckRootCtxt::new(tcx, def);
+        let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
+            do_mir_borrowck(&mut root_cx, def, None).0;
+        debug_assert!(closure_requirements.is_none());
+        debug_assert!(used_mut_upvars.is_empty());
+        root_cx.finalize()
     }
+}
+
+/// Data propagated to the typeck parent by nested items.
+/// This should always be empty for the typeck root.
+#[derive(Debug)]
+struct PropagatedBorrowCheckResults<'tcx> {
+    closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
+    used_mut_upvars: SmallVec<[FieldIdx; 8]>,
+}
+
+/// After we borrow check a closure, we are left with various
+/// requirements that we have inferred between the free regions that
+/// appear in the closure's signature or on its field types. These
+/// requirements are then verified and proved by the closure's
+/// creating function. This struct encodes those requirements.
+///
+/// The requirements are listed as being between various `RegionVid`. The 0th
+/// region refers to `'static`; subsequent region vids refer to the free
+/// regions that appear in the closure (or coroutine's) type, in order of
+/// appearance. (This numbering is actually defined by the `UniversalRegions`
+/// struct in the NLL region checker. See for example
+/// `UniversalRegions::closure_mapping`.) Note the free regions in the
+/// closure's signature and captures are erased.
+///
+/// Example: If type check produces a closure with the closure args:
+///
+/// ```text
+/// ClosureArgs = [
+///     'a,                                         // From the parent.
+///     'b,
+///     i8,                                         // the "closure kind"
+///     for<'x> fn(&'<erased> &'x u32) -> &'x u32,  // the "closure signature"
+///     &'<erased> String,                          // some upvar
+/// ]
+/// ```
+///
+/// We would "renumber" each free region to a unique vid, as follows:
+///
+/// ```text
+/// ClosureArgs = [
+///     '1,                                         // From the parent.
+///     '2,
+///     i8,                                         // the "closure kind"
+///     for<'x> fn(&'3 &'x u32) -> &'x u32,         // the "closure signature"
+///     &'4 String,                                 // some upvar
+/// ]
+/// ```
+///
+/// Now the code might impose a requirement like `'1: '2`. When an
+/// instance of the closure is created, the corresponding free regions
+/// can be extracted from its type and constrained to have the given
+/// outlives relationship.
+#[derive(Clone, Debug)]
+pub struct ClosureRegionRequirements<'tcx> {
+    /// The number of external regions defined on the closure. In our
+    /// example above, it would be 3 -- one for `'static`, then `'1`
+    /// and `'2`. This is just used for a sanity check later on, to
+    /// make sure that the number of regions we see at the callsite
+    /// matches.
+    pub num_external_vids: usize,
+
+    /// Requirements between the various free regions defined in
+    /// indices.
+    pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
+}
 
-    let borrowck_result = do_mir_borrowck(tcx, def, None).0;
-    debug!("mir_borrowck done");
+/// Indicates an outlives-constraint between a type or between two
+/// free regions declared on the closure.
+#[derive(Copy, Clone, Debug)]
+pub struct ClosureOutlivesRequirement<'tcx> {
+    // This region or type ...
+    pub subject: ClosureOutlivesSubject<'tcx>,
 
-    tcx.arena.alloc(borrowck_result)
+    // ... must outlive this one.
+    pub outlived_free_region: ty::RegionVid,
+
+    // If not, report an error here ...
+    pub blame_span: Span,
+
+    // ... due to this reason.
+    pub category: ConstraintCategory<'tcx>,
+}
+
+// Make sure this enum doesn't unintentionally grow
+#[cfg(target_pointer_width = "64")]
+rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
+
+/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
+/// that must outlive some region.
+#[derive(Copy, Clone, Debug)]
+pub enum ClosureOutlivesSubject<'tcx> {
+    /// Subject is a type, typically a type parameter, but could also
+    /// be a projection. Indicates a requirement like `T: 'a` being
+    /// passed to the caller, where the type here is `T`.
+    Ty(ClosureOutlivesSubjectTy<'tcx>),
+
+    /// Subject is a free region from the closure. Indicates a requirement
+    /// like `'a: 'b` being passed to the caller; the region here is `'a`.
+    Region(ty::RegionVid),
+}
+
+/// Represents a `ty::Ty` for use in [`ClosureOutlivesSubject`].
+///
+/// This abstraction is necessary because the type may include `ReVar` regions,
+/// which is what we use internally within NLL code, and they can't be used in
+/// a query response.
+#[derive(Copy, Clone, Debug)]
+pub struct ClosureOutlivesSubjectTy<'tcx> {
+    inner: Ty<'tcx>,
+}
+// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this
+// type is not recognized as a binder for late-bound region.
+impl<'tcx, I> !TypeVisitable<I> for ClosureOutlivesSubjectTy<'tcx> {}
+impl<'tcx, I> !TypeFoldable<I> for ClosureOutlivesSubjectTy<'tcx> {}
+
+impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
+    /// All regions of `ty` must be of kind `ReVar` and must represent
+    /// universal regions *external* to the closure.
+    pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
+        let inner = fold_regions(tcx, ty, |r, depth| match r.kind() {
+            ty::ReVar(vid) => {
+                let br = ty::BoundRegion {
+                    var: ty::BoundVar::from_usize(vid.index()),
+                    kind: ty::BoundRegionKind::Anon,
+                };
+                ty::Region::new_bound(tcx, depth, br)
+            }
+            _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
+        });
+
+        Self { inner }
+    }
+
+    pub fn instantiate(
+        self,
+        tcx: TyCtxt<'tcx>,
+        mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>,
+    ) -> Ty<'tcx> {
+        fold_regions(tcx, self.inner, |r, depth| match r.kind() {
+            ty::ReBound(debruijn, br) => {
+                debug_assert_eq!(debruijn, depth);
+                map(ty::RegionVid::from_usize(br.var.index()))
+            }
+            _ => bug!("unexpected region {r:?}"),
+        })
+    }
 }
 
 /// Perform the actual borrow checking.
 ///
 /// Use `consumer_options: None` for the default behavior of returning
-/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
-/// to the given [`ConsumerOptions`].
-#[instrument(skip(tcx), level = "debug")]
+/// [`PropagatedBorrowCheckResults`] only. Otherwise, return [`BodyWithBorrowckFacts`]
+/// according to the given [`ConsumerOptions`].
+///
+/// For nested bodies this should only be called through `root_cx.get_or_insert_nested`.
+#[instrument(skip(root_cx), level = "debug")]
 fn do_mir_borrowck<'tcx>(
-    tcx: TyCtxt<'tcx>,
+    root_cx: &mut BorrowCheckRootCtxt<'tcx>,
     def: LocalDefId,
     consumer_options: Option<ConsumerOptions>,
-) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
+) -> (PropagatedBorrowCheckResults<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
+    let tcx = root_cx.tcx;
     let infcx = BorrowckInferCtxt::new(tcx, def);
     let (input_body, promoted) = tcx.mir_promoted(def);
     let input_body: &Body<'_> = &input_body.borrow();
     let input_promoted: &IndexSlice<_, _> = &promoted.borrow();
     if let Some(e) = input_body.tainted_by_errors {
         infcx.set_tainted_by_errors(e);
+        root_cx.set_tainted_by_errors(e);
     }
 
     let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
@@ -185,13 +347,13 @@ fn do_mir_borrowck<'tcx>(
     // Compute non-lexical lifetimes.
     let nll::NllOutput {
         regioncx,
-        concrete_opaque_types,
         polonius_input,
         polonius_output,
         opt_closure_req,
         nll_errors,
         polonius_diagnostics,
     } = nll::compute_regions(
+        root_cx,
         &infcx,
         free_regions,
         body,
@@ -210,26 +372,19 @@ fn do_mir_borrowck<'tcx>(
     // We also have a `#[rustc_regions]` annotation that causes us to dump
     // information.
     let diags_buffer = &mut BorrowckDiagnosticsBuffer::default();
-    nll::dump_annotation(
-        &infcx,
-        body,
-        &regioncx,
-        &opt_closure_req,
-        &concrete_opaque_types,
-        diags_buffer,
-    );
+    nll::dump_annotation(&infcx, body, &regioncx, &opt_closure_req, diags_buffer);
 
     let movable_coroutine =
-        // The first argument is the coroutine type passed by value
-        if let Some(local) = body.local_decls.raw.get(1)
-        // Get the interior types and args which typeck computed
-        && let ty::Coroutine(def_id, _) = *local.ty.kind()
-        && tcx.coroutine_movability(def_id) == hir::Movability::Movable
-    {
-        true
-    } else {
-        false
-    };
+    // The first argument is the coroutine type passed by value
+    if let Some(local) = body.local_decls.raw.get(1)
+    // Get the interior types and args which typeck computed
+    && let ty::Coroutine(def_id, _) = *local.ty.kind()
+    && tcx.coroutine_movability(def_id) == hir::Movability::Movable
+{
+    true
+} else {
+    false
+};
 
     // While promoteds should mostly be correct by construction, we need to check them for
     // invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
@@ -240,6 +395,7 @@ fn do_mir_borrowck<'tcx>(
         // this check out of `MirBorrowckCtxt`, actually doing so is far from trivial.
         let move_data = MoveData::gather_moves(promoted_body, tcx, |_| true);
         let mut promoted_mbcx = MirBorrowckCtxt {
+            root_cx,
             infcx: &infcx,
             body: promoted_body,
             move_data: &move_data,
@@ -280,6 +436,7 @@ fn do_mir_borrowck<'tcx>(
     }
 
     let mut mbcx = MirBorrowckCtxt {
+        root_cx,
         infcx: &infcx,
         body,
         move_data: &move_data,
@@ -347,13 +504,13 @@ fn do_mir_borrowck<'tcx>(
 
     debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
     mbcx.lint_unused_mut();
-    let tainted_by_errors = mbcx.emit_errors();
+    if let Some(guar) = mbcx.emit_errors() {
+        mbcx.root_cx.set_tainted_by_errors(guar);
+    }
 
-    let result = BorrowCheckResult {
-        concrete_opaque_types: concrete_opaque_types.into_inner(),
+    let result = PropagatedBorrowCheckResults {
         closure_requirements: opt_closure_req,
         used_mut_upvars: mbcx.used_mut_upvars,
-        tainted_by_errors,
     };
 
     let body_with_facts = if consumer_options.is_some() {
@@ -488,6 +645,7 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
 }
 
 struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
+    root_cx: &'a mut BorrowCheckRootCtxt<'tcx>,
     infcx: &'infcx BorrowckInferCtxt<'tcx>,
     body: &'a Body<'tcx>,
     move_data: &'a MoveData<'tcx>,
@@ -1361,11 +1519,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
                     | AggregateKind::CoroutineClosure(def_id, _)
                     | AggregateKind::Coroutine(def_id, _) => {
                         let def_id = def_id.expect_local();
-                        let BorrowCheckResult { used_mut_upvars, .. } =
-                            self.infcx.tcx.mir_borrowck(def_id);
+                        let used_mut_upvars = self.root_cx.used_mut_upvars(def_id);
                         debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
-                        for field in used_mut_upvars {
-                            self.propagate_closure_used_mut_upvar(&operands[*field]);
+                        // FIXME: We're cloning the `SmallVec` here to avoid borrowing `root_cx`
+                        // when calling `propagate_closure_used_mut_upvar`. This should ideally
+                        // be unnecessary.
+                        for field in used_mut_upvars.clone() {
+                            self.propagate_closure_used_mut_upvar(&operands[field]);
                         }
                     }
                     AggregateKind::Adt(..)
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 8e7b6f083ac..8a2a34f207a 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -8,10 +8,7 @@ use std::str::FromStr;
 use polonius_engine::{Algorithm, Output};
 use rustc_index::IndexSlice;
 use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
-use rustc_middle::mir::{
-    Body, ClosureOutlivesSubject, ClosureRegionRequirements, PassWhere, Promoted, create_dump_file,
-    dump_enabled, dump_mir,
-};
+use rustc_middle::mir::{Body, PassWhere, Promoted, create_dump_file, dump_enabled, dump_mir};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_mir_dataflow::ResultsCursor;
@@ -25,7 +22,6 @@ use tracing::{debug, instrument};
 use crate::borrow_set::BorrowSet;
 use crate::consumers::ConsumerOptions;
 use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors};
-use crate::opaque_types::ConcreteOpaqueTypes;
 use crate::polonius::PoloniusDiagnosticsContext;
 use crate::polonius::legacy::{
     PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
@@ -33,13 +29,15 @@ use crate::polonius::legacy::{
 use crate::region_infer::RegionInferenceContext;
 use crate::type_check::{self, MirTypeckResults};
 use crate::universal_regions::UniversalRegions;
-use crate::{BorrowckInferCtxt, polonius, renumber};
+use crate::{
+    BorrowCheckRootCtxt, BorrowckInferCtxt, ClosureOutlivesSubject, ClosureRegionRequirements,
+    polonius, renumber,
+};
 
 /// The output of `nll::compute_regions`. This includes the computed `RegionInferenceContext`, any
 /// closure requirements to propagate, and any generated errors.
 pub(crate) struct NllOutput<'tcx> {
     pub regioncx: RegionInferenceContext<'tcx>,
-    pub concrete_opaque_types: ConcreteOpaqueTypes<'tcx>,
     pub polonius_input: Option<Box<PoloniusFacts>>,
     pub polonius_output: Option<Box<PoloniusOutput>>,
     pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
@@ -78,6 +76,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
 ///
 /// This may result in errors being reported.
 pub(crate) fn compute_regions<'a, 'tcx>(
+    root_cx: &mut BorrowCheckRootCtxt<'tcx>,
     infcx: &BorrowckInferCtxt<'tcx>,
     universal_regions: UniversalRegions<'tcx>,
     body: &Body<'tcx>,
@@ -98,8 +97,6 @@ pub(crate) fn compute_regions<'a, 'tcx>(
 
     let location_map = Rc::new(DenseLocationMap::new(body));
 
-    let mut concrete_opaque_types = ConcreteOpaqueTypes::default();
-
     // Run the MIR type-checker.
     let MirTypeckResults {
         constraints,
@@ -107,6 +104,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         opaque_type_values,
         polonius_context,
     } = type_check::type_check(
+        root_cx,
         infcx,
         body,
         promoted,
@@ -117,7 +115,6 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         flow_inits,
         move_data,
         Rc::clone(&location_map),
-        &mut concrete_opaque_types,
     );
 
     // Create the region inference context, taking ownership of the
@@ -181,11 +178,10 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         infcx.set_tainted_by_errors(guar);
     }
 
-    regioncx.infer_opaque_types(infcx, opaque_type_values, &mut concrete_opaque_types);
+    regioncx.infer_opaque_types(root_cx, infcx, opaque_type_values);
 
     NllOutput {
         regioncx,
-        concrete_opaque_types,
         polonius_input: polonius_facts.map(Box::new),
         polonius_output,
         opt_closure_req: closure_region_requirements,
@@ -301,7 +297,6 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
     body: &Body<'tcx>,
     regioncx: &RegionInferenceContext<'tcx>,
     closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
-    concrete_opaque_types: &ConcreteOpaqueTypes<'tcx>,
     diagnostics_buffer: &mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>,
 ) {
     let tcx = infcx.tcx;
@@ -318,7 +313,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
     // better.
 
     let def_span = tcx.def_span(body.source.def_id());
-    let mut err = if let Some(closure_region_requirements) = closure_region_requirements {
+    let err = if let Some(closure_region_requirements) = closure_region_requirements {
         let mut err = infcx.dcx().struct_span_note(def_span, "external requirements");
 
         regioncx.annotate(tcx, &mut err);
@@ -344,9 +339,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
         err
     };
 
-    if !concrete_opaque_types.is_empty() {
-        err.note(format!("Inferred opaque type values:\n{concrete_opaque_types:#?}"));
-    }
+    // FIXME(@lcnr): We currently don't dump the inferred hidden types here.
 
     diagnostics_buffer.buffer_non_error(err);
 }
diff --git a/compiler/rustc_borrowck/src/opaque_types.rs b/compiler/rustc_borrowck/src/opaque_types.rs
deleted file mode 100644
index 5c78814abdd..00000000000
--- a/compiler/rustc_borrowck/src/opaque_types.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-use rustc_data_structures::fx::FxIndexMap;
-use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt};
-
-#[derive(Debug, Default)]
-pub(super) struct ConcreteOpaqueTypes<'tcx> {
-    concrete_opaque_types: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
-}
-
-impl<'tcx> ConcreteOpaqueTypes<'tcx> {
-    pub(super) fn is_empty(&self) -> bool {
-        self.concrete_opaque_types.is_empty()
-    }
-
-    pub(super) fn into_inner(self) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
-        self.concrete_opaque_types
-    }
-
-    /// Insert an opaque type into the list of opaque types defined by this function
-    /// after mapping the hidden type to the generic parameters of the opaque type
-    /// definition.
-    pub(super) fn insert(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        def_id: LocalDefId,
-        hidden_ty: OpaqueHiddenType<'tcx>,
-    ) {
-        // Sometimes two opaque types are the same only after we remap the generic parameters
-        // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
-        // `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
-        // only know that once we convert the generic parameters to those of the opaque type.
-        if let Some(prev) = self.concrete_opaque_types.get_mut(&def_id) {
-            if prev.ty != hidden_ty.ty {
-                let (Ok(guar) | Err(guar)) =
-                    prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit());
-                prev.ty = Ty::new_error(tcx, guar);
-            }
-            // Pick a better span if there is one.
-            // FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
-            prev.span = prev.span.substitute_dummy(hidden_ty.span);
-        } else {
-            self.concrete_opaque_types.insert(def_id, hidden_ty);
-        }
-    }
-
-    pub(super) fn extend_from_nested_body(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        nested_body: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
-    ) {
-        for (&def_id, &hidden_ty) in nested_body {
-            self.insert(tcx, def_id, hidden_ty);
-        }
-    }
-}
diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs
index aa64a7c4e2a..eb53a98832c 100644
--- a/compiler/rustc_borrowck/src/polonius/dump.rs
+++ b/compiler/rustc_borrowck/src/polonius/dump.rs
@@ -5,7 +5,7 @@ use rustc_index::IndexVec;
 use rustc_middle::mir::pretty::{
     PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer,
 };
-use rustc_middle::mir::{Body, ClosureRegionRequirements, Location};
+use rustc_middle::mir::{Body, Location};
 use rustc_middle::ty::{RegionVid, TyCtxt};
 use rustc_mir_dataflow::points::PointIndex;
 use rustc_session::config::MirIncludeSpans;
@@ -17,7 +17,7 @@ use crate::polonius::{
 };
 use crate::region_infer::values::LivenessValues;
 use crate::type_check::Locations;
-use crate::{BorrowckInferCtxt, RegionInferenceContext};
+use crate::{BorrowckInferCtxt, ClosureRegionRequirements, RegionInferenceContext};
 
 /// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information.
 pub(crate) fn dump_polonius_mir<'tcx>(
@@ -334,7 +334,7 @@ fn emit_mermaid_nll_regions<'tcx>(
     writeln!(out, "flowchart TD")?;
 
     // Emit the region nodes.
-    for region in regioncx.var_infos.indices() {
+    for region in regioncx.definitions.indices() {
         write!(out, "{}[\"", region.as_usize())?;
         render_region(region, regioncx, out)?;
         writeln!(out, "\"]")?;
@@ -387,7 +387,7 @@ fn emit_mermaid_nll_sccs<'tcx>(
     // Gather and emit the SCC nodes.
     let mut nodes_per_scc: IndexVec<_, _> =
         regioncx.constraint_sccs().all_sccs().map(|_| Vec::new()).collect();
-    for region in regioncx.var_infos.indices() {
+    for region in regioncx.definitions.indices() {
         let scc = regioncx.constraint_sccs().scc(region);
         nodes_per_scc[scc].push(region);
     }
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index a80d74d9e37..569c46e6403 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -13,18 +13,16 @@ use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound,
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
 use rustc_middle::bug;
 use rustc_middle::mir::{
-    AnnotationSource, BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject,
-    ClosureOutlivesSubjectTy, ClosureRegionRequirements, ConstraintCategory, Local, Location,
-    ReturnConstraint, TerminatorKind,
+    AnnotationSource, BasicBlock, Body, ConstraintCategory, Local, Location, ReturnConstraint,
+    TerminatorKind,
 };
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, fold_regions};
 use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::{DUMMY_SP, Span};
-use tracing::{debug, instrument, trace};
+use tracing::{Level, debug, enabled, instrument, trace};
 
-use crate::BorrowckInferCtxt;
 use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph};
 use crate::constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet};
 use crate::dataflow::BorrowIndex;
@@ -37,6 +35,10 @@ use crate::region_infer::values::{LivenessValues, RegionElement, RegionValues, T
 use crate::type_check::free_region_relations::UniversalRegionRelations;
 use crate::type_check::{Locations, MirTypeckRegionConstraints};
 use crate::universal_regions::UniversalRegions;
+use crate::{
+    BorrowckInferCtxt, ClosureOutlivesRequirement, ClosureOutlivesSubject,
+    ClosureOutlivesSubjectTy, ClosureRegionRequirements,
+};
 
 mod dump_mir;
 mod graphviz;
@@ -139,13 +141,11 @@ impl RegionTracker {
 }
 
 pub struct RegionInferenceContext<'tcx> {
-    pub var_infos: VarInfos,
-
     /// Contains the definition for every region variable. Region
     /// variables are identified by their index (`RegionVid`). The
     /// definition contains information about where the region came
     /// from as well as its final inferred value.
-    definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
+    pub(crate) definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
 
     /// The liveness constraints added to each region. For most
     /// regions, these start out empty and steadily grow, though for
@@ -327,11 +327,13 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) {
     let mut var_to_origin_sorted = var_to_origin.clone().into_iter().collect::<Vec<_>>();
     var_to_origin_sorted.sort_by_key(|vto| vto.0);
 
-    let mut reg_vars_to_origins_str = "region variables to origins:\n".to_string();
-    for (reg_var, origin) in var_to_origin_sorted.into_iter() {
-        reg_vars_to_origins_str.push_str(&format!("{reg_var:?}: {origin:?}\n"));
+    if enabled!(Level::DEBUG) {
+        let mut reg_vars_to_origins_str = "region variables to origins:\n".to_string();
+        for (reg_var, origin) in var_to_origin_sorted.into_iter() {
+            reg_vars_to_origins_str.push_str(&format!("{reg_var:?}: {origin:?}\n"));
+        }
+        debug!("{}", reg_vars_to_origins_str);
     }
-    debug!("{}", reg_vars_to_origins_str);
 
     let num_components = sccs.num_sccs();
     let mut components = vec![FxIndexSet::default(); num_components];
@@ -342,16 +344,18 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) {
         components[scc_idx.as_usize()].insert((reg_var, *origin));
     }
 
-    let mut components_str = "strongly connected components:".to_string();
-    for (scc_idx, reg_vars_origins) in components.iter().enumerate() {
-        let regions_info = reg_vars_origins.clone().into_iter().collect::<Vec<_>>();
-        components_str.push_str(&format!(
-            "{:?}: {:?},\n)",
-            ConstraintSccIndex::from_usize(scc_idx),
-            regions_info,
-        ))
+    if enabled!(Level::DEBUG) {
+        let mut components_str = "strongly connected components:".to_string();
+        for (scc_idx, reg_vars_origins) in components.iter().enumerate() {
+            let regions_info = reg_vars_origins.clone().into_iter().collect::<Vec<_>>();
+            components_str.push_str(&format!(
+                "{:?}: {:?},\n)",
+                ConstraintSccIndex::from_usize(scc_idx),
+                regions_info,
+            ))
+        }
+        debug!("{}", components_str);
     }
-    debug!("{}", components_str);
 
     // calculate the best representative for each component
     let components_representatives = components
@@ -449,7 +453,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             Rc::new(member_constraints.into_mapped(|r| constraint_sccs.scc(r)));
 
         let mut result = Self {
-            var_infos,
             definitions,
             liveness_constraints,
             constraints,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index a098450352f..550c57338d3 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -10,7 +10,7 @@ use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
 use tracing::{debug, instrument};
 
 use super::RegionInferenceContext;
-use crate::opaque_types::ConcreteOpaqueTypes;
+use crate::BorrowCheckRootCtxt;
 use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
 use crate::universal_regions::RegionClassification;
 
@@ -58,12 +58,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// [rustc-dev-guide chapter]:
     /// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
-    #[instrument(level = "debug", skip(self, infcx), ret)]
+    #[instrument(level = "debug", skip(self, root_cx, infcx), ret)]
     pub(crate) fn infer_opaque_types(
         &self,
+        root_cx: &mut BorrowCheckRootCtxt<'tcx>,
         infcx: &InferCtxt<'tcx>,
         opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
-        concrete_opaque_types: &mut ConcreteOpaqueTypes<'tcx>,
     ) {
         let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
             FxIndexMap::default();
@@ -140,11 +140,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 }
             }
 
-            concrete_opaque_types.insert(
-                infcx.tcx,
+            root_cx.add_concrete_opaque_type(
                 opaque_type_key.def_id,
-                OpaqueHiddenType { ty, span: concrete_type.span },
+                OpaqueHiddenType { span: concrete_type.span, ty },
             );
+
             // Check that all opaque types have the same region parameters if they have the same
             // non-region parameters. This is necessary because within the new solver we perform
             // various query operations modulo regions, and thus could unsoundly select some impls
@@ -186,7 +186,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        fold_regions(tcx, ty, |region, _| match *region {
+        fold_regions(tcx, ty, |region, _| match region.kind() {
             ty::ReVar(vid) => {
                 let scc = self.constraint_sccs.scc(vid);
 
diff --git a/compiler/rustc_borrowck/src/root_cx.rs b/compiler/rustc_borrowck/src/root_cx.rs
new file mode 100644
index 00000000000..13daa5c7221
--- /dev/null
+++ b/compiler/rustc_borrowck/src/root_cx.rs
@@ -0,0 +1,101 @@
+use rustc_abi::FieldIdx;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::LocalDefId;
+use rustc_middle::bug;
+use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::ErrorGuaranteed;
+use smallvec::SmallVec;
+
+use crate::{ClosureRegionRequirements, ConcreteOpaqueTypes, PropagatedBorrowCheckResults};
+
+/// The shared context used by both the root as well as all its nested
+/// items.
+pub(super) struct BorrowCheckRootCtxt<'tcx> {
+    pub tcx: TyCtxt<'tcx>,
+    root_def_id: LocalDefId,
+    concrete_opaque_types: ConcreteOpaqueTypes<'tcx>,
+    nested_bodies: FxHashMap<LocalDefId, PropagatedBorrowCheckResults<'tcx>>,
+    tainted_by_errors: Option<ErrorGuaranteed>,
+}
+
+impl<'tcx> BorrowCheckRootCtxt<'tcx> {
+    pub(super) fn new(tcx: TyCtxt<'tcx>, root_def_id: LocalDefId) -> BorrowCheckRootCtxt<'tcx> {
+        BorrowCheckRootCtxt {
+            tcx,
+            root_def_id,
+            concrete_opaque_types: Default::default(),
+            nested_bodies: Default::default(),
+            tainted_by_errors: None,
+        }
+    }
+
+    /// Collect all defining uses of opaque types inside of this typeck root. This
+    /// expects the hidden type to be mapped to the definition parameters of the opaque
+    /// and errors if we end up with distinct hidden types.
+    pub(super) fn add_concrete_opaque_type(
+        &mut self,
+        def_id: LocalDefId,
+        hidden_ty: OpaqueHiddenType<'tcx>,
+    ) {
+        // Sometimes two opaque types are the same only after we remap the generic parameters
+        // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
+        // `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
+        // only know that once we convert the generic parameters to those of the opaque type.
+        if let Some(prev) = self.concrete_opaque_types.0.get_mut(&def_id) {
+            if prev.ty != hidden_ty.ty {
+                let guar = hidden_ty.ty.error_reported().err().unwrap_or_else(|| {
+                    let (Ok(e) | Err(e)) =
+                        prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit());
+                    e
+                });
+                prev.ty = Ty::new_error(self.tcx, guar);
+            }
+            // Pick a better span if there is one.
+            // FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
+            prev.span = prev.span.substitute_dummy(hidden_ty.span);
+        } else {
+            self.concrete_opaque_types.0.insert(def_id, hidden_ty);
+        }
+    }
+
+    pub(super) fn set_tainted_by_errors(&mut self, guar: ErrorGuaranteed) {
+        self.tainted_by_errors = Some(guar);
+    }
+
+    fn get_or_insert_nested(&mut self, def_id: LocalDefId) -> &PropagatedBorrowCheckResults<'tcx> {
+        debug_assert_eq!(
+            self.tcx.typeck_root_def_id(def_id.to_def_id()),
+            self.root_def_id.to_def_id()
+        );
+        if !self.nested_bodies.contains_key(&def_id) {
+            let result = super::do_mir_borrowck(self, def_id, None).0;
+            if let Some(prev) = self.nested_bodies.insert(def_id, result) {
+                bug!("unexpected previous nested body: {prev:?}");
+            }
+        }
+
+        self.nested_bodies.get(&def_id).unwrap()
+    }
+
+    pub(super) fn closure_requirements(
+        &mut self,
+        nested_body_def_id: LocalDefId,
+    ) -> &Option<ClosureRegionRequirements<'tcx>> {
+        &self.get_or_insert_nested(nested_body_def_id).closure_requirements
+    }
+
+    pub(super) fn used_mut_upvars(
+        &mut self,
+        nested_body_def_id: LocalDefId,
+    ) -> &SmallVec<[FieldIdx; 8]> {
+        &self.get_or_insert_nested(nested_body_def_id).used_mut_upvars
+    }
+
+    pub(super) fn finalize(self) -> Result<&'tcx ConcreteOpaqueTypes<'tcx>, ErrorGuaranteed> {
+        if let Some(guar) = self.tainted_by_errors {
+            Err(guar)
+        } else {
+            Ok(self.tcx.arena.alloc(self.concrete_opaque_types))
+        }
+    }
+}
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 6fbe1db6330..ccb257ae093 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -6,7 +6,6 @@ use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
 use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
 use rustc_infer::traits::query::type_op::DeeplyNormalize;
 use rustc_middle::bug;
-use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
 use rustc_middle::ty::{
     self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions,
 };
@@ -18,6 +17,7 @@ use crate::constraints::OutlivesConstraint;
 use crate::region_infer::TypeTest;
 use crate::type_check::{Locations, MirTypeckRegionConstraints};
 use crate::universal_regions::UniversalRegions;
+use crate::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
 
 pub(crate) struct ConstraintConversion<'a, 'tcx> {
     infcx: &'a InferCtxt<'tcx>,
@@ -205,7 +205,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
     /// are dealt with during trait solving.
     fn replace_placeholders_with_nll<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T {
         if value.has_placeholders() {
-            fold_regions(self.tcx, value, |r, _| match *r {
+            fold_regions(self.tcx, value, |r, _| match r.kind() {
                 ty::RePlaceholder(placeholder) => {
                     self.constraints.placeholder_region(self.infcx, placeholder)
                 }
@@ -227,7 +227,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
     }
 
     fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
-        if let ty::RePlaceholder(placeholder) = *r {
+        if let ty::RePlaceholder(placeholder) = r.kind() {
             self.constraints.placeholder_region(self.infcx, placeholder).as_var()
         } else {
             self.universal_regions.to_region_vid(r)
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index f6144a25938..a17dff5d271 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -45,7 +45,6 @@ use crate::borrow_set::BorrowSet;
 use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet};
 use crate::diagnostics::UniverseInfo;
 use crate::member_constraints::MemberConstraintSet;
-use crate::opaque_types::ConcreteOpaqueTypes;
 use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable};
 use crate::polonius::{PoloniusContext, PoloniusLivenessContext};
 use crate::region_infer::TypeTest;
@@ -53,7 +52,7 @@ use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderI
 use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst};
 use crate::type_check::free_region_relations::{CreateResult, UniversalRegionRelations};
 use crate::universal_regions::{DefiningTy, UniversalRegions};
-use crate::{BorrowckInferCtxt, path_utils};
+use crate::{BorrowCheckRootCtxt, BorrowckInferCtxt, path_utils};
 
 macro_rules! span_mirbug {
     ($context:expr, $elem:expr, $($message:tt)*) => ({
@@ -102,6 +101,7 @@ mod relate_tys;
 /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
 /// - `location_map` -- map between MIR `Location` and `PointIndex`
 pub(crate) fn type_check<'a, 'tcx>(
+    root_cx: &mut BorrowCheckRootCtxt<'tcx>,
     infcx: &BorrowckInferCtxt<'tcx>,
     body: &Body<'tcx>,
     promoted: &IndexSlice<Promoted, Body<'tcx>>,
@@ -112,7 +112,6 @@ pub(crate) fn type_check<'a, 'tcx>(
     flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     location_map: Rc<DenseLocationMap>,
-    concrete_opaque_types: &mut ConcreteOpaqueTypes<'tcx>,
 ) -> MirTypeckResults<'tcx> {
     let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
     let mut constraints = MirTypeckRegionConstraints {
@@ -153,6 +152,7 @@ pub(crate) fn type_check<'a, 'tcx>(
     };
 
     let mut typeck = TypeChecker {
+        root_cx,
         infcx,
         last_span: body.span,
         body,
@@ -167,7 +167,6 @@ pub(crate) fn type_check<'a, 'tcx>(
         polonius_facts,
         borrow_set,
         constraints: &mut constraints,
-        concrete_opaque_types,
         polonius_liveness,
     };
 
@@ -215,6 +214,7 @@ enum FieldAccessError {
 /// way, it accrues region constraints -- these can later be used by
 /// NLL region checking.
 struct TypeChecker<'a, 'tcx> {
+    root_cx: &'a mut BorrowCheckRootCtxt<'tcx>,
     infcx: &'a BorrowckInferCtxt<'tcx>,
     last_span: Span,
     body: &'a Body<'tcx>,
@@ -233,7 +233,6 @@ struct TypeChecker<'a, 'tcx> {
     polonius_facts: &'a mut Option<PoloniusFacts>,
     borrow_set: &'a BorrowSet<'tcx>,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
-    concrete_opaque_types: &'a mut ConcreteOpaqueTypes<'tcx>,
     /// When using `-Zpolonius=next`, the liveness helper data used to create polonius constraints.
     polonius_liveness: Option<PoloniusLivenessContext>,
 }
@@ -2503,11 +2502,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         args: GenericArgsRef<'tcx>,
         locations: Locations,
     ) -> ty::InstantiatedPredicates<'tcx> {
-        let closure_borrowck_results = tcx.mir_borrowck(def_id);
-        self.concrete_opaque_types
-            .extend_from_nested_body(tcx, &closure_borrowck_results.concrete_opaque_types);
-
-        if let Some(closure_requirements) = &closure_borrowck_results.closure_requirements {
+        if let Some(closure_requirements) = &self.root_cx.closure_requirements(def_id) {
             constraint_conversion::ConstraintConversion::new(
                 self.infcx,
                 self.universal_regions,
diff --git a/compiler/rustc_borrowck/src/type_check/opaque_types.rs b/compiler/rustc_borrowck/src/type_check/opaque_types.rs
index 8bab979a724..d41cbf757d7 100644
--- a/compiler/rustc_borrowck/src/type_check/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/type_check/opaque_types.rs
@@ -271,7 +271,7 @@ where
     }
 
     fn visit_region(&mut self, r: ty::Region<'tcx>) {
-        match *r {
+        match r.kind() {
             // ignore bound regions, keep visiting
             ty::ReBound(_, _) => {}
             _ => (self.op)(r),
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 8f6b405fcef..5c57ab99a85 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -909,19 +909,19 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
     /// if it is a placeholder. Handling placeholders requires access to the
     /// `MirTypeckRegionConstraints`.
     fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
-        if let ty::ReVar(..) = *r {
-            r.as_var()
-        } else if let ty::ReError(guar) = *r {
-            self.tainted_by_errors.set(Some(guar));
-            // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the
-            // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if
-            // errors are being emitted and 2) it leaves the happy path unaffected.
-            self.fr_static
-        } else {
-            *self
+        match r.kind() {
+            ty::ReVar(..) => r.as_var(),
+            ty::ReError(guar) => {
+                self.tainted_by_errors.set(Some(guar));
+                // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the
+                // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if
+                // errors are being emitted and 2) it leaves the happy path unaffected.
+                self.fr_static
+            }
+            _ => *self
                 .indices
                 .get(&r)
-                .unwrap_or_else(|| bug!("cannot convert `{:?}` to a region vid", r))
+                .unwrap_or_else(|| bug!("cannot convert `{:?}` to a region vid", r)),
         }
     }
 
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index 7f99f75b2b9..351413dea49 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -17,7 +17,7 @@ mod llvm_enzyme {
     use rustc_ast::visit::AssocCtxt::*;
     use rustc_ast::{
         self as ast, AssocItemKind, BindingMode, ExprKind, FnRetTy, FnSig, Generics, ItemKind,
-        MetaItemInner, PatKind, QSelf, TyKind,
+        MetaItemInner, PatKind, QSelf, TyKind, Visibility,
     };
     use rustc_expand::base::{Annotatable, ExtCtxt};
     use rustc_span::{Ident, Span, Symbol, kw, sym};
@@ -72,6 +72,16 @@ mod llvm_enzyme {
         }
     }
 
+    // Get information about the function the macro is applied to
+    fn extract_item_info(iitem: &P<ast::Item>) -> Option<(Visibility, FnSig, Ident)> {
+        match &iitem.kind {
+            ItemKind::Fn(box ast::Fn { sig, ident, .. }) => {
+                Some((iitem.vis.clone(), sig.clone(), ident.clone()))
+            }
+            _ => None,
+        }
+    }
+
     pub(crate) fn from_ast(
         ecx: &mut ExtCtxt<'_>,
         meta_item: &ThinVec<MetaItemInner>,
@@ -199,32 +209,26 @@ mod llvm_enzyme {
             return vec![item];
         }
         let dcx = ecx.sess.dcx();
-        // first get the annotable item:
-        let (primal, sig, is_impl): (Ident, FnSig, bool) = match &item {
-            Annotatable::Item(iitem) => {
-                let (ident, sig) = match &iitem.kind {
-                    ItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig),
-                    _ => {
-                        dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
-                        return vec![item];
-                    }
-                };
-                (*ident, sig.clone(), false)
-            }
+
+        // first get information about the annotable item:
+        let Some((vis, sig, primal)) = (match &item {
+            Annotatable::Item(iitem) => extract_item_info(iitem),
+            Annotatable::Stmt(stmt) => match &stmt.kind {
+                ast::StmtKind::Item(iitem) => extract_item_info(iitem),
+                _ => None,
+            },
             Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => {
-                let (ident, sig) = match &assoc_item.kind {
-                    ast::AssocItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig),
-                    _ => {
-                        dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
-                        return vec![item];
+                match &assoc_item.kind {
+                    ast::AssocItemKind::Fn(box ast::Fn { sig, ident, .. }) => {
+                        Some((assoc_item.vis.clone(), sig.clone(), ident.clone()))
                     }
-                };
-                (*ident, sig.clone(), true)
-            }
-            _ => {
-                dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
-                return vec![item];
+                    _ => None,
+                }
             }
+            _ => None,
+        }) else {
+            dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
+            return vec![item];
         };
 
         let meta_item_vec: ThinVec<MetaItemInner> = match meta_item.kind {
@@ -238,15 +242,6 @@ mod llvm_enzyme {
         let has_ret = has_ret(&sig.decl.output);
         let sig_span = ecx.with_call_site_ctxt(sig.span);
 
-        let vis = match &item {
-            Annotatable::Item(iitem) => iitem.vis.clone(),
-            Annotatable::AssocItem(assoc_item, _) => assoc_item.vis.clone(),
-            _ => {
-                dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
-                return vec![item];
-            }
-        };
-
         // create TokenStream from vec elemtents:
         // meta_item doesn't have a .tokens field
         let mut ts: Vec<TokenTree> = vec![];
@@ -379,6 +374,22 @@ mod llvm_enzyme {
                 }
                 Annotatable::AssocItem(assoc_item.clone(), i)
             }
+            Annotatable::Stmt(ref mut stmt) => {
+                match stmt.kind {
+                    ast::StmtKind::Item(ref mut iitem) => {
+                        if !iitem.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) {
+                            iitem.attrs.push(attr);
+                        }
+                        if !iitem.attrs.iter().any(|a| same_attribute(&a.kind, &inline_never.kind))
+                        {
+                            iitem.attrs.push(inline_never.clone());
+                        }
+                    }
+                    _ => unreachable!("stmt kind checked previously"),
+                };
+
+                Annotatable::Stmt(stmt.clone())
+            }
             _ => {
                 unreachable!("annotatable kind checked previously")
             }
@@ -389,22 +400,40 @@ mod llvm_enzyme {
             delim: rustc_ast::token::Delimiter::Parenthesis,
             tokens: ts,
         });
+
         let d_attr = outer_normal_attr(&rustc_ad_attr, new_id, span);
-        let d_annotatable = if is_impl {
-            let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(asdf);
-            let d_fn = P(ast::AssocItem {
-                attrs: thin_vec![d_attr, inline_never],
-                id: ast::DUMMY_NODE_ID,
-                span,
-                vis,
-                kind: assoc_item,
-                tokens: None,
-            });
-            Annotatable::AssocItem(d_fn, Impl { of_trait: false })
-        } else {
-            let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
-            d_fn.vis = vis;
-            Annotatable::Item(d_fn)
+        let d_annotatable = match &item {
+            Annotatable::AssocItem(_, _) => {
+                let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(asdf);
+                let d_fn = P(ast::AssocItem {
+                    attrs: thin_vec![d_attr, inline_never],
+                    id: ast::DUMMY_NODE_ID,
+                    span,
+                    vis,
+                    kind: assoc_item,
+                    tokens: None,
+                });
+                Annotatable::AssocItem(d_fn, Impl { of_trait: false })
+            }
+            Annotatable::Item(_) => {
+                let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
+                d_fn.vis = vis;
+
+                Annotatable::Item(d_fn)
+            }
+            Annotatable::Stmt(_) => {
+                let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
+                d_fn.vis = vis;
+
+                Annotatable::Stmt(P(ast::Stmt {
+                    id: ast::DUMMY_NODE_ID,
+                    kind: ast::StmtKind::Item(d_fn),
+                    span,
+                }))
+            }
+            _ => {
+                unreachable!("item kind checked previously")
+            }
         };
 
         return vec![orig_annotatable, d_annotatable];
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 75f3a3c1972..d3f47ad7263 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -1,5 +1,4 @@
-//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`,
-//! functions marked with the `#[rustc_intrinsic]` attribute
+//! Codegen of intrinsics. This includes functions marked with the `#[rustc_intrinsic]` attribute
 //! and LLVM intrinsics that have symbol names starting with `llvm.`.
 
 macro_rules! intrinsic_args {
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index bf6138142b6..76d431a4975 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -439,12 +439,9 @@ fn report_inline_asm(
     let span = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
         SpanData::default()
     } else {
-        let lo = BytePos::from_u32(cookie as u32);
-        let hi = BytePos::from_u32((cookie >> 32) as u32);
         SpanData {
-            lo,
-            // LLVM version < 19 silently truncates the cookie to 32 bits in some situations.
-            hi: if hi.to_u32() != 0 { hi } else { lo },
+            lo: BytePos::from_u32(cookie as u32),
+            hi: BytePos::from_u32((cookie >> 32) as u32),
             ctxt: SyntaxContext::root(),
             parent: None,
         }
diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
index 7d264ba4d00..5e7ef27143b 100644
--- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
@@ -201,7 +201,23 @@ fn compute_enzyme_fn_ty<'ll>(
         }
 
         if attrs.width == 1 {
-            todo!("Handle sret for scalar ad");
+            // Enzyme returns a struct of style:
+            // `{ original_ret(if requested), float, float, ... }`
+            let mut struct_elements = vec![];
+            if attrs.has_primal_ret() {
+                struct_elements.push(inner_ret_ty);
+            }
+            // Next, we push the list of active floats, since they will be lowered to `enzyme_out`,
+            // and therefore part of the return struct.
+            let param_tys = cx.func_params_types(fn_ty);
+            for (act, param_ty) in attrs.input_activity.iter().zip(param_tys) {
+                if matches!(act, DiffActivity::Active) {
+                    // Now find the float type at position i based on the fn_ty,
+                    // to know what (f16/f32/f64/...) to add to the struct.
+                    struct_elements.push(param_ty);
+                }
+            }
+            ret_ty = cx.type_struct(&struct_elements, false);
         } else {
             // First we check if we also have to deal with the primal return.
             match attrs.mode {
@@ -388,7 +404,11 @@ fn generate_enzyme_call<'ll>(
                 // now store the result of the enzyme call into the sret pointer.
                 let sret_ptr = outer_args[0];
                 let call_ty = cx.val_ty(call);
-                assert_eq!(cx.type_kind(call_ty), TypeKind::Array);
+                if attrs.width == 1 {
+                    assert_eq!(cx.type_kind(call_ty), TypeKind::Struct);
+                } else {
+                    assert_eq!(cx.type_kind(call_ty), TypeKind::Array);
+                }
                 llvm::LLVMBuildStore(&builder.llbuilder, call, sret_ptr);
             }
             builder.ret_void();
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 9a2473d6cf2..55b1e728b70 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -5,15 +5,11 @@ use rustc_abi::Align;
 use rustc_codegen_ssa::traits::{
     BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
 };
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_index::IndexVec;
-use rustc_middle::mir;
-use rustc_middle::mir::mono::MonoItemPartitions;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::RemapFileNameExt;
 use rustc_session::config::RemapPathScopeComponents;
-use rustc_span::def_id::DefIdSet;
 use rustc_span::{SourceFile, StableSourceFileId};
 use tracing::debug;
 
@@ -24,6 +20,7 @@ use crate::llvm;
 
 mod covfun;
 mod spans;
+mod unused;
 
 /// Generates and exports the coverage map, which is embedded in special
 /// linker sections in the final binary.
@@ -56,13 +53,6 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
         None => return,
     };
 
-    // The order of entries in this global file table needs to be deterministic,
-    // and ideally should also be independent of the details of stable-hashing,
-    // because coverage tests snapshots (`.cov-map`) can observe the order and
-    // would need to be re-blessed if it changes. As long as those requirements
-    // are satisfied, the order can be arbitrary.
-    let mut global_file_table = GlobalFileTable::new();
-
     let mut covfun_records = instances_used
         .iter()
         .copied()
@@ -70,18 +60,13 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
         // order that doesn't depend on the stable-hash-based order in which
         // instances were visited during codegen.
         .sorted_by_cached_key(|&instance| tcx.symbol_name(instance).name)
-        .filter_map(|instance| prepare_covfun_record(tcx, &mut global_file_table, instance, true))
+        .filter_map(|instance| prepare_covfun_record(tcx, instance, true))
         .collect::<Vec<_>>();
 
     // In a single designated CGU, also prepare covfun records for functions
     // in this crate that were instrumented for coverage, but are unused.
     if cx.codegen_unit.is_code_coverage_dead_code_cgu() {
-        let mut unused_instances = gather_unused_function_instances(cx);
-        // Sort the unused instances by symbol name, for the same reason as the used ones.
-        unused_instances.sort_by_cached_key(|&instance| tcx.symbol_name(instance).name);
-        covfun_records.extend(unused_instances.into_iter().filter_map(|instance| {
-            prepare_covfun_record(tcx, &mut global_file_table, instance, false)
-        }));
+        unused::prepare_covfun_records_for_unused_functions(cx, &mut covfun_records);
     }
 
     // If there are no covfun records for this CGU, don't generate a covmap record.
@@ -93,91 +78,88 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
         return;
     }
 
-    // Encode all filenames referenced by coverage mappings in this CGU.
-    let filenames_buffer = global_file_table.make_filenames_buffer(tcx);
-    // The `llvm-cov` tool uses this hash to associate each covfun record with
-    // its corresponding filenames table, since the final binary will typically
-    // contain multiple covmap records from different compilation units.
-    let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer);
-
-    let mut unused_function_names = vec![];
+    // Prepare the global file table for this CGU, containing all paths needed
+    // by one or more covfun records.
+    let global_file_table =
+        GlobalFileTable::build(tcx, covfun_records.iter().flat_map(|c| c.all_source_files()));
 
     for covfun in &covfun_records {
-        unused_function_names.extend(covfun.mangled_function_name_if_unused());
-
-        covfun::generate_covfun_record(cx, filenames_hash, covfun)
-    }
-
-    // For unused functions, we need to take their mangled names and store them
-    // in a specially-named global array. LLVM's `InstrProfiling` pass will
-    // detect this global and include those names in its `__llvm_prf_names`
-    // section. (See `llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp`.)
-    if !unused_function_names.is_empty() {
-        assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu());
-
-        let name_globals = unused_function_names
-            .into_iter()
-            .map(|mangled_function_name| cx.const_str(mangled_function_name).0)
-            .collect::<Vec<_>>();
-        let initializer = cx.const_array(cx.type_ptr(), &name_globals);
-
-        let array = llvm::add_global(cx.llmod, cx.val_ty(initializer), c"__llvm_coverage_names");
-        llvm::set_global_constant(array, true);
-        llvm::set_linkage(array, llvm::Linkage::InternalLinkage);
-        llvm::set_initializer(array, initializer);
+        covfun::generate_covfun_record(cx, &global_file_table, covfun)
     }
 
     // Generate the coverage map header, which contains the filenames used by
     // this CGU's coverage mappings, and store it in a well-known global.
     // (This is skipped if we returned early due to having no covfun records.)
-    generate_covmap_record(cx, covmap_version, &filenames_buffer);
+    generate_covmap_record(cx, covmap_version, &global_file_table.filenames_buffer);
 }
 
-/// Maps "global" (per-CGU) file ID numbers to their underlying source files.
+/// Maps "global" (per-CGU) file ID numbers to their underlying source file paths.
+#[derive(Debug)]
 struct GlobalFileTable {
     /// This "raw" table doesn't include the working dir, so a file's
     /// global ID is its index in this set **plus one**.
-    raw_file_table: FxIndexMap<StableSourceFileId, Arc<SourceFile>>,
+    raw_file_table: FxIndexMap<StableSourceFileId, String>,
+
+    /// The file table in encoded form (possibly compressed), which can be
+    /// included directly in this CGU's `__llvm_covmap` record.
+    filenames_buffer: Vec<u8>,
+
+    /// Truncated hash of the bytes in `filenames_buffer`.
+    ///
+    /// The `llvm-cov` tool uses this hash to associate each covfun record with
+    /// its corresponding filenames table, since the final binary will typically
+    /// contain multiple covmap records from different compilation units.
+    filenames_hash: u64,
 }
 
 impl GlobalFileTable {
-    fn new() -> Self {
-        Self { raw_file_table: FxIndexMap::default() }
-    }
+    /// Builds a "global file table" for this CGU, mapping numeric IDs to
+    /// path strings.
+    fn build<'a>(tcx: TyCtxt<'_>, all_files: impl Iterator<Item = &'a SourceFile>) -> Self {
+        let mut raw_file_table = FxIndexMap::default();
+
+        for file in all_files {
+            raw_file_table.entry(file.stable_id).or_insert_with(|| {
+                file.name
+                    .for_scope(tcx.sess, RemapPathScopeComponents::MACRO)
+                    .to_string_lossy()
+                    .into_owned()
+            });
+        }
 
-    fn global_file_id_for_file(&mut self, file: &Arc<SourceFile>) -> GlobalFileId {
-        // Ensure the given file has a table entry, and get its index.
-        let entry = self.raw_file_table.entry(file.stable_id);
-        let raw_id = entry.index();
-        entry.or_insert_with(|| Arc::clone(file));
+        // FIXME(Zalathar): Consider sorting the file table here, but maybe
+        // only after adding filename support to coverage-dump, so that the
+        // table order isn't directly visible in `.coverage-map` snapshots.
 
-        // The raw file table doesn't include an entry for the working dir
-        // (which has ID 0), so add 1 to get the correct ID.
-        GlobalFileId::from_usize(raw_id + 1)
-    }
+        let mut table = Vec::with_capacity(raw_file_table.len() + 1);
 
-    fn make_filenames_buffer(&self, tcx: TyCtxt<'_>) -> Vec<u8> {
-        let mut table = Vec::with_capacity(self.raw_file_table.len() + 1);
-
-        // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5)
-        // requires setting the first filename to the compilation directory.
-        // Since rustc generates coverage maps with relative paths, the
-        // compilation directory can be combined with the relative paths
-        // to get absolute paths, if needed.
-        table.push(
-            tcx.sess
-                .opts
-                .working_dir
-                .for_scope(tcx.sess, RemapPathScopeComponents::MACRO)
-                .to_string_lossy(),
-        );
+        // Since version 6 of the LLVM coverage mapping format, the first entry
+        // in the global file table is treated as a base directory, used to
+        // resolve any other entries that are stored as relative paths.
+        let base_dir = tcx
+            .sess
+            .opts
+            .working_dir
+            .for_scope(tcx.sess, RemapPathScopeComponents::MACRO)
+            .to_string_lossy();
+        table.push(base_dir.as_ref());
 
         // Add the regular entries after the base directory.
-        table.extend(self.raw_file_table.values().map(|file| {
-            file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy()
-        }));
+        table.extend(raw_file_table.values().map(|name| name.as_str()));
 
-        llvm_cov::write_filenames_to_buffer(&table)
+        // Encode the file table into a buffer, and get the hash of its encoded
+        // bytes, so that we can embed that hash in `__llvm_covfun` records.
+        let filenames_buffer = llvm_cov::write_filenames_to_buffer(&table);
+        let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer);
+
+        Self { raw_file_table, filenames_buffer, filenames_hash }
+    }
+
+    fn get_existing_id(&self, file: &SourceFile) -> Option<GlobalFileId> {
+        let raw_id = self.raw_file_table.get_index_of(&file.stable_id)?;
+        // The raw file table doesn't include an entry for the base dir
+        // (which has ID 0), so add 1 to get the correct ID.
+        Some(GlobalFileId::from_usize(raw_id + 1))
     }
 }
 
@@ -193,26 +175,31 @@ rustc_index::newtype_index! {
     struct LocalFileId {}
 }
 
-/// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU)
-/// file IDs.
+/// Holds a mapping from "local" (per-function) file IDs to their corresponding
+/// source files.
 #[derive(Debug, Default)]
 struct VirtualFileMapping {
-    local_to_global: IndexVec<LocalFileId, GlobalFileId>,
-    global_to_local: FxIndexMap<GlobalFileId, LocalFileId>,
+    local_file_table: IndexVec<LocalFileId, Arc<SourceFile>>,
 }
 
 impl VirtualFileMapping {
-    fn local_id_for_global(&mut self, global_file_id: GlobalFileId) -> LocalFileId {
-        *self
-            .global_to_local
-            .entry(global_file_id)
-            .or_insert_with(|| self.local_to_global.push(global_file_id))
+    fn push_file(&mut self, source_file: &Arc<SourceFile>) -> LocalFileId {
+        self.local_file_table.push(Arc::clone(source_file))
     }
 
-    fn to_vec(&self) -> Vec<u32> {
-        // This clone could be avoided by transmuting `&[GlobalFileId]` to `&[u32]`,
-        // but it isn't hot or expensive enough to justify the extra unsafety.
-        self.local_to_global.iter().map(|&global| GlobalFileId::as_u32(global)).collect()
+    /// Resolves all of the filenames in this local file mapping to a list of
+    /// global file IDs in its CGU, for inclusion in this function's
+    /// `__llvm_covfun` record.
+    ///
+    /// The global file IDs are returned as `u32` to make FFI easier.
+    fn resolve_all(&self, global_file_table: &GlobalFileTable) -> Option<Vec<u32>> {
+        self.local_file_table
+            .iter()
+            .map(|file| try {
+                let id = global_file_table.get_existing_id(file)?;
+                GlobalFileId::as_u32(id)
+            })
+            .collect::<Option<Vec<_>>>()
     }
 }
 
@@ -249,121 +236,3 @@ fn generate_covmap_record<'ll>(cx: &CodegenCx<'ll, '_>, version: u32, filenames_
 
     cx.add_used_global(covmap_global);
 }
-
-/// Each CGU will normally only emit coverage metadata for the functions that it actually generates.
-/// But since we don't want unused functions to disappear from coverage reports, we also scan for
-/// functions that were instrumented but are not participating in codegen.
-///
-/// These unused functions don't need to be codegenned, but we do need to add them to the function
-/// coverage map (in a single designated CGU) so that we still emit coverage mappings for them.
-/// We also end up adding their symbol names to a special global array that LLVM will include in
-/// its embedded coverage data.
-fn gather_unused_function_instances<'tcx>(cx: &CodegenCx<'_, 'tcx>) -> Vec<ty::Instance<'tcx>> {
-    assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu());
-
-    let tcx = cx.tcx;
-    let usage = prepare_usage_sets(tcx);
-
-    let is_unused_fn = |def_id: LocalDefId| -> bool {
-        // Usage sets expect `DefId`, so convert from `LocalDefId`.
-        let d: DefId = LocalDefId::to_def_id(def_id);
-        // To be potentially eligible for "unused function" mappings, a definition must:
-        // - Be eligible for coverage instrumentation
-        // - Not participate directly in codegen (or have lost all its coverage statements)
-        // - Not have any coverage statements inlined into codegenned functions
-        tcx.is_eligible_for_coverage(def_id)
-            && (!usage.all_mono_items.contains(&d) || usage.missing_own_coverage.contains(&d))
-            && !usage.used_via_inlining.contains(&d)
-    };
-
-    // FIXME(#79651): Consider trying to filter out dummy instantiations of
-    // unused generic functions from library crates, because they can produce
-    // "unused instantiation" in coverage reports even when they are actually
-    // used by some downstream crate in the same binary.
-
-    tcx.mir_keys(())
-        .iter()
-        .copied()
-        .filter(|&def_id| is_unused_fn(def_id))
-        .map(|def_id| make_dummy_instance(tcx, def_id))
-        .collect::<Vec<_>>()
-}
-
-struct UsageSets<'tcx> {
-    all_mono_items: &'tcx DefIdSet,
-    used_via_inlining: FxHashSet<DefId>,
-    missing_own_coverage: FxHashSet<DefId>,
-}
-
-/// Prepare sets of definitions that are relevant to deciding whether something
-/// is an "unused function" for coverage purposes.
-fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> {
-    let MonoItemPartitions { all_mono_items, codegen_units, .. } =
-        tcx.collect_and_partition_mono_items(());
-
-    // Obtain a MIR body for each function participating in codegen, via an
-    // arbitrary instance.
-    let mut def_ids_seen = FxHashSet::default();
-    let def_and_mir_for_all_mono_fns = codegen_units
-        .iter()
-        .flat_map(|cgu| cgu.items().keys())
-        .filter_map(|item| match item {
-            mir::mono::MonoItem::Fn(instance) => Some(instance),
-            mir::mono::MonoItem::Static(_) | mir::mono::MonoItem::GlobalAsm(_) => None,
-        })
-        // We only need one arbitrary instance per definition.
-        .filter(move |instance| def_ids_seen.insert(instance.def_id()))
-        .map(|instance| {
-            // We don't care about the instance, just its underlying MIR.
-            let body = tcx.instance_mir(instance.def);
-            (instance.def_id(), body)
-        });
-
-    // Functions whose coverage statements were found inlined into other functions.
-    let mut used_via_inlining = FxHashSet::default();
-    // Functions that were instrumented, but had all of their coverage statements
-    // removed by later MIR transforms (e.g. UnreachablePropagation).
-    let mut missing_own_coverage = FxHashSet::default();
-
-    for (def_id, body) in def_and_mir_for_all_mono_fns {
-        let mut saw_own_coverage = false;
-
-        // Inspect every coverage statement in the function's MIR.
-        for stmt in body
-            .basic_blocks
-            .iter()
-            .flat_map(|block| &block.statements)
-            .filter(|stmt| matches!(stmt.kind, mir::StatementKind::Coverage(_)))
-        {
-            if let Some(inlined) = stmt.source_info.scope.inlined_instance(&body.source_scopes) {
-                // This coverage statement was inlined from another function.
-                used_via_inlining.insert(inlined.def_id());
-            } else {
-                // Non-inlined coverage statements belong to the enclosing function.
-                saw_own_coverage = true;
-            }
-        }
-
-        if !saw_own_coverage && body.function_coverage_info.is_some() {
-            missing_own_coverage.insert(def_id);
-        }
-    }
-
-    UsageSets { all_mono_items, used_via_inlining, missing_own_coverage }
-}
-
-fn make_dummy_instance<'tcx>(tcx: TyCtxt<'tcx>, local_def_id: LocalDefId) -> ty::Instance<'tcx> {
-    let def_id = local_def_id.to_def_id();
-
-    // Make a dummy instance that fills in all generics with placeholders.
-    ty::Instance::new(
-        def_id,
-        ty::GenericArgs::for_item(tcx, def_id, |param, _| {
-            if let ty::GenericParamDefKind::Lifetime = param.kind {
-                tcx.lifetimes.re_erased.into()
-            } else {
-                tcx.mk_param_from_def(param)
-            }
-        }),
-    )
-}
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
index 048e1988c32..7bdbc685952 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
@@ -5,6 +5,7 @@
 //! [^win]: On Windows the section name is `.lcovfun`.
 
 use std::ffi::CString;
+use std::sync::Arc;
 
 use rustc_abi::Align;
 use rustc_codegen_ssa::traits::{
@@ -15,7 +16,7 @@ use rustc_middle::mir::coverage::{
     MappingKind, Op,
 };
 use rustc_middle::ty::{Instance, TyCtxt};
-use rustc_span::Span;
+use rustc_span::{SourceFile, Span};
 use rustc_target::spec::HasTargetSpec;
 use tracing::debug;
 
@@ -38,16 +39,15 @@ pub(crate) struct CovfunRecord<'tcx> {
 }
 
 impl<'tcx> CovfunRecord<'tcx> {
-    /// FIXME(Zalathar): Make this the responsibility of the code that determines
-    /// which functions are unused.
-    pub(crate) fn mangled_function_name_if_unused(&self) -> Option<&'tcx str> {
-        (!self.is_used).then_some(self.mangled_function_name)
+    /// Iterator that yields all source files referred to by this function's
+    /// coverage mappings. Used to build the global file table for the CGU.
+    pub(crate) fn all_source_files(&self) -> impl Iterator<Item = &SourceFile> {
+        self.virtual_file_mapping.local_file_table.iter().map(Arc::as_ref)
     }
 }
 
 pub(crate) fn prepare_covfun_record<'tcx>(
     tcx: TyCtxt<'tcx>,
-    global_file_table: &mut GlobalFileTable,
     instance: Instance<'tcx>,
     is_used: bool,
 ) -> Option<CovfunRecord<'tcx>> {
@@ -65,7 +65,7 @@ pub(crate) fn prepare_covfun_record<'tcx>(
         regions: ffi::Regions::default(),
     };
 
-    fill_region_tables(tcx, global_file_table, fn_cov_info, ids_info, &mut covfun);
+    fill_region_tables(tcx, fn_cov_info, ids_info, &mut covfun);
 
     if covfun.regions.has_no_regions() {
         debug!(?covfun, "function has no mappings to embed; skipping");
@@ -100,7 +100,6 @@ fn prepare_expressions(ids_info: &CoverageIdsInfo) -> Vec<ffi::CounterExpression
 /// Populates the mapping region tables in the current function's covfun record.
 fn fill_region_tables<'tcx>(
     tcx: TyCtxt<'tcx>,
-    global_file_table: &mut GlobalFileTable,
     fn_cov_info: &'tcx FunctionCoverageInfo,
     ids_info: &'tcx CoverageIdsInfo,
     covfun: &mut CovfunRecord<'tcx>,
@@ -114,11 +113,7 @@ fn fill_region_tables<'tcx>(
     };
     let source_file = source_map.lookup_source_file(first_span.lo());
 
-    // Look up the global file ID for that file.
-    let global_file_id = global_file_table.global_file_id_for_file(&source_file);
-
-    // Associate that global file ID with a local file ID for this function.
-    let local_file_id = covfun.virtual_file_mapping.local_id_for_global(global_file_id);
+    let local_file_id = covfun.virtual_file_mapping.push_file(&source_file);
 
     // In rare cases, _all_ of a function's spans are discarded, and coverage
     // codegen needs to handle that gracefully to avoid #133606.
@@ -187,7 +182,7 @@ fn fill_region_tables<'tcx>(
 /// as a global variable in the `__llvm_covfun` section.
 pub(crate) fn generate_covfun_record<'tcx>(
     cx: &CodegenCx<'_, 'tcx>,
-    filenames_hash: u64,
+    global_file_table: &GlobalFileTable,
     covfun: &CovfunRecord<'tcx>,
 ) {
     let &CovfunRecord {
@@ -199,12 +194,19 @@ pub(crate) fn generate_covfun_record<'tcx>(
         ref regions,
     } = covfun;
 
+    let Some(local_file_table) = virtual_file_mapping.resolve_all(global_file_table) else {
+        debug_assert!(
+            false,
+            "all local files should be present in the global file table: \
+                global_file_table = {global_file_table:?}, \
+                virtual_file_mapping = {virtual_file_mapping:?}"
+        );
+        return;
+    };
+
     // Encode the function's coverage mappings into a buffer.
-    let coverage_mapping_buffer = llvm_cov::write_function_mappings_to_buffer(
-        &virtual_file_mapping.to_vec(),
-        expressions,
-        regions,
-    );
+    let coverage_mapping_buffer =
+        llvm_cov::write_function_mappings_to_buffer(&local_file_table, expressions, regions);
 
     // A covfun record consists of four target-endian integers, followed by the
     // encoded mapping data in bytes. Note that the length field is 32 bits.
@@ -217,7 +219,7 @@ pub(crate) fn generate_covfun_record<'tcx>(
             cx.const_u64(func_name_hash),
             cx.const_u32(coverage_mapping_buffer.len() as u32),
             cx.const_u64(source_hash),
-            cx.const_u64(filenames_hash),
+            cx.const_u64(global_file_table.filenames_hash),
             cx.const_bytes(&coverage_mapping_buffer),
         ],
         // This struct needs to be packed, so that the 32-bit length field
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs
new file mode 100644
index 00000000000..68f60f169b5
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs
@@ -0,0 +1,170 @@
+use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_middle::mir;
+use rustc_middle::mir::mono::MonoItemPartitions;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::def_id::DefIdSet;
+
+use crate::common::CodegenCx;
+use crate::coverageinfo::mapgen::covfun::{CovfunRecord, prepare_covfun_record};
+use crate::llvm;
+
+/// Each CGU will normally only emit coverage metadata for the functions that it actually generates.
+/// But since we don't want unused functions to disappear from coverage reports, we also scan for
+/// functions that were instrumented but are not participating in codegen.
+///
+/// These unused functions don't need to be codegenned, but we do need to add them to the function
+/// coverage map (in a single designated CGU) so that we still emit coverage mappings for them.
+/// We also end up adding their symbol names to a special global array that LLVM will include in
+/// its embedded coverage data.
+pub(crate) fn prepare_covfun_records_for_unused_functions<'tcx>(
+    cx: &CodegenCx<'_, 'tcx>,
+    covfun_records: &mut Vec<CovfunRecord<'tcx>>,
+) {
+    assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu());
+
+    let mut unused_instances = gather_unused_function_instances(cx);
+    // Sort the unused instances by symbol name, so that their order isn't hash-sensitive.
+    unused_instances.sort_by_key(|instance| instance.symbol_name);
+
+    // Try to create a covfun record for each unused function.
+    let mut name_globals = Vec::with_capacity(unused_instances.len());
+    covfun_records.extend(unused_instances.into_iter().filter_map(|unused| try {
+        let record = prepare_covfun_record(cx.tcx, unused.instance, false)?;
+        // If successful, also store its symbol name in a global constant.
+        name_globals.push(cx.const_str(unused.symbol_name.name).0);
+        record
+    }));
+
+    // Store the names of unused functions in a specially-named global array.
+    // LLVM's `InstrProfilling` pass will detect this array, and include the
+    // referenced names in its `__llvm_prf_names` section.
+    // (See `llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp`.)
+    if !name_globals.is_empty() {
+        let initializer = cx.const_array(cx.type_ptr(), &name_globals);
+
+        let array = llvm::add_global(cx.llmod, cx.val_ty(initializer), c"__llvm_coverage_names");
+        llvm::set_global_constant(array, true);
+        llvm::set_linkage(array, llvm::Linkage::InternalLinkage);
+        llvm::set_initializer(array, initializer);
+    }
+}
+
+/// Holds a dummy function instance along with its symbol name, to avoid having
+/// to repeatedly query for the name.
+struct UnusedInstance<'tcx> {
+    instance: ty::Instance<'tcx>,
+    symbol_name: ty::SymbolName<'tcx>,
+}
+
+fn gather_unused_function_instances<'tcx>(cx: &CodegenCx<'_, 'tcx>) -> Vec<UnusedInstance<'tcx>> {
+    assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu());
+
+    let tcx = cx.tcx;
+    let usage = prepare_usage_sets(tcx);
+
+    let is_unused_fn = |def_id: LocalDefId| -> bool {
+        // Usage sets expect `DefId`, so convert from `LocalDefId`.
+        let d: DefId = LocalDefId::to_def_id(def_id);
+        // To be potentially eligible for "unused function" mappings, a definition must:
+        // - Be eligible for coverage instrumentation
+        // - Not participate directly in codegen (or have lost all its coverage statements)
+        // - Not have any coverage statements inlined into codegenned functions
+        tcx.is_eligible_for_coverage(def_id)
+            && (!usage.all_mono_items.contains(&d) || usage.missing_own_coverage.contains(&d))
+            && !usage.used_via_inlining.contains(&d)
+    };
+
+    // FIXME(#79651): Consider trying to filter out dummy instantiations of
+    // unused generic functions from library crates, because they can produce
+    // "unused instantiation" in coverage reports even when they are actually
+    // used by some downstream crate in the same binary.
+
+    tcx.mir_keys(())
+        .iter()
+        .copied()
+        .filter(|&def_id| is_unused_fn(def_id))
+        .map(|def_id| make_dummy_instance(tcx, def_id))
+        .map(|instance| UnusedInstance { instance, symbol_name: tcx.symbol_name(instance) })
+        .collect::<Vec<_>>()
+}
+
+struct UsageSets<'tcx> {
+    all_mono_items: &'tcx DefIdSet,
+    used_via_inlining: FxHashSet<DefId>,
+    missing_own_coverage: FxHashSet<DefId>,
+}
+
+/// Prepare sets of definitions that are relevant to deciding whether something
+/// is an "unused function" for coverage purposes.
+fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> {
+    let MonoItemPartitions { all_mono_items, codegen_units, .. } =
+        tcx.collect_and_partition_mono_items(());
+
+    // Obtain a MIR body for each function participating in codegen, via an
+    // arbitrary instance.
+    let mut def_ids_seen = FxHashSet::default();
+    let def_and_mir_for_all_mono_fns = codegen_units
+        .iter()
+        .flat_map(|cgu| cgu.items().keys())
+        .filter_map(|item| match item {
+            mir::mono::MonoItem::Fn(instance) => Some(instance),
+            mir::mono::MonoItem::Static(_) | mir::mono::MonoItem::GlobalAsm(_) => None,
+        })
+        // We only need one arbitrary instance per definition.
+        .filter(move |instance| def_ids_seen.insert(instance.def_id()))
+        .map(|instance| {
+            // We don't care about the instance, just its underlying MIR.
+            let body = tcx.instance_mir(instance.def);
+            (instance.def_id(), body)
+        });
+
+    // Functions whose coverage statements were found inlined into other functions.
+    let mut used_via_inlining = FxHashSet::default();
+    // Functions that were instrumented, but had all of their coverage statements
+    // removed by later MIR transforms (e.g. UnreachablePropagation).
+    let mut missing_own_coverage = FxHashSet::default();
+
+    for (def_id, body) in def_and_mir_for_all_mono_fns {
+        let mut saw_own_coverage = false;
+
+        // Inspect every coverage statement in the function's MIR.
+        for stmt in body
+            .basic_blocks
+            .iter()
+            .flat_map(|block| &block.statements)
+            .filter(|stmt| matches!(stmt.kind, mir::StatementKind::Coverage(_)))
+        {
+            if let Some(inlined) = stmt.source_info.scope.inlined_instance(&body.source_scopes) {
+                // This coverage statement was inlined from another function.
+                used_via_inlining.insert(inlined.def_id());
+            } else {
+                // Non-inlined coverage statements belong to the enclosing function.
+                saw_own_coverage = true;
+            }
+        }
+
+        if !saw_own_coverage && body.function_coverage_info.is_some() {
+            missing_own_coverage.insert(def_id);
+        }
+    }
+
+    UsageSets { all_mono_items, used_via_inlining, missing_own_coverage }
+}
+
+fn make_dummy_instance<'tcx>(tcx: TyCtxt<'tcx>, local_def_id: LocalDefId) -> ty::Instance<'tcx> {
+    let def_id = local_def_id.to_def_id();
+
+    // Make a dummy instance that fills in all generics with placeholders.
+    ty::Instance::new(
+        def_id,
+        ty::GenericArgs::for_item(tcx, def_id, |param, _| {
+            if let ty::GenericParamDefKind::Lifetime = param.kind {
+                tcx.lifetimes.re_erased.into()
+            } else {
+                tcx.mk_param_from_def(param)
+            }
+        }),
+    )
+}
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 0758e5d0456..6a37889217a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -3,7 +3,7 @@ use std::iter;
 use rustc_index::IndexVec;
 use rustc_index::bit_set::DenseBitSet;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::mir::{Local, UnwindTerminateReason, traversal};
+use rustc_middle::mir::{Body, Local, UnwindTerminateReason, traversal};
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_middle::{bug, mir, span_bug};
@@ -170,19 +170,29 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 ) {
     assert!(!instance.args.has_infer());
 
+    let tcx = cx.tcx();
     let llfn = cx.get_fn(instance);
 
-    let mir = cx.tcx().instance_mir(instance.def);
+    let mut mir = tcx.instance_mir(instance.def);
 
     let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
     debug!("fn_abi: {:?}", fn_abi);
 
-    if cx.tcx().codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) {
+    if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) {
         crate::mir::naked_asm::codegen_naked_asm::<Bx>(cx, &mir, instance);
         return;
     }
 
-    let debug_context = cx.create_function_debug_context(instance, fn_abi, llfn, mir);
+    if tcx.features().ergonomic_clones() {
+        let monomorphized_mir = instance.instantiate_mir_and_normalize_erasing_regions(
+            tcx,
+            ty::TypingEnv::fully_monomorphized(),
+            ty::EarlyBinder::bind(mir.clone()),
+        );
+        mir = tcx.arena.alloc(optimize_use_clone::<Bx>(cx, monomorphized_mir));
+    }
+
+    let debug_context = cx.create_function_debug_context(instance, fn_abi, llfn, &mir);
 
     let start_llbb = Bx::append_block(cx, llfn, "start");
     let mut start_bx = Bx::build(cx, start_llbb);
@@ -194,7 +204,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     }
 
     let cleanup_kinds =
-        base::wants_new_eh_instructions(cx.tcx().sess).then(|| analyze::cleanup_kinds(mir));
+        base::wants_new_eh_instructions(tcx.sess).then(|| analyze::cleanup_kinds(&mir));
 
     let cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>> =
         mir.basic_blocks
@@ -217,7 +227,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         cleanup_kinds,
         landing_pads: IndexVec::from_elem(None, &mir.basic_blocks),
         funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()),
-        cold_blocks: find_cold_blocks(cx.tcx(), mir),
+        cold_blocks: find_cold_blocks(tcx, mir),
         locals: locals::Locals::empty(),
         debug_context,
         per_local_var_debug_info: None,
@@ -233,7 +243,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         fx.compute_per_local_var_debug_info(&mut start_bx).unzip();
     fx.per_local_var_debug_info = per_local_var_debug_info;
 
-    let traversal_order = traversal::mono_reachable_reverse_postorder(mir, cx.tcx(), instance);
+    let traversal_order = traversal::mono_reachable_reverse_postorder(mir, tcx, instance);
     let memory_locals = analyze::non_ssa_locals(&fx, &traversal_order);
 
     // Allocate variable and temp allocas
@@ -310,6 +320,61 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     }
 }
 
+// FIXME: Move this function to mir::transform when post-mono MIR passes land.
+fn optimize_use_clone<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
+    cx: &'a Bx::CodegenCx,
+    mut mir: Body<'tcx>,
+) -> Body<'tcx> {
+    let tcx = cx.tcx();
+
+    if tcx.features().ergonomic_clones() {
+        for bb in mir.basic_blocks.as_mut() {
+            let mir::TerminatorKind::Call {
+                args,
+                destination,
+                target,
+                call_source: mir::CallSource::Use,
+                ..
+            } = &bb.terminator().kind
+            else {
+                continue;
+            };
+
+            // CallSource::Use calls always use 1 argument.
+            assert_eq!(args.len(), 1);
+            let arg = &args[0];
+
+            // These types are easily available from locals, so check that before
+            // doing DefId lookups to figure out what we're actually calling.
+            let arg_ty = arg.node.ty(&mir.local_decls, tcx);
+
+            let ty::Ref(_region, inner_ty, mir::Mutability::Not) = *arg_ty.kind() else { continue };
+
+            if !tcx.type_is_copy_modulo_regions(cx.typing_env(), inner_ty) {
+                continue;
+            }
+
+            let Some(arg_place) = arg.node.place() else { continue };
+
+            let destination_block = target.unwrap();
+
+            bb.statements.push(mir::Statement {
+                source_info: bb.terminator().source_info,
+                kind: mir::StatementKind::Assign(Box::new((
+                    *destination,
+                    mir::Rvalue::Use(mir::Operand::Copy(
+                        arg_place.project_deeper(&[mir::ProjectionElem::Deref], tcx),
+                    )),
+                ))),
+            });
+
+            bb.terminator_mut().kind = mir::TerminatorKind::Goto { target: destination_block };
+        }
+    }
+
+    mir
+}
+
 /// Produces, for each argument, a `Value` pointing at the
 /// argument's value. As arguments are places, these are always
 /// indirect.
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 7e355b6406a..eade9e52de9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -9,6 +9,7 @@ use rustc_middle::mir::{self, ConstValue};
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::{bug, span_bug};
+use rustc_session::config::OptLevel;
 use tracing::{debug, instrument};
 
 use super::place::{PlaceRef, PlaceValue};
@@ -496,6 +497,18 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                     _ => (tag_imm, bx.cx().immediate_backend_type(tag_op.layout)),
                 };
 
+                // Layout ensures that we only get here for cases where the discriminant
+                // value and the variant index match, since that's all `Niche` can encode.
+                // But for emphasis and debugging, let's double-check one anyway.
+                debug_assert_eq!(
+                    self.layout
+                        .ty
+                        .discriminant_for_variant(bx.tcx(), untagged_variant)
+                        .unwrap()
+                        .val,
+                    u128::from(untagged_variant.as_u32()),
+                );
+
                 let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
 
                 // We have a subrange `niche_start..=niche_end` inside `range`.
@@ -537,6 +550,21 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                         relative_discr,
                         bx.cx().const_uint(tag_llty, relative_max as u64),
                     );
+
+                    // Thanks to parameter attributes and load metadata, LLVM already knows
+                    // the general valid range of the tag. It's possible, though, for there
+                    // to be an impossible value *in the middle*, which those ranges don't
+                    // communicate, so it's worth an `assume` to let the optimizer know.
+                    if niche_variants.contains(&untagged_variant)
+                        && bx.cx().sess().opts.optimize != OptLevel::No
+                    {
+                        let impossible =
+                            u64::from(untagged_variant.as_u32() - niche_variants.start().as_u32());
+                        let impossible = bx.cx().const_uint(tag_llty, impossible);
+                        let ne = bx.icmp(IntPredicate::IntNE, relative_discr, impossible);
+                        bx.assume(ne);
+                    }
+
                     (is_niche, cast_tag, niche_variants.start().as_u32() as u128)
                 };
 
@@ -553,7 +581,9 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                 );
 
                 // In principle we could insert assumes on the possible range of `discr`, but
-                // currently in LLVM this seems to be a pessimization.
+                // currently in LLVM this isn't worth it because the original `tag` will
+                // have either a `range` parameter attribute or `!range` metadata,
+                // or come from a `transmute` that already `assume`d it.
 
                 discr
             }
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index f63b201742d..2c62034c6e8 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -315,7 +315,7 @@ mod helper {
     use super::*;
     pub(super) type ObligationTreeIdGenerator = impl Iterator<Item = ObligationTreeId>;
     impl<O: ForestObligation> ObligationForest<O> {
-        #[cfg_attr(not(bootstrap), define_opaque(ObligationTreeIdGenerator))]
+        #[define_opaque(ObligationTreeIdGenerator)]
         pub fn new() -> ObligationForest<O> {
             ObligationForest {
                 nodes: vec![],
diff --git a/compiler/rustc_error_codes/src/error_codes/E0622.md b/compiler/rustc_error_codes/src/error_codes/E0622.md
index 4cb605b636d..e6ff949d3e9 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0622.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0622.md
@@ -6,8 +6,9 @@ Erroneous code example:
 #![feature(intrinsics)]
 #![allow(internal_features)]
 
-extern "rust-intrinsic" {
-    pub static atomic_singlethreadfence_seqcst: fn();
+extern "C" {
+    #[rustc_intrinsic]
+    pub static atomic_singlethreadfence_seqcst: unsafe fn();
     // error: intrinsic must be a function
 }
 
@@ -22,9 +23,8 @@ error, just declare a function. Example:
 #![feature(intrinsics)]
 #![allow(internal_features)]
 
-extern "rust-intrinsic" {
-    pub fn atomic_singlethreadfence_seqcst(); // ok!
-}
+#[rustc_intrinsic]
+pub unsafe fn atomic_singlethreadfence_seqcst(); // ok!
 
 fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }
 ```
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 39e78ae8841..3c6df147b1b 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -208,7 +208,7 @@ pub type LazyFallbackBundle = Arc<LazyLock<FluentBundle, impl FnOnce() -> Fluent
 
 /// Return the default `FluentBundle` with standard "en-US" diagnostic messages.
 #[instrument(level = "trace", skip(resources))]
-#[cfg_attr(not(bootstrap), define_opaque(LazyFallbackBundle))]
+#[define_opaque(LazyFallbackBundle)]
 pub fn fallback_fluent_bundle(
     resources: Vec<&'static str>,
     with_directionality_markers: bool,
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 794502d7aae..bd13c413a4d 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -647,9 +647,9 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     #[rustc_lint_diagnostics]
     pub fn note_expected_found(
         &mut self,
-        expected_label: &dyn fmt::Display,
+        expected_label: &str,
         expected: DiagStyledString,
-        found_label: &dyn fmt::Display,
+        found_label: &str,
         found: DiagStyledString,
     ) -> &mut Self {
         self.note_expected_found_extra(
@@ -665,9 +665,9 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     #[rustc_lint_diagnostics]
     pub fn note_expected_found_extra(
         &mut self,
-        expected_label: &dyn fmt::Display,
+        expected_label: &str,
         expected: DiagStyledString,
-        found_label: &dyn fmt::Display,
+        found_label: &str,
         found: DiagStyledString,
         expected_extra: DiagStyledString,
         found_extra: DiagStyledString,
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index f5f7618285e..75bb0e8e7b4 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -589,7 +589,8 @@ struct DiagCtxtInner {
     /// add more information). All stashed diagnostics must be emitted with
     /// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped,
     /// otherwise an assertion failure will occur.
-    stashed_diagnostics: FxIndexMap<(Span, StashKey), (DiagInner, Option<ErrorGuaranteed>)>,
+    stashed_diagnostics:
+        FxIndexMap<StashKey, FxIndexMap<Span, (DiagInner, Option<ErrorGuaranteed>)>>,
 
     future_breakage_diagnostics: Vec<DiagInner>,
 
@@ -912,8 +913,12 @@ impl<'a> DiagCtxtHandle<'a> {
         // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
         // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
         // See the PR for a discussion.
-        let key = (span.with_parent(None), key);
-        self.inner.borrow_mut().stashed_diagnostics.insert(key, (diag, guar));
+        self.inner
+            .borrow_mut()
+            .stashed_diagnostics
+            .entry(key)
+            .or_default()
+            .insert(span.with_parent(None), (diag, guar));
 
         guar
     }
@@ -922,9 +927,10 @@ impl<'a> DiagCtxtHandle<'a> {
     /// and [`StashKey`] as the key. Panics if the found diagnostic is an
     /// error.
     pub fn steal_non_err(self, span: Span, key: StashKey) -> Option<Diag<'a, ()>> {
-        let key = (span.with_parent(None), key);
         // FIXME(#120456) - is `swap_remove` correct?
-        let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key)?;
+        let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
+            |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
+        )?;
         assert!(!diag.is_error());
         assert!(guar.is_none());
         Some(Diag::new_diagnostic(self, diag))
@@ -943,9 +949,10 @@ impl<'a> DiagCtxtHandle<'a> {
     where
         F: FnMut(&mut Diag<'_>),
     {
-        let key = (span.with_parent(None), key);
         // FIXME(#120456) - is `swap_remove` correct?
-        let err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key);
+        let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
+            |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
+        );
         err.map(|(err, guar)| {
             // The use of `::<ErrorGuaranteed>` is safe because level is `Level::Error`.
             assert_eq!(err.level, Error);
@@ -966,9 +973,10 @@ impl<'a> DiagCtxtHandle<'a> {
         key: StashKey,
         new_err: Diag<'_>,
     ) -> ErrorGuaranteed {
-        let key = (span.with_parent(None), key);
         // FIXME(#120456) - is `swap_remove` correct?
-        let old_err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key);
+        let old_err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
+            |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
+        );
         match old_err {
             Some((old_err, guar)) => {
                 assert_eq!(old_err.level, Error);
@@ -983,7 +991,14 @@ impl<'a> DiagCtxtHandle<'a> {
     }
 
     pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
-        self.inner.borrow().stashed_diagnostics.get(&(span.with_parent(None), key)).is_some()
+        let inner = self.inner.borrow();
+        if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key)
+            && !stashed_diagnostics.is_empty()
+        {
+            stashed_diagnostics.contains_key(&span.with_parent(None))
+        } else {
+            false
+        }
     }
 
     /// Emit all stashed diagnostics.
@@ -997,7 +1012,11 @@ impl<'a> DiagCtxtHandle<'a> {
         let inner = self.inner.borrow();
         inner.err_guars.len()
             + inner.lint_err_guars.len()
-            + inner.stashed_diagnostics.values().filter(|(_diag, guar)| guar.is_some()).count()
+            + inner
+                .stashed_diagnostics
+                .values()
+                .map(|a| a.values().filter(|(_, guar)| guar.is_some()).count())
+                .sum::<usize>()
     }
 
     /// This excludes lint errors and delayed bugs. Unless absolutely
@@ -1486,16 +1505,18 @@ impl DiagCtxtInner {
     fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
         let mut guar = None;
         let has_errors = !self.err_guars.is_empty();
-        for (_, (diag, _guar)) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
-            if !diag.is_error() {
-                // Unless they're forced, don't flush stashed warnings when
-                // there are errors, to avoid causing warning overload. The
-                // stash would've been stolen already if it were important.
-                if !diag.is_force_warn() && has_errors {
-                    continue;
+        for (_, stashed_diagnostics) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
+            for (_, (diag, _guar)) in stashed_diagnostics {
+                if !diag.is_error() {
+                    // Unless they're forced, don't flush stashed warnings when
+                    // there are errors, to avoid causing warning overload. The
+                    // stash would've been stolen already if it were important.
+                    if !diag.is_force_warn() && has_errors {
+                        continue;
+                    }
                 }
+                guar = guar.or(self.emit_diagnostic(diag, None));
             }
-            guar = guar.or(self.emit_diagnostic(diag, None));
         }
         guar
     }
@@ -1688,6 +1709,7 @@ impl DiagCtxtInner {
             if let Some((_diag, guar)) = self
                 .stashed_diagnostics
                 .values()
+                .flat_map(|stashed_diagnostics| stashed_diagnostics.values())
                 .find(|(diag, guar)| guar.is_some() && diag.is_lint.is_none())
             {
                 *guar
@@ -1700,13 +1722,9 @@ impl DiagCtxtInner {
     fn has_errors(&self) -> Option<ErrorGuaranteed> {
         self.err_guars.get(0).copied().or_else(|| self.lint_err_guars.get(0).copied()).or_else(
             || {
-                if let Some((_diag, guar)) =
-                    self.stashed_diagnostics.values().find(|(_diag, guar)| guar.is_some())
-                {
-                    *guar
-                } else {
-                    None
-                }
+                self.stashed_diagnostics.values().find_map(|stashed_diagnostics| {
+                    stashed_diagnostics.values().find_map(|(_, guar)| *guar)
+                })
             },
         )
     }
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index f68172c1f67..6d616cf84bb 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -230,6 +230,7 @@ impl<'a> ExtCtxt<'a> {
             self.pat_ident(sp, ident)
         };
         let local = P(ast::Local {
+            super_: None,
             pat,
             ty,
             id: ast::DUMMY_NODE_ID,
@@ -245,6 +246,7 @@ impl<'a> ExtCtxt<'a> {
     /// Generates `let _: Type;`, which is usually used for type assertions.
     pub fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt {
         let local = P(ast::Local {
+            super_: None,
             pat: self.pat_wild(span),
             ty: Some(ty),
             id: ast::DUMMY_NODE_ID,
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 88e6593572b..8968c1771e4 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -63,7 +63,7 @@ declare_features! (
     /// Allows using `const` operands in inline assembly.
     (accepted, asm_const, "1.82.0", Some(93332)),
     /// Allows using `label` operands in inline assembly.
-    (accepted, asm_goto, "CURRENT_RUSTC_VERSION", Some(119364)),
+    (accepted, asm_goto, "1.87.0", Some(119364)),
     /// Allows using `sym` operands in inline assembly.
     (accepted, asm_sym, "1.66.0", Some(93333)),
     /// Allows the definition of associated constants in `trait` or `impl` blocks.
@@ -332,7 +332,7 @@ declare_features! (
     /// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
     (accepted, precise_capturing, "1.82.0", Some(123432)),
     /// Allows `use<..>` precise capturign on impl Trait in traits.
-    (accepted, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)),
+    (accepted, precise_capturing_in_traits, "1.87.0", Some(130044)),
     /// Allows procedural macros in `proc-macro` crates.
     (accepted, proc_macro, "1.29.0", Some(38356)),
     /// Allows multi-segment paths in attributes and derives.
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 6ba7b22a0df..402e18c5d14 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -247,7 +247,7 @@ declare_features! (
     /// Allows unnamed fields of struct and union type
     (removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign")),
     (removed, unsafe_no_drop_flag, "1.0.0", None, None),
-    (removed, unsized_tuple_coercion, "CURRENT_RUSTC_VERSION", Some(42877),
+    (removed, unsized_tuple_coercion, "1.87.0", Some(42877),
      Some("The feature restricts possible layouts for tuples, and this restriction is not worth it.")),
     /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue.
     (removed, untagged_unions, "1.13.0", Some(55149),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 710e129b609..98213affc5b 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -211,7 +211,7 @@ declare_features! (
     (internal, custom_mir, "1.65.0", None),
     /// Outputs useful `assert!` messages
     (unstable, generic_assert, "1.63.0", None),
-    /// Allows using the `rust-intrinsic`'s "ABI".
+    /// Allows using the #[rustc_intrinsic] attribute.
     (internal, intrinsics, "1.0.0", None),
     /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
     (internal, lang_items, "1.0.0", None),
@@ -474,7 +474,7 @@ declare_features! (
     /// Allows `dyn* Trait` objects.
     (incomplete, dyn_star, "1.65.0", Some(102425)),
     /// Allows the .use postfix syntax `x.use` and use closures `use |x| { ... }`
-    (incomplete, ergonomic_clones, "CURRENT_RUSTC_VERSION", Some(132290)),
+    (incomplete, ergonomic_clones, "1.87.0", Some(132290)),
     /// Allows exhaustive pattern matching on types that contain uninhabited types.
     (unstable, exhaustive_patterns, "1.13.0", Some(51085)),
     /// Allows explicit tail calls via `become` expression.
@@ -511,7 +511,7 @@ declare_features! (
     /// Allows generic parameters and where-clauses on free & associated const items.
     (incomplete, generic_const_items, "1.73.0", Some(113521)),
     /// Allows the type of const generics to depend on generic parameters
-    (incomplete, generic_const_parameter_types, "CURRENT_RUSTC_VERSION", Some(137626)),
+    (incomplete, generic_const_parameter_types, "1.87.0", Some(137626)),
     /// Allows any generic constants being used as pattern type range ends
     (incomplete, generic_pattern_types, "1.86.0", Some(136574)),
     /// Allows registering static items globally, possibly across crates, to iterate over at runtime.
@@ -602,7 +602,7 @@ declare_features! (
     /// Allows macro attributes on expressions, statements and non-inline modules.
     (unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
     /// Allows the use of raw-dylibs on ELF platforms
-    (incomplete, raw_dylib_elf, "CURRENT_RUSTC_VERSION", Some(135694)),
+    (incomplete, raw_dylib_elf, "1.87.0", Some(135694)),
     /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
     (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)),
     /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant
@@ -630,7 +630,7 @@ declare_features! (
     /// Allows string patterns to dereference values to match them.
     (unstable, string_deref_patterns, "1.67.0", Some(87121)),
     /// Allows `super let` statements.
-    (incomplete, super_let, "CURRENT_RUSTC_VERSION", Some(139076)),
+    (unstable, super_let, "CURRENT_RUSTC_VERSION", Some(139076)),
     /// Allows subtrait items to shadow supertrait items.
     (unstable, supertrait_item_shadowing, "1.86.0", Some(89151)),
     /// Allows using `#[thread_local]` on `static` items.
@@ -664,14 +664,14 @@ declare_features! (
     /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
     (unstable, used_with_arg, "1.60.0", Some(93798)),
     /// Allows use of attributes in `where` clauses.
-    (unstable, where_clause_attrs, "CURRENT_RUSTC_VERSION", Some(115590)),
+    (unstable, where_clause_attrs, "1.87.0", Some(115590)),
     /// Allows use of x86 `AMX` target-feature attributes and intrinsics
     (unstable, x86_amx_intrinsics, "1.81.0", Some(126622)),
     /// Allows use of the `xop` target-feature
     (unstable, xop_target_feature, "1.81.0", Some(127208)),
     /// Allows `do yeet` expressions
     (unstable, yeet_expr, "1.62.0", Some(96373)),
-    (unstable, yield_expr, "CURRENT_RUSTC_VERSION", Some(43122)),
+    (unstable, yield_expr, "1.87.0", Some(43122)),
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
     // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 1a6c15b66a4..c61477951c9 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1555,6 +1555,7 @@ impl<'hir> Pat<'hir> {
 
         use PatKind::*;
         match self.kind {
+            Missing => unreachable!(),
             Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => true,
             Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it),
             Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
@@ -1582,7 +1583,7 @@ impl<'hir> Pat<'hir> {
 
         use PatKind::*;
         match self.kind {
-            Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {}
+            Missing | Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {}
             Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
             Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
             TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
@@ -1720,6 +1721,9 @@ pub enum TyPatKind<'hir> {
 
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum PatKind<'hir> {
+    /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`.
+    Missing,
+
     /// Represents a wildcard pattern (i.e., `_`).
     Wild,
 
@@ -1817,6 +1821,8 @@ pub enum StmtKind<'hir> {
 /// Represents a `let` statement (i.e., `let <pat>:<ty> = <init>;`).
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct LetStmt<'hir> {
+    /// Span of `super` in `super let`.
+    pub super_: Option<Span>,
     pub pat: &'hir Pat<'hir>,
     /// Type annotation, if any (otherwise the type will be inferred).
     pub ty: Option<&'hir Ty<'hir>>,
@@ -4850,7 +4856,7 @@ mod size_asserts {
     static_assert_size!(ImplItemKind<'_>, 40);
     static_assert_size!(Item<'_>, 88);
     static_assert_size!(ItemKind<'_>, 64);
-    static_assert_size!(LetStmt<'_>, 64);
+    static_assert_size!(LetStmt<'_>, 72);
     static_assert_size!(Param<'_>, 32);
     static_assert_size!(Pat<'_>, 72);
     static_assert_size!(Path<'_>, 40);
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 506358341b5..ea3f396761b 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -744,7 +744,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
             visit_opt!(visitor, visit_pat_expr, lower_bound);
             visit_opt!(visitor, visit_pat_expr, upper_bound);
         }
-        PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
+        PatKind::Missing | PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
         PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
             walk_list!(visitor, visit_pat, prepatterns);
             visit_opt!(visitor, visit_pat, slice_pattern);
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 194f2cd04e4..2f7c3cb3c7d 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -486,6 +486,9 @@ hir_analysis_self_in_impl_self =
     `Self` is not valid in the self type of an impl block
     .note = replace `Self` with a different type
 
+hir_analysis_self_in_type_alias = `Self` is not allowed in type aliases
+    .label = `Self` is only available in impls, traits, and concrete type definitions
+
 hir_analysis_self_ty_not_captured = `impl Trait` must mention the `Self` type of the trait in `use<...>`
     .label = `Self` type parameter is implicitly captured by this `impl Trait`
     .note = currently, all type parameters are required to be mentioned in the precise captures list
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index a0798656763..bcfbd7b0e97 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -397,8 +397,11 @@ fn best_definition_site_of_opaque<'tcx>(
                 return ControlFlow::Continue(());
             }
 
-            if let Some(hidden_ty) =
-                self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id)
+            if let Some(hidden_ty) = self
+                .tcx
+                .mir_borrowck(item_def_id)
+                .ok()
+                .and_then(|opaque_types| opaque_types.0.get(&self.opaque_def_id))
             {
                 ControlFlow::Break((hidden_ty.span, item_def_id))
             } else {
@@ -413,9 +416,6 @@ fn best_definition_site_of_opaque<'tcx>(
             self.tcx
         }
         fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result {
-            if let hir::ExprKind::Closure(closure) = ex.kind {
-                self.check(closure.def_id)?;
-            }
             intravisit::walk_expr(self, ex)
         }
         fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) -> Self::Result {
@@ -741,10 +741,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 
             for &assoc_item in assoc_items.in_definition_order() {
                 match assoc_item.kind {
-                    ty::AssocKind::Fn => {
-                        let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi();
-                        forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi);
-                    }
                     ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
                         let trait_args = GenericArgs::identity_for_item(tcx, def_id);
                         let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
@@ -788,65 +784,59 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             };
             check_abi(tcx, it.span, abi);
 
-            match abi {
-                ExternAbi::RustIntrinsic => {
-                    for item in items {
-                        intrinsic::check_intrinsic_type(
-                            tcx,
-                            item.id.owner_id.def_id,
-                            item.span,
-                            item.ident.name,
-                            abi,
-                        );
-                    }
+            for item in items {
+                let def_id = item.id.owner_id.def_id;
+
+                if tcx.has_attr(def_id, sym::rustc_intrinsic) {
+                    intrinsic::check_intrinsic_type(
+                        tcx,
+                        item.id.owner_id.def_id,
+                        item.span,
+                        item.ident.name,
+                        abi,
+                    );
                 }
 
-                _ => {
-                    for item in items {
-                        let def_id = item.id.owner_id.def_id;
-                        let generics = tcx.generics_of(def_id);
-                        let own_counts = generics.own_counts();
-                        if generics.own_params.len() - own_counts.lifetimes != 0 {
-                            let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts)
-                            {
-                                (_, 0) => ("type", "types", Some("u32")),
-                                // We don't specify an example value, because we can't generate
-                                // a valid value for any type.
-                                (0, _) => ("const", "consts", None),
-                                _ => ("type or const", "types or consts", None),
-                            };
-                            struct_span_code_err!(
-                                tcx.dcx(),
-                                item.span,
-                                E0044,
-                                "foreign items may not have {kinds} parameters",
-                            )
-                            .with_span_label(item.span, format!("can't have {kinds} parameters"))
-                            .with_help(
-                                // FIXME: once we start storing spans for type arguments, turn this
-                                // into a suggestion.
-                                format!(
-                                    "replace the {} parameters with concrete {}{}",
-                                    kinds,
-                                    kinds_pl,
-                                    egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(),
-                                ),
-                            )
-                            .emit();
-                        }
+                let generics = tcx.generics_of(def_id);
+                let own_counts = generics.own_counts();
+                if generics.own_params.len() - own_counts.lifetimes != 0 {
+                    let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) {
+                        (_, 0) => ("type", "types", Some("u32")),
+                        // We don't specify an example value, because we can't generate
+                        // a valid value for any type.
+                        (0, _) => ("const", "consts", None),
+                        _ => ("type or const", "types or consts", None),
+                    };
+                    struct_span_code_err!(
+                        tcx.dcx(),
+                        item.span,
+                        E0044,
+                        "foreign items may not have {kinds} parameters",
+                    )
+                    .with_span_label(item.span, format!("can't have {kinds} parameters"))
+                    .with_help(
+                        // FIXME: once we start storing spans for type arguments, turn this
+                        // into a suggestion.
+                        format!(
+                            "replace the {} parameters with concrete {}{}",
+                            kinds,
+                            kinds_pl,
+                            egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(),
+                        ),
+                    )
+                    .emit();
+                }
 
-                        let item = tcx.hir_foreign_item(item.id);
-                        match &item.kind {
-                            hir::ForeignItemKind::Fn(sig, _, _) => {
-                                require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span);
-                            }
-                            hir::ForeignItemKind::Static(..) => {
-                                check_static_inhabited(tcx, def_id);
-                                check_static_linkage(tcx, def_id);
-                            }
-                            _ => {}
-                        }
+                let item = tcx.hir_foreign_item(item.id);
+                match &item.kind {
+                    hir::ForeignItemKind::Fn(sig, _, _) => {
+                        require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span);
                     }
+                    hir::ForeignItemKind::Static(..) => {
+                        check_static_inhabited(tcx, def_id);
+                        check_static_linkage(tcx, def_id);
+                    }
+                    _ => {}
                 }
             }
         }
@@ -947,31 +937,7 @@ fn check_impl_items_against_trait<'tcx>(
 
     let trait_def = tcx.trait_def(trait_ref.def_id);
 
-    let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
-
-    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
-    let cause = ObligationCause::misc(tcx.def_span(impl_id), impl_id);
-    let param_env = tcx.param_env(impl_id);
-
-    let self_is_guaranteed_unsized = match tcx
-        .struct_tail_raw(
-            trait_ref.self_ty(),
-            |ty| {
-                ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| {
-                    Ty::new_error_with_message(
-                        tcx,
-                        tcx.def_span(impl_id),
-                        "struct tail should be computable",
-                    )
-                })
-            },
-            || (),
-        )
-        .kind()
-    {
-        ty::Dynamic(_, _, ty::DynKind::Dyn) | ty::Slice(_) | ty::Str => true,
-        _ => false,
-    };
+    let self_is_guaranteed_unsize_self = tcx.impl_self_is_guaranteed_unsized(impl_id);
 
     for &impl_item in impl_item_refs {
         let ty_impl_item = tcx.associated_item(impl_item);
@@ -1002,7 +968,7 @@ fn check_impl_items_against_trait<'tcx>(
             }
         }
 
-        if self_is_guaranteed_unsized && tcx.generics_require_sized_self(ty_trait_item.def_id) {
+        if self_is_guaranteed_unsize_self && tcx.generics_require_sized_self(ty_trait_item.def_id) {
             tcx.emit_node_span_lint(
                 rustc_lint_defs::builtin::DEAD_CODE,
                 tcx.local_def_id_to_hir_id(ty_impl_item.def_id.expect_local()),
@@ -1037,7 +1003,7 @@ fn check_impl_items_against_trait<'tcx>(
             if !is_implemented
                 && tcx.defaultness(impl_id).is_final()
                 // unsized types don't need to implement methods that have `Self: Sized` bounds.
-                && !(self_is_guaranteed_unsized && tcx.generics_require_sized_self(trait_item_id))
+                && !(self_is_guaranteed_unsize_self && tcx.generics_require_sized_self(trait_item_id))
             {
                 missing_items.push(tcx.associated_item(trait_item_id));
             }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 5e68bb31001..32a8f101849 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -442,7 +442,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateParam<'tcx> {
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        if let ty::ReLateParam(fr) = *r {
+        if let ty::ReLateParam(fr) = r.kind() {
             ty::Region::new_late_param(
                 self.tcx,
                 fr.scope,
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 42d785c8dd0..0bf9e127989 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -1,4 +1,4 @@
-//! Type-checking for the rust-intrinsic intrinsics that the compiler exposes.
+//! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes.
 
 use rustc_abi::ExternAbi;
 use rustc_errors::codes::*;
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 7c5d7b33a34..30921b6f055 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -137,15 +137,6 @@ fn get_owner_return_paths(
     })
 }
 
-/// Forbid defining intrinsics in Rust code,
-/// as they must always be defined by the compiler.
-// FIXME: Move this to a more appropriate place.
-pub fn forbid_intrinsic_abi(tcx: TyCtxt<'_>, sp: Span, abi: ExternAbi) {
-    if let ExternAbi::RustIntrinsic = abi {
-        tcx.dcx().span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block");
-    }
-}
-
 pub(super) fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
     // Only restricted on wasm target for now
     if !tcx.sess.target.is_like_wasm {
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index cf66ab708bb..7cb31a64e13 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -8,6 +8,7 @@
 
 use std::mem;
 
+use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, Visitor};
@@ -44,6 +45,8 @@ struct ScopeResolutionVisitor<'tcx> {
     scope_tree: ScopeTree,
 
     cx: Context,
+
+    extended_super_lets: FxHashMap<hir::ItemLocalId, Option<Scope>>,
 }
 
 /// Records the lifetime of a local variable as `cx.var_parent`
@@ -214,18 +217,29 @@ fn resolve_stmt<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, stmt: &'tcx hi
     let stmt_id = stmt.hir_id.local_id;
     debug!("resolve_stmt(stmt.id={:?})", stmt_id);
 
-    // Every statement will clean up the temporaries created during
-    // execution of that statement. Therefore each statement has an
-    // associated destruction scope that represents the scope of the
-    // statement plus its destructors, and thus the scope for which
-    // regions referenced by the destructors need to survive.
+    if let hir::StmtKind::Let(LetStmt { super_: Some(_), .. }) = stmt.kind {
+        // `super let` statement does not start a new scope, such that
+        //
+        //     { super let x = identity(&temp()); &x }.method();
+        //
+        // behaves exactly as
+        //
+        //     (&identity(&temp()).method();
+        intravisit::walk_stmt(visitor, stmt);
+    } else {
+        // Every statement will clean up the temporaries created during
+        // execution of that statement. Therefore each statement has an
+        // associated destruction scope that represents the scope of the
+        // statement plus its destructors, and thus the scope for which
+        // regions referenced by the destructors need to survive.
 
-    let prev_parent = visitor.cx.parent;
-    visitor.enter_node_scope_with_dtor(stmt_id, true);
+        let prev_parent = visitor.cx.parent;
+        visitor.enter_node_scope_with_dtor(stmt_id, true);
 
-    intravisit::walk_stmt(visitor, stmt);
+        intravisit::walk_stmt(visitor, stmt);
 
-    visitor.cx.parent = prev_parent;
+        visitor.cx.parent = prev_parent;
+    }
 }
 
 fn resolve_expr<'tcx>(
@@ -446,14 +460,11 @@ fn resolve_expr<'tcx>(
         // Mark this expr's scope and all parent scopes as containing `yield`.
         let mut scope = Scope { local_id: expr.hir_id.local_id, data: ScopeData::Node };
         loop {
-            let span = match expr.kind {
-                hir::ExprKind::Yield(expr, hir::YieldSource::Await { .. }) => {
-                    expr.span.shrink_to_hi().to(expr.span)
-                }
-                _ => expr.span,
+            let data = YieldData {
+                span: expr.span,
+                expr_and_pat_count: visitor.expr_and_pat_count,
+                source: *source,
             };
-            let data =
-                YieldData { span, expr_and_pat_count: visitor.expr_and_pat_count, source: *source };
             match visitor.scope_tree.yield_in_scope.get_mut(&scope) {
                 Some(yields) => yields.push(data),
                 None => {
@@ -481,14 +492,19 @@ fn resolve_expr<'tcx>(
     visitor.cx = prev_cx;
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum LetKind {
+    Regular,
+    Super,
+}
+
 fn resolve_local<'tcx>(
     visitor: &mut ScopeResolutionVisitor<'tcx>,
     pat: Option<&'tcx hir::Pat<'tcx>>,
     init: Option<&'tcx hir::Expr<'tcx>>,
+    let_kind: LetKind,
 ) {
-    debug!("resolve_local(pat={:?}, init={:?})", pat, init);
-
-    let blk_scope = visitor.cx.var_parent;
+    debug!("resolve_local(pat={:?}, init={:?}, let_kind={:?})", pat, init, let_kind);
 
     // As an exception to the normal rules governing temporary
     // lifetimes, initializers in a let have a temporary lifetime
@@ -546,14 +562,50 @@ fn resolve_local<'tcx>(
     // A, but the inner rvalues `a()` and `b()` have an extended lifetime
     // due to rule C.
 
+    if let_kind == LetKind::Super {
+        if let Some(scope) = visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) {
+            // This expression was lifetime-extended by a parent let binding. E.g.
+            //
+            //     let a = {
+            //         super let b = temp();
+            //         &b
+            //     };
+            //
+            // (Which needs to behave exactly as: let a = &temp();)
+            //
+            // Processing of `let a` will have already decided to extend the lifetime of this
+            // `super let` to its own var_scope. We use that scope.
+            visitor.cx.var_parent = scope;
+        } else {
+            // This `super let` is not subject to lifetime extension from a parent let binding. E.g.
+            //
+            //     identity({ super let x = temp(); &x }).method();
+            //
+            // (Which needs to behave exactly as: identity(&temp()).method();)
+            //
+            // Iterate up to the enclosing destruction scope to find the same scope that will also
+            // be used for the result of the block itself.
+            while let Some(s) = visitor.cx.var_parent {
+                let parent = visitor.scope_tree.parent_map.get(&s).cloned();
+                if let Some(Scope { data: ScopeData::Destruction, .. }) = parent {
+                    break;
+                }
+                visitor.cx.var_parent = parent;
+            }
+        }
+    }
+
     if let Some(expr) = init {
-        record_rvalue_scope_if_borrow_expr(visitor, expr, blk_scope);
+        record_rvalue_scope_if_borrow_expr(visitor, expr, visitor.cx.var_parent);
 
         if let Some(pat) = pat {
             if is_binding_pat(pat) {
                 visitor.scope_tree.record_rvalue_candidate(
                     expr.hir_id,
-                    RvalueCandidate { target: expr.hir_id.local_id, lifetime: blk_scope },
+                    RvalueCandidate {
+                        target: expr.hir_id.local_id,
+                        lifetime: visitor.cx.var_parent,
+                    },
                 );
             }
         }
@@ -565,6 +617,7 @@ fn resolve_local<'tcx>(
     if let Some(expr) = init {
         visitor.visit_expr(expr);
     }
+
     if let Some(pat) = pat {
         visitor.visit_pat(pat);
     }
@@ -626,6 +679,7 @@ fn resolve_local<'tcx>(
 
             PatKind::Ref(_, _)
             | PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..)
+            | PatKind::Missing
             | PatKind::Wild
             | PatKind::Never
             | PatKind::Expr(_)
@@ -642,6 +696,7 @@ fn resolve_local<'tcx>(
     ///        | [ ..., E&, ... ]
     ///        | ( ..., E&, ... )
     ///        | {...; E&}
+    ///        | { super let ... = E&; ... }
     ///        | if _ { ...; E& } else { ...; E& }
     ///        | match _ { ..., _ => E&, ... }
     ///        | box E&
@@ -678,6 +733,13 @@ fn resolve_local<'tcx>(
                 if let Some(subexpr) = block.expr {
                     record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
                 }
+                for stmt in block.stmts {
+                    if let hir::StmtKind::Let(local) = stmt.kind
+                        && let Some(_) = local.super_
+                    {
+                        visitor.extended_super_lets.insert(local.pat.hir_id.local_id, blk_id);
+                    }
+                }
             }
             hir::ExprKind::If(_, then_block, else_block) => {
                 record_rvalue_scope_if_borrow_expr(visitor, then_block, blk_id);
@@ -803,7 +865,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
                     local_id: body.value.hir_id.local_id,
                     data: ScopeData::Destruction,
                 });
-                resolve_local(this, None, Some(body.value));
+                resolve_local(this, None, Some(body.value), LetKind::Regular);
             }
         })
     }
@@ -821,7 +883,11 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
         resolve_expr(self, ex, false);
     }
     fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) {
-        resolve_local(self, Some(l.pat), l.init)
+        let let_kind = match l.super_ {
+            Some(_) => LetKind::Super,
+            None => LetKind::Regular,
+        };
+        resolve_local(self, Some(l.pat), l.init, let_kind);
     }
     fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) {
         let body = self.tcx.hir_body(c.body);
@@ -850,6 +916,7 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
             cx: Context { parent: None, var_parent: None },
             pessimistic_yield: false,
             fixup_scopes: vec![],
+            extended_super_lets: Default::default(),
         };
 
         visitor.scope_tree.root_body = Some(body.value.hir_id);
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 83d095ab72e..6292d03bf6a 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -631,7 +631,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
         // Ignore `'static` lifetimes for the purpose of this lint: it's
         // because we know it outlives everything and so doesn't give meaningful
         // clues. Also ignore `ReError`, to avoid knock-down errors.
-        if let ty::ReStatic | ty::ReError(_) = **region_a {
+        if let ty::ReStatic | ty::ReError(_) = region_a.kind() {
             continue;
         }
         // For each region argument (e.g., `'a` in our example), check for a
@@ -672,7 +672,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
             // Again, skip `'static` because it outlives everything. Also, we trivially
             // know that a region outlives itself. Also ignore `ReError`, to avoid
             // knock-down errors.
-            if matches!(**region_b, ty::ReStatic | ty::ReError(_)) || region_a == region_b {
+            if matches!(region_b.kind(), ty::ReStatic | ty::ReError(_)) || region_a == region_b {
                 continue;
             }
             if region_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *region_a, *region_b) {
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 1f3f0b754bb..8ad9d80c6b5 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -656,7 +656,7 @@ fn infringing_fields_error<'tcx>(
                                 .entry((ty.clone(), predicate.clone()))
                                 .or_default()
                                 .push(origin.span());
-                            if let ty::RegionKind::ReEarlyParam(ebr) = *b
+                            if let ty::RegionKind::ReEarlyParam(ebr) = b.kind()
                                 && ebr.has_name()
                             {
                                 bounds.push((b.to_string(), a.to_string(), None));
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 625f51dd29e..69b921fccbf 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -14,6 +14,7 @@
 //! At present, however, we do run collection across all items in the
 //! crate as a kind of pass. This should eventually be factored away.
 
+use std::assert_matches::assert_matches;
 use std::cell::Cell;
 use std::iter;
 use std::ops::Bound;
@@ -42,7 +43,6 @@ use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::ObligationCtxt;
 use tracing::{debug, instrument};
 
-use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::errors;
 use crate::hir_ty_lowering::errors::assoc_kind_str;
 use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
@@ -1345,7 +1345,8 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
             compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
         }
 
-        Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
+        Ctor(data) => {
+            assert_matches!(data.ctor(), Some(_));
             let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id();
             let ty = tcx.type_of(adt_def_id).instantiate_identity();
             let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
@@ -1417,7 +1418,7 @@ fn recover_infer_ret_ty<'tcx>(
         GenericParamKind::Lifetime { .. } => true,
         _ => false,
     });
-    let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r {
+    let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() {
         ty::ReErased => {
             if has_region_params {
                 ty::Region::new_error_with_message(
@@ -1704,18 +1705,13 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
     abi: ExternAbi,
     safety: hir::Safety,
 ) -> ty::PolyFnSig<'tcx> {
-    let safety = if abi == ExternAbi::RustIntrinsic {
-        intrinsic_operation_unsafety(tcx, def_id)
-    } else {
-        safety
-    };
     let hir_id = tcx.local_def_id_to_hir_id(def_id);
     let fty =
         ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None);
 
     // Feature gate SIMD types in FFI, since I am not sure that the
     // ABIs are handled at all correctly. -huonw
-    if abi != ExternAbi::RustIntrinsic && !tcx.features().simd_ffi() {
+    if !tcx.features().simd_ffi() {
         let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
             if ty.is_simd() {
                 let snip = tcx
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 776b23bea8e..e90a1cc24c1 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -172,33 +172,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     };
 
     if let Node::TraitItem(item) = node {
-        let parent = tcx.local_parent(item.hir_id().owner.def_id);
-        let Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else {
-            unreachable!();
-        };
-
-        let (trait_generics, trait_bounds) = match parent_trait.kind {
-            hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits),
-            hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
-            _ => unreachable!(),
-        };
-
-        // Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if
-        // they are not added as super trait bounds to the trait itself. See comment on
-        // `requires_default_supertraits` for more details.
-        if !icx.lowerer().requires_default_supertraits(trait_bounds, trait_generics) {
-            let mut bounds = Vec::new();
-            let self_ty_where_predicates = (parent, item.generics.predicates);
-            icx.lowerer().add_default_traits_with_filter(
-                &mut bounds,
-                tcx.types.self_param,
-                &[],
-                Some(self_ty_where_predicates),
-                item.span,
-                |tr| tr != hir::LangItem::Sized,
-            );
-            predicates.extend(bounds);
-        }
+        let mut bounds = Vec::new();
+        icx.lowerer().add_default_trait_item_bounds(item, &mut bounds);
+        predicates.extend(bounds);
     }
 
     let generics = tcx.generics_of(def_id);
@@ -383,7 +359,7 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
 ) {
     for param in opaque_own_params {
         let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
-        if let ty::ReEarlyParam(..) = *orig_lifetime {
+        if let ty::ReEarlyParam(..) = orig_lifetime.kind() {
             let dup_lifetime = ty::Region::new_early_param(
                 tcx,
                 ty::EarlyParamRegion { index: param.index, name: param.name },
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index 3fe3d71b32d..772197a53ac 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -183,25 +183,23 @@ impl<'tcx> TaitConstraintLocator<'tcx> {
                     self.non_defining_use_in_defining_scope(item_def_id);
                 }
             }
-            DefiningScopeKind::MirBorrowck => {
-                let borrowck_result = tcx.mir_borrowck(item_def_id);
-                if let Some(guar) = borrowck_result.tainted_by_errors {
-                    self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar));
-                } else if let Some(&hidden_type) =
-                    borrowck_result.concrete_opaque_types.get(&self.def_id)
-                {
-                    debug!(?hidden_type, "found constraint");
-                    self.insert_found(hidden_type);
-                } else if let Err(guar) = tcx
-                    .type_of_opaque_hir_typeck(self.def_id)
-                    .instantiate_identity()
-                    .error_reported()
-                {
-                    self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar));
-                } else {
-                    self.non_defining_use_in_defining_scope(item_def_id);
+            DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(item_def_id) {
+                Err(guar) => self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)),
+                Ok(concrete_opaque_types) => {
+                    if let Some(&hidden_type) = concrete_opaque_types.0.get(&self.def_id) {
+                        debug!(?hidden_type, "found constraint");
+                        self.insert_found(hidden_type);
+                    } else if let Err(guar) = tcx
+                        .type_of_opaque_hir_typeck(self.def_id)
+                        .instantiate_identity()
+                        .error_reported()
+                    {
+                        self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar));
+                    } else {
+                        self.non_defining_use_in_defining_scope(item_def_id);
+                    }
                 }
-            }
+            },
         }
     }
 }
@@ -264,20 +262,20 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
                 Ty::new_diverging_default(tcx)
             }
         }
-        DefiningScopeKind::MirBorrowck => {
-            let borrowck_result = tcx.mir_borrowck(owner_def_id);
-            if let Some(guar) = borrowck_result.tainted_by_errors {
-                Ty::new_error(tcx, guar)
-            } else if let Some(hidden_ty) = borrowck_result.concrete_opaque_types.get(&def_id) {
-                hidden_ty.ty
-            } else {
-                let hir_ty = tcx.type_of_opaque_hir_typeck(def_id).instantiate_identity();
-                if let Err(guar) = hir_ty.error_reported() {
-                    Ty::new_error(tcx, guar)
+        DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(owner_def_id) {
+            Ok(concrete_opaque_types) => {
+                if let Some(hidden_ty) = concrete_opaque_types.0.get(&def_id) {
+                    hidden_ty.ty
                 } else {
-                    hir_ty
+                    let hir_ty = tcx.type_of_opaque_hir_typeck(def_id).instantiate_identity();
+                    if let Err(guar) = hir_ty.error_reported() {
+                        Ty::new_error(tcx, guar)
+                    } else {
+                        hir_ty
+                    }
                 }
             }
-        }
+            Err(guar) => Ty::new_error(tcx, guar),
+        },
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index 53866aa27b1..951eda72ffe 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -80,7 +80,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
     }
 
     fn visit_region(&mut self, r: ty::Region<'tcx>) {
-        if let ty::ReEarlyParam(data) = *r {
+        if let ty::ReEarlyParam(data) = r.kind() {
             self.parameters.push(Parameter::from(data));
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index f2560f22874..e6090a128b1 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1707,3 +1707,11 @@ pub(crate) enum SupertraitItemShadowee {
         traits: DiagSymbolList,
     },
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_self_in_type_alias, code = E0411)]
+pub(crate) struct SelfInTypeAlias {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index c3bb860538e..55087d1f400 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -43,12 +43,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     }
 
     /// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds
-    /// or associative items.
+    /// or associated items.
     ///
     /// To keep backward compatibility with existing code, `experimental_default_bounds` bounds
     /// should be added everywhere, including super bounds. However this causes a huge performance
     /// costs. For optimization purposes instead of adding default supertraits, bounds
-    /// are added to the associative items:
+    /// are added to the associated items:
     ///
     /// ```ignore(illustrative)
     /// // Default bounds are generated in the following way:
@@ -81,7 +81,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     ///
     /// Therefore, `experimental_default_bounds` are still being added to supertraits if
     /// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header.
-    pub(crate) fn requires_default_supertraits(
+    fn requires_default_supertraits(
         &self,
         hir_bounds: &'tcx [hir::GenericBound<'tcx>],
         hir_generics: &'tcx hir::Generics<'tcx>,
@@ -120,6 +120,43 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         found
     }
 
+    /// Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if
+    /// they are not added as super trait bounds to the trait itself. See
+    /// `requires_default_supertraits` for more information.
+    pub(crate) fn add_default_trait_item_bounds(
+        &self,
+        trait_item: &hir::TraitItem<'tcx>,
+        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
+    ) {
+        let tcx = self.tcx();
+        if !tcx.sess.opts.unstable_opts.experimental_default_bounds {
+            return;
+        }
+
+        let parent = tcx.local_parent(trait_item.hir_id().owner.def_id);
+        let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else {
+            unreachable!();
+        };
+
+        let (trait_generics, trait_bounds) = match parent_trait.kind {
+            hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits),
+            hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
+            _ => unreachable!(),
+        };
+
+        if !self.requires_default_supertraits(trait_bounds, trait_generics) {
+            let self_ty_where_predicates = (parent, trait_item.generics.predicates);
+            self.add_default_traits_with_filter(
+                bounds,
+                tcx.types.self_param,
+                &[],
+                Some(self_ty_where_predicates),
+                trait_item.span,
+                |tr| tr != hir::LangItem::Sized,
+            );
+        }
+    }
+
     /// Lazily sets `experimental_default_bounds` to true on trait super bounds.
     /// See `requires_default_supertraits` for more information.
     pub(crate) fn add_default_super_traits(
@@ -130,6 +167,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         hir_generics: &'tcx hir::Generics<'tcx>,
         span: Span,
     ) {
+        if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds {
+            return;
+        }
+
         assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias));
         if self.requires_default_supertraits(hir_bounds, hir_generics) {
             let self_ty_where_predicates = (trait_def_id, hir_generics.predicates);
@@ -263,11 +304,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 seen_unbound = true;
             }
             let emit_relax_err = || {
-                let unbound_traits =
-                    match self.tcx().sess.opts.unstable_opts.experimental_default_bounds {
-                        true => "`?Sized` and `experimental_default_bounds`",
-                        false => "`?Sized`",
-                    };
+                let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds {
+                    true => "`?Sized` and `experimental_default_bounds`",
+                    false => "`?Sized`",
+                };
                 // There was a `?Trait` bound, but it was neither `?Sized` nor `experimental_default_bounds`.
                 tcx.dcx().span_err(
                     unbound.span,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index aeebe45f881..e64cd8ec302 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -16,6 +16,7 @@ use smallvec::{SmallVec, smallvec};
 use tracing::{debug, instrument};
 
 use super::HirTyLowerer;
+use crate::errors::SelfInTypeAlias;
 use crate::hir_ty_lowering::{
     GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason,
 };
@@ -125,6 +126,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         // ```
         let mut projection_bounds = FxIndexMap::default();
         for (proj, proj_span) in elaborated_projection_bounds {
+            let proj = proj.map_bound(|mut b| {
+                if let Some(term_ty) = &b.term.as_type() {
+                    let references_self = term_ty.walk().any(|arg| arg == dummy_self.into());
+                    if references_self {
+                        // With trait alias and type alias combined, type resolver
+                        // may not be able to catch all illegal `Self` usages (issue 139082)
+                        let guar = tcx.dcx().emit_err(SelfInTypeAlias { span });
+                        b.term = replace_dummy_self_with_error(tcx, b.term, guar);
+                    }
+                }
+                b
+            });
+
             let key = (
                 proj.skip_binder().projection_term.def_id,
                 tcx.anonymize_bound_vars(
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index c01b81563dc..64c1a78bd1c 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -4,7 +4,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ObligationCause, WellFormedLoc};
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, TyCtxt, TypingMode, fold_regions};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode, fold_regions};
 use rustc_span::def_id::LocalDefId;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
 use tracing::debug;
@@ -77,6 +77,15 @@ fn diagnostic_hir_wf_check<'tcx>(
             let tcx_ty = fold_regions(self.tcx, tcx_ty, |r, _| {
                 if r.is_bound() { self.tcx.lifetimes.re_erased } else { r }
             });
+
+            // We may be checking the WFness of a type in an opaque with a non-lifetime bound.
+            // Perhaps we could rebind all the escaping bound vars, but they're coming from
+            // arbitrary debruijn indices and aren't particularly important anyways, since they
+            // are only coming from `feature(non_lifetime_binders)` anyways.
+            if tcx_ty.has_escaping_bound_vars() {
+                return;
+            }
+
             let cause = traits::ObligationCause::new(
                 ty.span,
                 self.def_id,
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index a0faa5e8429..780c27d4595 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -24,8 +24,8 @@ pub(super) fn infer_predicates(
 
     // If new predicates were added then we need to re-calculate
     // all crates since there could be new implied predicates.
-    loop {
-        let mut predicates_added = false;
+    for i in 0.. {
+        let mut predicates_added = vec![];
 
         // Visit all the crates and infer predicates
         for id in tcx.hir_free_items() {
@@ -83,14 +83,27 @@ pub(super) fn infer_predicates(
                 .get(&item_did.to_def_id())
                 .map_or(0, |p| p.as_ref().skip_binder().len());
             if item_required_predicates.len() > item_predicates_len {
-                predicates_added = true;
+                predicates_added.push(item_did);
                 global_inferred_outlives
                     .insert(item_did.to_def_id(), ty::EarlyBinder::bind(item_required_predicates));
             }
         }
 
-        if !predicates_added {
+        if predicates_added.is_empty() {
+            // We've reached a fixed point.
             break;
+        } else if !tcx.recursion_limit().value_within_limit(i) {
+            let msg = if let &[id] = &predicates_added[..] {
+                format!("overflow computing implied lifetime bounds for `{}`", tcx.def_path_str(id),)
+            } else {
+                "overflow computing implied lifetime bounds".to_string()
+            };
+            tcx.dcx()
+                .struct_span_fatal(
+                    predicates_added.iter().map(|id| tcx.def_span(*id)).collect::<Vec<_>>(),
+                    msg,
+                )
+                .emit();
         }
     }
 
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index d0a2a2230ab..044fb64ca82 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -146,7 +146,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
 
 fn is_free_region(region: Region<'_>) -> bool {
     // First, screen for regions that might appear in a type header.
-    match *region {
+    match region.kind() {
         // These correspond to `T: 'a` relationships:
         //
         //     struct Foo<'a, T> {
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 8475903c68f..23223de918c 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -428,7 +428,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         region: ty::Region<'tcx>,
         variance: VarianceTermPtr<'a>,
     ) {
-        match *region {
+        match region.kind() {
             ty::ReEarlyParam(ref data) => {
                 self.add_constraint(current, data.index, variance);
             }
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 0800d99e945..dbba45dc7bb 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -44,13 +44,13 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
         return &[];
     }
 
-    match tcx.def_kind(item_def_id) {
+    let kind = tcx.def_kind(item_def_id);
+    match kind {
         DefKind::Fn
         | DefKind::AssocFn
         | DefKind::Enum
         | DefKind::Struct
         | DefKind::Union
-        | DefKind::Variant
         | DefKind::Ctor(..) => {
             // These are inferred.
             let crate_map = tcx.crate_variances(());
@@ -89,7 +89,11 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
     }
 
     // Variance not relevant.
-    span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item");
+    span_bug!(
+        tcx.def_span(item_def_id),
+        "asked to compute variance for {}",
+        kind.descr(item_def_id.to_def_id())
+    );
 }
 
 #[derive(Debug, Copy, Clone)]
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 8c0c17f7a7d..865209b6a96 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -960,12 +960,16 @@ impl<'a> State<'a> {
 
     fn print_local(
         &mut self,
+        super_: bool,
         init: Option<&hir::Expr<'_>>,
         els: Option<&hir::Block<'_>>,
         decl: impl Fn(&mut Self),
     ) {
         self.space_if_not_bol();
         self.ibox(INDENT_UNIT);
+        if super_ {
+            self.word_nbsp("super");
+        }
         self.word_nbsp("let");
 
         self.ibox(INDENT_UNIT);
@@ -995,7 +999,9 @@ impl<'a> State<'a> {
         self.maybe_print_comment(st.span.lo());
         match st.kind {
             hir::StmtKind::Let(loc) => {
-                self.print_local(loc.init, loc.els, |this| this.print_local_decl(loc));
+                self.print_local(loc.super_.is_some(), loc.init, loc.els, |this| {
+                    this.print_local_decl(loc)
+                });
             }
             hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)),
             hir::StmtKind::Expr(expr) => {
@@ -1488,7 +1494,7 @@ impl<'a> State<'a> {
 
                 // Print `let _t = $init;`:
                 let temp = Ident::from_str("_t");
-                self.print_local(Some(init), None, |this| this.print_ident(temp));
+                self.print_local(false, Some(init), None, |this| this.print_ident(temp));
                 self.word(";");
 
                 // Print `_t`:
@@ -1868,6 +1874,7 @@ impl<'a> State<'a> {
         // Pat isn't normalized, but the beauty of it
         // is that it doesn't matter
         match pat.kind {
+            PatKind::Missing => unreachable!(),
             PatKind::Wild => self.word("_"),
             PatKind::Never => self.word("!"),
             PatKind::Binding(BindingMode(by_ref, mutbl), _, ident, sub) => {
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index dabae7b1d09..2189fdf0f34 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -5,7 +5,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir_analysis::check::{check_function_signature, forbid_intrinsic_abi};
+use rustc_hir_analysis::check::check_function_signature;
 use rustc_infer::infer::RegionVariableOrigin;
 use rustc_infer::traits::WellFormedLoc;
 use rustc_middle::ty::{self, Binder, Ty, TyCtxt};
@@ -50,8 +50,6 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     let span = body.value.span;
 
-    forbid_intrinsic_abi(tcx, span, fn_sig.abi);
-
     GatherLocalsVisitor::new(fcx).visit_body(body);
 
     // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 467ca26e7ea..b8968b58769 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -970,7 +970,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result);
 
         // Normalize only after registering in `user_provided_sigs`.
-        self.normalize(self.tcx.hir_span(hir_id), result)
+        self.normalize(self.tcx.def_span(expr_def_id), result)
     }
 
     /// Invoked when we are translating the coroutine that results
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index f42ca3af2b3..f1571cf4c83 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -37,7 +37,6 @@
 
 use std::ops::Deref;
 
-use rustc_abi::ExternAbi;
 use rustc_attr_parsing::InlineAttr;
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, Diag, struct_span_code_err};
@@ -1240,10 +1239,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         };
         if let (Some(a_sig), Some(b_sig)) = (a_sig, b_sig) {
-            // Intrinsics are not coercible to function pointers.
-            if a_sig.abi() == ExternAbi::RustIntrinsic || b_sig.abi() == ExternAbi::RustIntrinsic {
-                return Err(TypeError::IntrinsicCast);
-            }
             // The signature must match.
             let (a_sig, b_sig) = self.normalize(new.span, (a_sig, b_sig));
             let sig = self
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index b845e2190ef..fec45995410 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -865,10 +865,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
                 vec![(
                     ty_ref.1.ty.span.shrink_to_lo(),
-                    format!(
-                        "{}mut ",
-                        if ty_ref.0.ident.span.lo() == ty_ref.0.ident.span.hi() { "" } else { " " },
-                    ),
+                    format!("{}mut ", if ty_ref.0.ident.span.is_empty() { "" } else { " " },),
                 )]
             };
             sugg.extend([
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 45ab8e03db5..3475d15e948 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -482,7 +482,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             // All of these constitute a read, or match on something that isn't `!`,
             // which would require a `NeverToAny` coercion.
-            hir::PatKind::Binding(_, _, _, _)
+            hir::PatKind::Missing
+            | hir::PatKind::Binding(_, _, _, _)
             | hir::PatKind::Struct(_, _, _)
             | hir::PatKind::TupleStruct(_, _, _)
             | hir::PatKind::Tuple(_, _)
@@ -2204,8 +2205,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let fields = listify(&missing_mandatory_fields, |f| format!("`{f}`")).unwrap();
                 self.dcx()
                     .struct_span_err(
-                        span.shrink_to_hi(),
-                        format!("missing mandatory field{s} {fields}"),
+                        span.shrink_to_lo(),
+                        format!("missing field{s} {fields} in initializer"),
+                    )
+                    .with_span_label(
+                        span.shrink_to_lo(),
+                        "fields that do not have a defaulted value must be provided explicitly",
                     )
                     .emit();
                 return;
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 64176dacb73..27df8f0e98a 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -611,6 +611,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         for pat in pats {
             self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
                 match &pat.kind {
+                    PatKind::Missing => unreachable!(),
                     PatKind::Binding(.., opt_sub_pat) => {
                         // If the opt_sub_pat is None, then the binding does not count as
                         // a wildcard for the purpose of borrowing discr.
@@ -1832,6 +1833,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
             | PatKind::Expr(..)
             | PatKind::Range(..)
             | PatKind::Never
+            | PatKind::Missing
             | PatKind::Wild
             | PatKind::Err(_) => {
                 // always ok
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 48fd5f1f982..5d87e800096 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -43,7 +43,7 @@ pub(super) struct Declaration<'a> {
 
 impl<'a> From<&'a hir::LetStmt<'a>> for Declaration<'a> {
     fn from(local: &'a hir::LetStmt<'a>) -> Self {
-        let hir::LetStmt { hir_id, pat, ty, span, init, els, source: _ } = *local;
+        let hir::LetStmt { hir_id, super_: _, pat, ty, span, init, els, source: _ } = *local;
         Declaration { hir_id, pat, ty, span, init, origin: DeclOrigin::LocalDecl { els } }
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 46389668de7..1d86ff14471 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -117,7 +117,7 @@ fn typeck_with_inspect<'tcx>(
 
     let id = tcx.local_def_id_to_hir_id(def_id);
     let node = tcx.hir_node(id);
-    let span = tcx.hir_span(id);
+    let span = tcx.def_span(def_id);
 
     // Figure out what primary body this item has.
     let body_id = node.body_id().unwrap_or_else(|| {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 246b23f11b6..8be4d55542d 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -25,6 +25,7 @@ use rustc_middle::bug;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type};
 use rustc_middle::ty::print::{
     PrintTraitRefExt as _, with_crate_prefix, with_forced_trimmed_paths,
+    with_no_visible_paths_if_doc_hidden,
 };
 use rustc_middle::ty::{self, GenericArgKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::DefIdSet;
@@ -3328,7 +3329,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let path_strings = candidates.iter().map(|trait_did| {
                 format!(
                     "{prefix}{}{postfix}\n",
-                    with_crate_prefix!(self.tcx.def_path_str(*trait_did)),
+                    with_no_visible_paths_if_doc_hidden!(with_crate_prefix!(
+                        self.tcx.def_path_str(*trait_did)
+                    )),
                 )
             });
 
@@ -3336,7 +3339,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let parent_did = parent_map.get(trait_did).unwrap();
                 format!(
                     "{prefix}{}::*{postfix} // trait {}\n",
-                    with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
+                    with_no_visible_paths_if_doc_hidden!(with_crate_prefix!(
+                        self.tcx.def_path_str(*parent_did)
+                    )),
                     self.tcx.item_name(*trait_did),
                 )
             });
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 9766ceda569..8641348bffb 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -341,7 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         let ty = match pat.kind {
-            PatKind::Wild | PatKind::Err(_) => expected,
+            PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected,
             // We allow any type here; we ensure that the type is uninhabited during match checking.
             PatKind::Never => expected,
             PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
@@ -505,9 +505,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             },
 
             // Ref patterns are complicated, we handle them in `check_pat_ref`.
-            PatKind::Ref(..) => AdjustMode::Pass,
+            PatKind::Ref(..)
+            // No need to do anything on a missing pattern.
+            | PatKind::Missing
             // A `_` pattern works with any expected type, so there's no need to do anything.
-            PatKind::Wild
+            | PatKind::Wild
             // A malformed pattern doesn't have an expected type, so let's just accept any type.
             | PatKind::Err(_)
             // Bindings also work with whatever the expected type is,
@@ -1032,7 +1034,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         | PatKind::Tuple(..)
                         | PatKind::Slice(..) => "binding",
 
-                        PatKind::Wild
+                        PatKind::Missing
+                        | PatKind::Wild
                         | PatKind::Never
                         | PatKind::Binding(..)
                         | PatKind::Box(..)
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 307110d9fbc..a1a0926cd81 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -159,7 +159,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
     ) -> ty::Region<'tcx> {
         let infcx = canonicalizer.infcx.unwrap();
 
-        if let ty::ReVar(vid) = *r {
+        if let ty::ReVar(vid) = r.kind() {
             r = infcx
                 .inner
                 .borrow_mut()
@@ -171,7 +171,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
             );
         };
 
-        match *r {
+        match r.kind() {
             ty::ReLateParam(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyParam(..) => r,
 
             ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region(
@@ -227,7 +227,7 @@ impl CanonicalizeMode for CanonicalizeUserTypeAnnotation {
         canonicalizer: &mut Canonicalizer<'_, 'tcx>,
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
-        match *r {
+        match r.kind() {
             ty::ReEarlyParam(_)
             | ty::ReLateParam(_)
             | ty::ReErased
@@ -321,7 +321,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
+        match r.kind() {
             ty::ReBound(index, ..) => {
                 if index >= self.binder_index {
                     bug!("escaping late-bound region during canonicalization");
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index d53f631cc07..5220071c500 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -432,7 +432,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 }
                 GenericArgKind::Lifetime(result_value) => {
                     // e.g., here `result_value` might be `'?1` in the example above...
-                    if let ty::ReBound(debruijn, br) = *result_value {
+                    if let ty::ReBound(debruijn, br) = result_value.kind() {
                         // ... in which case we would set `canonical_vars[0]` to `Some('static)`.
 
                         // We only allow a `ty::INNERMOST` index in generic parameters.
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index f2bb66ff736..cae674165f0 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -109,7 +109,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
+        match r.kind() {
             ty::ReBound(..) => {
                 // leave bound regions alone
                 r
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 91595de97f7..e3522137d83 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -218,7 +218,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                                 true
                             }
                             VarValue::Value(cur_region) => {
-                                match *cur_region {
+                                match cur_region.kind() {
                                     // If this empty region is from a universe that can name the
                                     // placeholder universe, then the LUB is the Placeholder region
                                     // (which is the cur_region). Otherwise, the LUB is the Static
@@ -310,7 +310,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
 
         match *b_data {
             VarValue::Empty(empty_ui) => {
-                let lub = match *a_region {
+                let lub = match a_region.kind() {
                     RePlaceholder(placeholder) => {
                         // If this empty region is from a universe that can
                         // name the placeholder, then the placeholder is
@@ -350,7 +350,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 // tighter bound than `'static`.
                 //
                 // (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.)
-                if let ty::RePlaceholder(p) = *lub
+                if let ty::RePlaceholder(p) = lub.kind()
                     && b_universe.cannot_name(p.universe)
                 {
                     lub = self.tcx().lifetimes.re_static;
@@ -377,7 +377,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 a_ui.min(b_ui) == b_ui
             }
             (VarValue::Value(a), VarValue::Empty(_)) => {
-                match *a {
+                match a.kind() {
                     // this is always on an error path,
                     // so it doesn't really matter if it's shorter or longer than an empty region
                     ReError(_) => false,
@@ -410,7 +410,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 }
             }
             (VarValue::Empty(a_ui), VarValue::Value(b)) => {
-                match *b {
+                match b.kind() {
                     // this is always on an error path,
                     // so it doesn't really matter if it's shorter or longer than an empty region
                     ReError(_) => false,
@@ -479,7 +479,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
     /// term "concrete regions").
     #[instrument(level = "trace", skip(self), ret)]
     fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
-        match (*a, *b) {
+        match (a.kind(), b.kind()) {
             (ReBound(..), _) | (_, ReBound(..)) | (ReErased, _) | (_, ReErased) => {
                 bug!("cannot relate region: LUB({:?}, {:?})", a, b);
             }
@@ -725,7 +725,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         // SubSupConflict(ReLateParam, ReLateParam) when reporting error, and so
         // the user will more likely get a specific suggestion.
         fn region_order_key(x: &RegionAndOrigin<'_>) -> u8 {
-            match *x.region {
+            match x.region.kind() {
                 ReEarlyParam(_) => 0,
                 ReLateParam(_) => 1,
                 _ => 2,
@@ -737,7 +737,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         let node_universe = self.var_infos[node_idx].universe;
 
         for lower_bound in &lower_bounds {
-            let effective_lower_bound = if let ty::RePlaceholder(p) = *lower_bound.region {
+            let effective_lower_bound = if let ty::RePlaceholder(p) = lower_bound.region.kind() {
                 if node_universe.cannot_name(p.universe) {
                     self.tcx().lifetimes.re_static
                 } else {
@@ -785,7 +785,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             .expect("lower_vid_bounds should at least include `node_idx`");
 
         for upper_bound in &upper_bounds {
-            if let ty::RePlaceholder(p) = *upper_bound.region {
+            if let ty::RePlaceholder(p) = upper_bound.region.kind() {
                 if min_universe.cannot_name(p.universe) {
                     let origin = self.var_infos[node_idx].origin;
                     errors.push(RegionResolutionError::UpperBoundUniverseConflict(
@@ -913,7 +913,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         generic_ty: Ty<'tcx>,
         min: ty::Region<'tcx>,
     ) -> bool {
-        if let ty::ReError(_) = *min {
+        if let ty::ReError(_) = min.kind() {
             return true;
         }
 
@@ -931,18 +931,18 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             }
 
             VerifyBound::OutlivedBy(r) => {
-                let a = match *min {
+                let a = match min.kind() {
                     ty::ReVar(rid) => var_values.values[rid],
                     _ => VarValue::Value(min),
                 };
-                let b = match **r {
+                let b = match r.kind() {
                     ty::ReVar(rid) => var_values.values[rid],
                     _ => VarValue::Value(*r),
                 };
                 self.sub_region_values(a, b)
             }
 
-            VerifyBound::IsEmpty => match *min {
+            VerifyBound::IsEmpty => match min.kind() {
                 ty::ReVar(rid) => match var_values.values[rid] {
                     VarValue::ErrorValue => false,
                     VarValue::Empty(_) => true,
@@ -989,7 +989,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> {
         tcx: TyCtxt<'tcx>,
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
-        let result = match *r {
+        let result = match r.kind() {
             ty::ReVar(rid) => match self.values[rid] {
                 VarValue::Empty(_) => r,
                 VarValue::Value(r) => r,
diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs
index e924c974a02..cb5a33c5c97 100644
--- a/compiler/rustc_infer/src/infer/outlives/env.rs
+++ b/compiler/rustc_infer/src/infer/outlives/env.rs
@@ -69,7 +69,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
                     region_bound_pairs
                         .insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a));
                 }
-                OutlivesBound::RegionSubRegion(r_a, r_b) => match (*r_a, *r_b) {
+                OutlivesBound::RegionSubRegion(r_a, r_b) => match (r_a.kind(), r_b.kind()) {
                     (
                         ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_),
                         ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_),
diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
index 379410641fe..c44d9723f29 100644
--- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
+++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
@@ -29,7 +29,7 @@ where
     }
 
     fn visit_region(&mut self, r: ty::Region<'tcx>) {
-        match *r {
+        match r.kind() {
             // ignore bound regions, keep visiting
             ty::ReBound(_, _) => {}
             _ => (self.op)(r),
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index 3cfc58dea05..e332b6d0447 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -155,7 +155,7 @@ impl<'a, 'tcx> LeakCheck<'a, 'tcx> {
             self.scc_universes[scc].take_min(universe, *region);
 
             // Detect those SCCs that directly contain a placeholder
-            if let ty::RePlaceholder(placeholder) = **region {
+            if let ty::RePlaceholder(placeholder) = region.kind() {
                 if self.outer_universe.cannot_name(placeholder.universe) {
                     // Update `scc_placeholders` to account for the fact that `P: S` must hold.
                     match self.scc_placeholders[scc] {
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 57555db37ab..8366aa6ec42 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -463,7 +463,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         // cannot add constraints once regions are resolved
         debug!("origin = {:#?}", origin);
 
-        match (*sub, *sup) {
+        match (sub.kind(), sup.kind()) {
             (ReBound(..), _) | (_, ReBound(..)) => {
                 span_bug!(origin.span(), "cannot relate bound region: {:?} <= {:?}", sub, sup);
             }
@@ -595,7 +595,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     }
 
     pub fn universe(&mut self, region: Region<'tcx>) -> ty::UniverseIndex {
-        match *region {
+        match region.kind() {
             ty::ReStatic
             | ty::ReErased
             | ty::ReLateParam(..)
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index e16212955ff..b0ccd35e8f0 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -571,7 +571,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
         assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
 
-        match *r {
+        match r.kind() {
             // Never make variables for regions bound within the type itself,
             // nor for erased regions.
             ty::ReBound(..) | ty::ReErased => {
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 4a99c220975..245f1a4ac5e 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -89,7 +89,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticRegionResolver<'a, 'tcx
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
+        match r.kind() {
             ty::ReVar(vid) => self
                 .infcx
                 .inner
@@ -153,7 +153,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
     }
 
     fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
-        match *r {
+        match r.kind() {
             ty::ReVar(_) => Ok(self
                 .infcx
                 .lexical_region_resolutions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 747e36b6a1a..7dfad165836 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -955,7 +955,9 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
             // Run unsafety check because it's responsible for stealing and
             // deallocating THIR.
             tcx.ensure_ok().check_unsafety(def_id);
-            tcx.ensure_ok().mir_borrowck(def_id)
+            if !tcx.is_typeck_child(def_id.to_def_id()) {
+                tcx.ensure_ok().mir_borrowck(def_id)
+            }
         });
     });
     sess.time("MIR_effect_checking", || {
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index dae0efcbbc4..e65f4beab24 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -779,21 +779,19 @@ impl EarlyLintPass for AnonymousParameters {
         }
         if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind {
             for arg in sig.decl.inputs.iter() {
-                if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind {
-                    if ident.name == kw::Empty {
-                        let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);
+                if let ast::PatKind::Missing = arg.pat.kind {
+                    let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);
 
-                        let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
-                            (snip.as_str(), Applicability::MachineApplicable)
-                        } else {
-                            ("<type>", Applicability::HasPlaceholders)
-                        };
-                        cx.emit_span_lint(
-                            ANONYMOUS_PARAMETERS,
-                            arg.pat.span,
-                            BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip },
-                        );
-                    }
+                    let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
+                        (snip.as_str(), Applicability::MachineApplicable)
+                    } else {
+                        ("<type>", Applicability::HasPlaceholders)
+                    };
+                    cx.emit_span_lint(
+                        ANONYMOUS_PARAMETERS,
+                        arg.pat.span,
+                        BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip },
+                    );
                 }
             }
         }
@@ -1990,7 +1988,7 @@ impl ExplicitOutlivesRequirements {
 
         inferred_outlives
             .filter_map(|(clause, _)| match clause.kind().skip_binder() {
-                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
+                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match a.kind() {
                     ty::ReEarlyParam(ebr)
                         if item_generics.region_param(ebr, tcx).def_id == lifetime.to_def_id() =>
                     {
@@ -2040,7 +2038,7 @@ impl ExplicitOutlivesRequirements {
                 let is_inferred = match tcx.named_bound_var(lifetime.hir_id) {
                     Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives
                         .iter()
-                        .any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id.to_def_id() })),
+                        .any(|r| matches!(r.kind(), ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id.to_def_id() })),
                     _ => false,
                 };
 
diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
index 26481b97076..f1dc420aa3c 100644
--- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs
+++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
@@ -461,7 +461,7 @@ fn extract_def_id_from_arg<'tcx>(
     arg: ty::GenericArg<'tcx>,
 ) -> DefId {
     match arg.unpack() {
-        ty::GenericArgKind::Lifetime(re) => match *re {
+        ty::GenericArgKind::Lifetime(re) => match re.kind() {
             ty::ReEarlyParam(ebr) => generics.region_param(ebr, tcx).def_id,
             ty::ReBound(
                 _,
@@ -530,7 +530,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> {
         a: ty::Region<'tcx>,
         _: ty::Region<'tcx>,
     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        let def_id = match *a {
+        let def_id = match a.kind() {
             ty::ReEarlyParam(ebr) => self.generics.region_param(ebr, self.tcx).def_id,
             ty::ReBound(
                 _,
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index f1fe07cfcfa..d0b1e7bf255 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -1,10 +1,11 @@
 use rustc_ast::attr::AttributeExt;
 use rustc_ast_pretty::pprust;
-use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
+use rustc_data_structures::unord::UnordSet;
 use rustc_errors::{Diag, LintDiagnostic, MultiSpan};
 use rustc_feature::{Features, GateIssue};
+use rustc_hir::HirId;
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{CRATE_HIR_ID, HirId};
 use rustc_index::IndexVec;
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
@@ -115,12 +116,11 @@ impl LintLevelSets {
     }
 }
 
-fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LintId> {
+fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> UnordSet<LintId> {
     let store = unerased_lint_store(&tcx.sess);
+    let root_map = tcx.shallow_lint_levels_on(hir::CRATE_OWNER_ID);
 
-    let map = tcx.shallow_lint_levels_on(rustc_hir::CRATE_OWNER_ID);
-
-    let dont_need_to_run: FxIndexSet<LintId> = store
+    let mut dont_need_to_run: FxHashSet<LintId> = store
         .get_lints()
         .into_iter()
         .filter(|lint| {
@@ -129,24 +129,31 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LintId> {
                 lint.future_incompatible.is_some_and(|fut| fut.reason.has_future_breakage());
             !has_future_breakage && !lint.eval_always
         })
-        .filter_map(|lint| {
-            let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID);
-            if matches!(lint_level.level, Level::Allow)
-                || (matches!(lint_level.src, LintLevelSource::Default))
-                    && lint.default_level(tcx.sess.edition()) == Level::Allow
-            {
-                Some(LintId::of(lint))
-            } else {
-                None
-            }
+        .filter(|lint| {
+            let lint_level =
+                root_map.lint_level_id_at_node(tcx, LintId::of(lint), hir::CRATE_HIR_ID);
+            // Only include lints that are allowed at crate root or by default.
+            matches!(lint_level.level, Level::Allow)
+                || (matches!(lint_level.src, LintLevelSource::Default)
+                    && lint.default_level(tcx.sess.edition()) == Level::Allow)
         })
+        .map(|lint| LintId::of(*lint))
         .collect();
 
-    let mut visitor = LintLevelMaximum { tcx, dont_need_to_run };
-    visitor.process_opts();
-    tcx.hir_walk_attributes(&mut visitor);
+    for owner in tcx.hir_crate_items(()).owners() {
+        let map = tcx.shallow_lint_levels_on(owner);
+
+        // All lints that appear with a non-allow level must be run.
+        for (_, specs) in map.specs.iter() {
+            for (lint, level_and_source) in specs.iter() {
+                if !matches!(level_and_source.level, Level::Allow) {
+                    dont_need_to_run.remove(lint);
+                }
+            }
+        }
+    }
 
-    visitor.dont_need_to_run
+    dont_need_to_run.into()
 }
 
 #[instrument(level = "trace", skip(tcx), ret)]
@@ -340,76 +347,6 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {
     }
 }
 
-/// Visitor with the only function of visiting every item-like in a crate and
-/// computing the highest level that every lint gets put to.
-///
-/// E.g., if a crate has a global #![allow(lint)] attribute, but a single item
-/// uses #[warn(lint)], this visitor will set that lint level as `Warn`
-struct LintLevelMaximum<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    /// The actual list of detected lints.
-    dont_need_to_run: FxIndexSet<LintId>,
-}
-
-impl<'tcx> LintLevelMaximum<'tcx> {
-    fn process_opts(&mut self) {
-        let store = unerased_lint_store(self.tcx.sess);
-        for (lint_group, level) in &self.tcx.sess.opts.lint_opts {
-            if *level != Level::Allow {
-                let Ok(lints) = store.find_lints(lint_group) else {
-                    return;
-                };
-                for lint in lints {
-                    self.dont_need_to_run.swap_remove(&lint);
-                }
-            }
-        }
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> {
-    type NestedFilter = nested_filter::All;
-
-    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
-        self.tcx
-    }
-
-    /// FIXME(blyxyas): In a future revision, we should also graph #![allow]s,
-    /// but that is handled with more care
-    fn visit_attribute(&mut self, attribute: &'tcx hir::Attribute) {
-        if matches!(
-            Level::from_attr(attribute),
-            Some((Level::Warn | Level::Deny | Level::Forbid | Level::Expect | Level::ForceWarn, _))
-        ) {
-            let store = unerased_lint_store(self.tcx.sess);
-            // Lint attributes are always a metalist inside a
-            // metalist (even with just one lint).
-            let Some(meta_item_list) = attribute.meta_item_list() else { return };
-
-            for meta_list in meta_item_list {
-                // Convert Path to String
-                let Some(meta_item) = meta_list.meta_item() else { return };
-                let ident: &str = &meta_item
-                    .path
-                    .segments
-                    .iter()
-                    .map(|segment| segment.ident.as_str())
-                    .collect::<Vec<&str>>()
-                    .join("::");
-                let Ok(lints) = store.find_lints(
-                    // Lint attributes can only have literals
-                    ident,
-                ) else {
-                    return;
-                };
-                for lint in lints {
-                    self.dont_need_to_run.swap_remove(&lint);
-                }
-            }
-        }
-    }
-}
-
 pub struct LintLevelsBuilder<'s, P> {
     sess: &'s Session,
     features: &'s Features,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 55d010e6d34..51214c8e8a4 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -513,7 +513,7 @@ impl Subdiagnostic for BuiltinClashingExternSub<'_> {
         expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false);
         let mut found_str = DiagStyledString::new();
         found_str.push(self.found.fn_sig(self.tcx).to_string(), true);
-        diag.note_expected_found(&"", expected_str, &"", found_str);
+        diag.note_expected_found("", expected_str, "", found_str);
     }
 }
 
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 7b43aac90c7..806bca78f78 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1201,7 +1201,8 @@ impl EarlyLintPass for UnusedParens {
             // Do not lint on `(..)` as that will result in the other arms being useless.
             Paren(_)
             // The other cases do not contain sub-patterns.
-            | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {},
+            | Missing | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None)
+            | Path(..) | Err(_) => {},
             // These are list-like patterns; parens can always be removed.
             TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
                 self.check_unused_parens_pat(cx, p, false, false, keep_space);
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 130a425e9c7..cfb0de8475c 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -207,7 +207,7 @@ impl<'tcx> Collector<'tcx> {
 
         let sess = self.tcx.sess;
 
-        if matches!(abi, ExternAbi::Rust | ExternAbi::RustIntrinsic) {
+        if matches!(abi, ExternAbi::Rust) {
             return;
         }
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 167122a9793..55bb984c5b6 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1099,7 +1099,6 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
         DefKind::Struct
         | DefKind::Union
         | DefKind::Enum
-        | DefKind::Variant
         | DefKind::OpaqueTy
         | DefKind::Fn
         | DefKind::Ctor(..)
@@ -1109,6 +1108,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
             matches!(tcx.opt_rpitit_info(def_id), Some(ty::ImplTraitInTraitData::Trait { .. }))
         }
         DefKind::Mod
+        | DefKind::Variant
         | DefKind::Field
         | DefKind::AssocConst
         | DefKind::TyParam
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index aef56ea46e9..98273a05446 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -28,7 +28,7 @@ macro_rules! arena_types {
                     rustc_middle::mir::Body<'tcx>
                 >,
             [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>,
-            [decode] borrowck_result: rustc_middle::mir::BorrowCheckResult<'tcx>,
+            [decode] borrowck_result: rustc_middle::mir::ConcreteOpaqueTypes<'tcx>,
             [] resolver: rustc_data_structures::steal::Steal<(
                 rustc_middle::ty::ResolverAstLowering,
                 std::sync::Arc<rustc_ast::Crate>,
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 5a9fe10938a..3fc05f2caf2 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -6,14 +6,13 @@ use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::LocalDefId;
+use rustc_index::IndexVec;
 use rustc_index::bit_set::BitMatrix;
-use rustc_index::{Idx, IndexVec};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 use rustc_span::{Span, Symbol};
-use smallvec::SmallVec;
 
 use super::{ConstValue, SourceInfo};
-use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt, fold_regions};
+use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty};
 
 rustc_index::newtype_index! {
     #[derive(HashStable)]
@@ -85,16 +84,11 @@ impl Debug for CoroutineLayout<'_> {
     }
 }
 
-#[derive(Debug, TyEncodable, TyDecodable, HashStable)]
-pub struct BorrowCheckResult<'tcx> {
-    /// All the opaque types that are restricted to concrete types
-    /// by this function. Unlike the value in `TypeckResults`, this has
-    /// unerased regions.
-    pub concrete_opaque_types: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
-    pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
-    pub used_mut_upvars: SmallVec<[FieldIdx; 8]>,
-    pub tainted_by_errors: Option<ErrorGuaranteed>,
-}
+/// All the opaque types that are restricted to concrete types
+/// by this function. Unlike the value in `TypeckResults`, this has
+/// unerased regions.
+#[derive(Default, Debug, TyEncodable, TyDecodable, HashStable)]
+pub struct ConcreteOpaqueTypes<'tcx>(pub FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>);
 
 /// The result of the `mir_const_qualif` query.
 ///
@@ -108,84 +102,6 @@ pub struct ConstQualifs {
     pub needs_non_const_drop: bool,
     pub tainted_by_errors: Option<ErrorGuaranteed>,
 }
-
-/// After we borrow check a closure, we are left with various
-/// requirements that we have inferred between the free regions that
-/// appear in the closure's signature or on its field types. These
-/// requirements are then verified and proved by the closure's
-/// creating function. This struct encodes those requirements.
-///
-/// The requirements are listed as being between various `RegionVid`. The 0th
-/// region refers to `'static`; subsequent region vids refer to the free
-/// regions that appear in the closure (or coroutine's) type, in order of
-/// appearance. (This numbering is actually defined by the `UniversalRegions`
-/// struct in the NLL region checker. See for example
-/// `UniversalRegions::closure_mapping`.) Note the free regions in the
-/// closure's signature and captures are erased.
-///
-/// Example: If type check produces a closure with the closure args:
-///
-/// ```text
-/// ClosureArgs = [
-///     'a,                                         // From the parent.
-///     'b,
-///     i8,                                         // the "closure kind"
-///     for<'x> fn(&'<erased> &'x u32) -> &'x u32,  // the "closure signature"
-///     &'<erased> String,                          // some upvar
-/// ]
-/// ```
-///
-/// We would "renumber" each free region to a unique vid, as follows:
-///
-/// ```text
-/// ClosureArgs = [
-///     '1,                                         // From the parent.
-///     '2,
-///     i8,                                         // the "closure kind"
-///     for<'x> fn(&'3 &'x u32) -> &'x u32,         // the "closure signature"
-///     &'4 String,                                 // some upvar
-/// ]
-/// ```
-///
-/// Now the code might impose a requirement like `'1: '2`. When an
-/// instance of the closure is created, the corresponding free regions
-/// can be extracted from its type and constrained to have the given
-/// outlives relationship.
-#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
-pub struct ClosureRegionRequirements<'tcx> {
-    /// The number of external regions defined on the closure. In our
-    /// example above, it would be 3 -- one for `'static`, then `'1`
-    /// and `'2`. This is just used for a sanity check later on, to
-    /// make sure that the number of regions we see at the callsite
-    /// matches.
-    pub num_external_vids: usize,
-
-    /// Requirements between the various free regions defined in
-    /// indices.
-    pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
-}
-
-/// Indicates an outlives-constraint between a type or between two
-/// free regions declared on the closure.
-#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
-pub struct ClosureOutlivesRequirement<'tcx> {
-    // This region or type ...
-    pub subject: ClosureOutlivesSubject<'tcx>,
-
-    // ... must outlive this one.
-    pub outlived_free_region: ty::RegionVid,
-
-    // If not, report an error here ...
-    pub blame_span: Span,
-
-    // ... due to this reason.
-    pub category: ConstraintCategory<'tcx>,
-}
-
-// Make sure this enum doesn't unintentionally grow
-#[cfg(target_pointer_width = "64")]
-rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
-
 /// Outlives-constraints can be categorized to determine whether and why they
 /// are interesting (for error reporting). Order of variants indicates sort
 /// order of the category, thereby influencing diagnostic output.
@@ -253,66 +169,6 @@ pub enum AnnotationSource {
     GenericArg,
 }
 
-/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
-/// that must outlive some region.
-#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
-pub enum ClosureOutlivesSubject<'tcx> {
-    /// Subject is a type, typically a type parameter, but could also
-    /// be a projection. Indicates a requirement like `T: 'a` being
-    /// passed to the caller, where the type here is `T`.
-    Ty(ClosureOutlivesSubjectTy<'tcx>),
-
-    /// Subject is a free region from the closure. Indicates a requirement
-    /// like `'a: 'b` being passed to the caller; the region here is `'a`.
-    Region(ty::RegionVid),
-}
-
-/// Represents a `ty::Ty` for use in [`ClosureOutlivesSubject`].
-///
-/// This abstraction is necessary because the type may include `ReVar` regions,
-/// which is what we use internally within NLL code, and they can't be used in
-/// a query response.
-///
-/// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this
-/// type is not recognized as a binder for late-bound region.
-#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
-pub struct ClosureOutlivesSubjectTy<'tcx> {
-    inner: Ty<'tcx>,
-}
-
-impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
-    /// All regions of `ty` must be of kind `ReVar` and must represent
-    /// universal regions *external* to the closure.
-    pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
-        let inner = fold_regions(tcx, ty, |r, depth| match r.kind() {
-            ty::ReVar(vid) => {
-                let br = ty::BoundRegion {
-                    var: ty::BoundVar::new(vid.index()),
-                    kind: ty::BoundRegionKind::Anon,
-                };
-                ty::Region::new_bound(tcx, depth, br)
-            }
-            _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
-        });
-
-        Self { inner }
-    }
-
-    pub fn instantiate(
-        self,
-        tcx: TyCtxt<'tcx>,
-        mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>,
-    ) -> Ty<'tcx> {
-        fold_regions(tcx, self.inner, |r, depth| match r.kind() {
-            ty::ReBound(debruijn, br) => {
-                debug_assert_eq!(debruijn, depth);
-                map(ty::RegionVid::new(br.var.index()))
-            }
-            _ => bug!("unexpected region {r:?}"),
-        })
-    }
-}
-
 /// The constituent parts of a mir constant of kind ADT or array.
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct DestructuredConstant<'tcx> {
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 707c8d04d55..ff9d32ebb71 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -652,6 +652,8 @@ pub enum CallSource {
     /// Other types of desugaring that did not come from the HIR, but we don't care about
     /// for diagnostics (yet).
     Misc,
+    /// Use of value, generating a clone function call
+    Use,
     /// Normal function call, no special source
     Normal,
 }
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index b2c51ad8864..82e8422c52d 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -454,7 +454,7 @@ mod helper {
         /// Like [`SwitchTargets::target_for_value`], but returning the same type as
         /// [`Terminator::successors`].
         #[inline]
-        #[cfg_attr(not(bootstrap), define_opaque(Successors))]
+        #[define_opaque(Successors)]
         pub fn successors_for_value(&self, value: u128) -> Successors<'_> {
             let target = self.target_for_value(value);
             (&[]).into_iter().copied().chain(Some(target))
@@ -463,7 +463,7 @@ mod helper {
 
     impl<'tcx> TerminatorKind<'tcx> {
         #[inline]
-        #[cfg_attr(not(bootstrap), define_opaque(Successors))]
+        #[define_opaque(Successors)]
         pub fn successors(&self) -> Successors<'_> {
             use self::TerminatorKind::*;
             match *self {
@@ -502,7 +502,7 @@ mod helper {
         }
 
         #[inline]
-        #[cfg_attr(not(bootstrap), define_opaque(SuccessorsMut))]
+        #[define_opaque(SuccessorsMut)]
         pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
             use self::TerminatorKind::*;
             match *self {
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 6c6b9a5510c..5bd111fa2f2 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -25,7 +25,7 @@ pub trait EraseType: Copy {
 pub type Erase<T: EraseType> = Erased<impl Copy>;
 
 #[inline(always)]
-#[cfg_attr(not(bootstrap), define_opaque(Erase))]
+#[define_opaque(Erase)]
 pub fn erase<T: EraseType>(src: T) -> Erase<T> {
     // Ensure the sizes match
     const {
@@ -49,7 +49,7 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> {
 
 /// Restores an erased value.
 #[inline(always)]
-#[cfg_attr(not(bootstrap), define_opaque(Erase))]
+#[define_opaque(Erase)]
 pub fn restore<T: EraseType>(value: Erase<T>) -> T {
     let value: Erased<<T as EraseType>::Result> = value;
     // See comment in `erase` for why we use `transmute_unchecked`.
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 0d5fba3cc69..40d0028db86 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -484,7 +484,7 @@ rustc_queries! {
         desc { "computing `#[expect]`ed lints in this crate" }
     }
 
-    query lints_that_dont_need_to_run(_: ()) -> &'tcx FxIndexSet<LintId> {
+    query lints_that_dont_need_to_run(_: ()) -> &'tcx UnordSet<LintId> {
         arena_cache
         desc { "Computing all lints that are explicitly enabled or with a default level greater than Allow" }
     }
@@ -1026,6 +1026,13 @@ rustc_queries! {
         separate_provide_extern
     }
 
+    /// Given an `impl_def_id`, return true if the self type is guaranteed to be unsized due
+    /// to either being one of the built-in unsized types (str/slice/dyn) or to be a struct
+    /// whose tail is one of those types.
+    query impl_self_is_guaranteed_unsized(impl_def_id: DefId) -> bool {
+        desc { |tcx| "computing whether `{}` has a guaranteed unsized self type", tcx.def_path_str(impl_def_id) }
+    }
+
     /// Maps a `DefId` of a type to a list of its inherent impls.
     /// Contains implementations of methods that are inherent to a type.
     /// Methods in these implementations don't need to be exported.
@@ -1153,11 +1160,10 @@ rustc_queries! {
         return_result_from_ensure_ok
     }
 
-    /// Borrow-checks the function body. If this is a closure, returns
-    /// additional requirements that the closure's creator must verify.
-    query mir_borrowck(key: LocalDefId) -> &'tcx mir::BorrowCheckResult<'tcx> {
+    /// Borrow-checks the given typeck root, e.g. functions, const/static items,
+    /// and its children, e.g. closures, inline consts.
+    query mir_borrowck(key: LocalDefId) -> Result<&'tcx mir::ConcreteOpaqueTypes<'tcx>, ErrorGuaranteed> {
         desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) }
-        cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
     }
 
     /// Gets a complete map from all types to their inherent impls.
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 8d373cb3b30..c168142fb1e 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -747,6 +747,9 @@ pub struct Ascription<'tcx> {
 
 #[derive(Clone, Debug, HashStable, TypeVisitable)]
 pub enum PatKind<'tcx> {
+    /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`.
+    Missing,
+
     /// A wildcard pattern: `_`.
     Wild,
 
@@ -812,23 +815,17 @@ pub enum PatKind<'tcx> {
     },
 
     /// Pattern obtained by converting a constant (inline or named) to its pattern
-    /// representation using `const_to_pat`.
+    /// representation using `const_to_pat`. This is used for unsafety checking.
     ExpandedConstant {
-        /// [DefId] of the constant, we need this so that we have a
-        /// reference that can be used by unsafety checking to visit nested
-        /// unevaluated constants and for diagnostics. If the `DefId` doesn't
-        /// correspond to a local crate, it points at the `const` item.
+        /// [DefId] of the constant item.
         def_id: DefId,
-        /// If `false`, then `def_id` points at a `const` item, otherwise it
-        /// corresponds to a local inline const.
-        is_inline: bool,
-        /// If the inline constant is used in a range pattern, this subpattern
-        /// represents the range (if both ends are inline constants, there will
-        /// be multiple InlineConstant wrappers).
+        /// The pattern that the constant lowered to.
         ///
-        /// Otherwise, the actual pattern that the constant lowered to. As with
-        /// other constants, inline constants are matched structurally where
-        /// possible.
+        /// HACK: we need to keep the `DefId` of inline constants around for unsafety checking;
+        /// therefore when a range pattern contains inline constants, we re-wrap the range pattern
+        /// with the `ExpandedConstant` nodes that correspond to the range endpoints. Hence
+        /// `subpattern` may actually be a range pattern, and `def_id` be the constant for one of
+        /// its endpoints.
         subpattern: Box<Pat<'tcx>>,
     },
 
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index 7d62ab7970d..f3da2a5cc8e 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -250,7 +250,8 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>(
     mut callback: impl FnMut(&'a Pat<'tcx>),
 ) {
     match &pat.kind {
-        PatKind::Wild
+        PatKind::Missing
+        | PatKind::Wild
         | PatKind::Binding { subpattern: None, .. }
         | PatKind::Constant { value: _ }
         | PatKind::Range(_)
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 74b34afe616..23927c112bc 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -501,7 +501,7 @@ impl_decodable_via_ref! {
     &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
     &'tcx traits::ImplSource<'tcx, ()>,
     &'tcx mir::Body<'tcx>,
-    &'tcx mir::BorrowCheckResult<'tcx>,
+    &'tcx mir::ConcreteOpaqueTypes<'tcx>,
     &'tcx ty::List<ty::BoundVariableKind>,
     &'tcx ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>,
     &'tcx ty::List<FieldIdx>,
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 162ca1f4af8..abf6cbbcd87 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -437,6 +437,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         )
     }
 
+    fn impl_self_is_guaranteed_unsized(self, impl_def_id: DefId) -> bool {
+        self.impl_self_is_guaranteed_unsized(impl_def_id)
+    }
+
     fn has_target_features(self, def_id: DefId) -> bool {
         !self.codegen_fn_attrs(def_id).target_features.is_empty()
     }
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index 8bddb5c0fd7..45a0b1288db 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -65,7 +65,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
         // We must not erase bound regions. `for<'a> fn(&'a ())` and
         // `fn(&'free ())` are different types: they may implement different
         // traits and have a different `TypeId`.
-        match *r {
+        match r.kind() {
             ty::ReBound(..) => r,
             _ => self.tcx.lifetimes.re_erased,
         }
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index b0c442d28f0..2424923fb78 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -288,7 +288,7 @@ impl FlagComputation {
 
     fn add_region(&mut self, r: ty::Region<'_>) {
         self.add_flags(r.type_flags());
-        if let ty::ReBound(debruijn, _) = *r {
+        if let ty::ReBound(debruijn, _) = r.kind() {
             self.add_bound_var(debruijn);
         }
     }
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index dc2c9e3d9f1..8dc73e4ce85 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -145,10 +145,10 @@ where
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
+        match r.kind() {
             ty::ReBound(debruijn, br) if debruijn == self.current_index => {
                 let region = self.delegate.replace_region(br);
-                if let ty::ReBound(debruijn1, br) = *region {
+                if let ty::ReBound(debruijn1, br) = region.kind() {
                     // If the callback returns a bound region,
                     // that region should always use the INNERMOST
                     // debruijn index. Then we adjust it to the
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 55ebd15248c..07f2a602f2b 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -71,7 +71,7 @@ pub enum InstanceKind<'tcx> {
     /// - coroutines
     Item(DefId),
 
-    /// An intrinsic `fn` item (with `"rust-intrinsic"` ABI).
+    /// An intrinsic `fn` item (with`#[rustc_instrinsic]`).
     ///
     /// Alongside `Virtual`, this is the only `InstanceKind` that does not have its own callable MIR.
     /// Instead, codegen and const eval "magically" evaluate calls to intrinsics purely in the
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index ebb6a8c08a5..7ebfebea44e 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1265,9 +1265,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi)
         | CCmseNonSecureCall
         | CCmseNonSecureEntry
         | Unadjusted => false,
-        Rust | RustCall | RustCold | RustIntrinsic => {
-            tcx.sess.panic_strategy() == PanicStrategy::Unwind
-        }
+        Rust | RustCall | RustCold => tcx.sess.panic_strategy() == PanicStrategy::Unwind,
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index c72efde0994..9445a18ad76 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -95,7 +95,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
 
     #[instrument(skip(self), level = "debug")]
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
+        match r.kind() {
             // Ignore bound regions and `'static` regions that appear in the
             // type, we only need to remap regions that reference lifetimes
             // from the function declaration.
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 3281cb4135a..667cc5c3f0e 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -63,6 +63,7 @@ thread_local! {
     static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
     static REDUCED_QUERIES: Cell<bool> = const { Cell::new(false) };
     static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
+    static NO_VISIBLE_PATH_IF_DOC_HIDDEN: Cell<bool> = const { Cell::new(false) };
     static RTN_MODE: Cell<RtnMode> = const { Cell::new(RtnMode::ForDiagnostic) };
 }
 
@@ -134,6 +135,8 @@ define_helper!(
     /// Prevent selection of visible paths. `Display` impl of DefId will prefer
     /// visible (public) reexports of types as paths.
     fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
+    /// Prevent selection of visible paths if the paths are through a doc hidden path.
+    fn with_no_visible_paths_if_doc_hidden(NoVisibleIfDocHiddenGuard, NO_VISIBLE_PATH_IF_DOC_HIDDEN);
 );
 
 #[must_use]
@@ -569,6 +572,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             return Ok(false);
         };
 
+        if self.tcx().is_doc_hidden(visible_parent) && with_no_visible_paths_if_doc_hidden() {
+            return Ok(false);
+        }
+
         let actual_parent = self.tcx().opt_parent(def_id);
         debug!(
             "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}",
@@ -2520,7 +2527,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
 
         let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
 
-        match *region {
+        match region.kind() {
             ty::ReEarlyParam(ref data) => data.has_name(),
 
             ty::ReLateParam(ty::LateParamRegion { kind, .. }) => kind.is_named(),
@@ -2590,7 +2597,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         // the user might want to diagnose an error, but there is basically no way
         // to fit that into a short string. Hence the recommendation to use
         // `explain_region()` or `note_and_explain_region()`.
-        match *region {
+        match region.kind() {
             ty::ReEarlyParam(data) => {
                 p!(write("{}", data.name));
                 return Ok(());
@@ -2680,7 +2687,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         let name = &mut self.name;
-        let region = match *r {
+        let region = match r.kind() {
             ty::ReBound(db, br) if db >= self.current_index => {
                 *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br))
             }
@@ -2704,7 +2711,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
             }
             _ => return r,
         };
-        if let ty::ReBound(debruijn1, br) = *region {
+        if let ty::ReBound(debruijn1, br) = region.kind() {
             assert_eq!(debruijn1, ty::INNERMOST);
             ty::Region::new_bound(self.tcx, self.current_index, br)
         } else {
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index c78306f2ca3..3e4f7a79d53 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -1,5 +1,3 @@
-use std::ops::Deref;
-
 use rustc_data_structures::intern::Interned;
 use rustc_errors::MultiSpan;
 use rustc_hir::def_id::DefId;
@@ -22,7 +20,7 @@ impl<'tcx> rustc_type_ir::inherent::IntoKind for Region<'tcx> {
     type Kind = RegionKind<'tcx>;
 
     fn kind(self) -> RegionKind<'tcx> {
-        *self
+        *self.0.0
     }
 }
 
@@ -32,7 +30,7 @@ impl<'tcx> rustc_type_ir::Flags for Region<'tcx> {
     }
 
     fn outer_exclusive_binder(&self) -> ty::DebruijnIndex {
-        match **self {
+        match self.kind() {
             ty::ReBound(debruijn, _) => debruijn.shifted_in(1),
             _ => ty::INNERMOST,
         }
@@ -163,7 +161,7 @@ impl<'tcx> Region<'tcx> {
 
     pub fn get_name(self) -> Option<Symbol> {
         if self.has_name() {
-            match *self {
+            match self.kind() {
                 ty::ReEarlyParam(ebr) => Some(ebr.name),
                 ty::ReBound(_, br) => br.kind.get_name(),
                 ty::ReLateParam(fr) => fr.kind.get_name(),
@@ -185,7 +183,7 @@ impl<'tcx> Region<'tcx> {
 
     /// Is this region named by the user?
     pub fn has_name(self) -> bool {
-        match *self {
+        match self.kind() {
             ty::ReEarlyParam(ebr) => ebr.has_name(),
             ty::ReBound(_, br) => br.kind.is_named(),
             ty::ReLateParam(fr) => fr.kind.is_named(),
@@ -199,32 +197,32 @@ impl<'tcx> Region<'tcx> {
 
     #[inline]
     pub fn is_error(self) -> bool {
-        matches!(*self, ty::ReError(_))
+        matches!(self.kind(), ty::ReError(_))
     }
 
     #[inline]
     pub fn is_static(self) -> bool {
-        matches!(*self, ty::ReStatic)
+        matches!(self.kind(), ty::ReStatic)
     }
 
     #[inline]
     pub fn is_erased(self) -> bool {
-        matches!(*self, ty::ReErased)
+        matches!(self.kind(), ty::ReErased)
     }
 
     #[inline]
     pub fn is_bound(self) -> bool {
-        matches!(*self, ty::ReBound(..))
+        matches!(self.kind(), ty::ReBound(..))
     }
 
     #[inline]
     pub fn is_placeholder(self) -> bool {
-        matches!(*self, ty::RePlaceholder(..))
+        matches!(self.kind(), ty::RePlaceholder(..))
     }
 
     #[inline]
     pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool {
-        match *self {
+        match self.kind() {
             ty::ReBound(debruijn, _) => debruijn >= index,
             _ => false,
         }
@@ -233,7 +231,7 @@ impl<'tcx> Region<'tcx> {
     pub fn type_flags(self) -> TypeFlags {
         let mut flags = TypeFlags::empty();
 
-        match *self {
+        match self.kind() {
             ty::ReVar(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
                 flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
@@ -275,14 +273,14 @@ impl<'tcx> Region<'tcx> {
 
     /// True for free regions other than `'static`.
     pub fn is_param(self) -> bool {
-        matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_))
+        matches!(self.kind(), ty::ReEarlyParam(_) | ty::ReLateParam(_))
     }
 
     /// True for free region in the current context.
     ///
     /// This is the case for `'static` and param regions.
     pub fn is_free(self) -> bool {
-        match *self {
+        match self.kind() {
             ty::ReStatic | ty::ReEarlyParam(..) | ty::ReLateParam(..) => true,
             ty::ReVar(..)
             | ty::RePlaceholder(..)
@@ -319,15 +317,6 @@ impl<'tcx> Region<'tcx> {
     }
 }
 
-impl<'tcx> Deref for Region<'tcx> {
-    type Target = RegionKind<'tcx>;
-
-    #[inline]
-    fn deref(&self) -> &RegionKind<'tcx> {
-        self.0.0
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct EarlyParamRegion {
diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs
index 4881d611c12..ce4208f2c44 100644
--- a/compiler/rustc_middle/src/ty/significant_drop_order.rs
+++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs
@@ -143,25 +143,11 @@ pub fn ty_dtor_span<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Span> {
         | ty::UnsafeBinder(_) => None,
 
         ty::Adt(adt_def, _) => {
-            let did = adt_def.did();
-            let try_local_did_span = |did: DefId| {
-                if let Some(local) = did.as_local() {
-                    tcx.source_span(local)
-                } else {
-                    tcx.def_span(did)
-                }
-            };
-            let dtor = if let Some(dtor) = tcx.adt_destructor(did) {
-                dtor.did
-            } else if let Some(dtor) = tcx.adt_async_destructor(did) {
-                return Some(tcx.source_span(dtor.impl_did));
+            if let Some(dtor) = tcx.adt_destructor(adt_def.did()) {
+                Some(tcx.def_span(tcx.parent(dtor.did)))
             } else {
-                return Some(try_local_did_span(did));
-            };
-            let def_key = tcx.def_key(dtor);
-            let Some(parent_index) = def_key.parent else { return Some(try_local_did_span(dtor)) };
-            let parent_did = DefId { index: parent_index, krate: dtor.krate };
-            Some(try_local_did_span(parent_did))
+                Some(tcx.def_span(adt_def.did()))
+            }
         }
         ty::Coroutine(did, _)
         | ty::CoroutineWitness(did, _)
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 7c437abfe24..90c6ef67fb8 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -758,7 +758,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
                             _ => false,
                         },
 
-                        GenericArgKind::Lifetime(r) => match *r {
+                        GenericArgKind::Lifetime(r) => match r.kind() {
                             ty::ReBound(debruijn, br) => {
                                 // We only allow a `ty::INNERMOST` index in generic parameters.
                                 assert_eq!(debruijn, ty::INNERMOST);
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index e4863896fc8..857b462b9eb 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -2,7 +2,7 @@
 
 use std::{fmt, iter};
 
-use rustc_abi::{ExternAbi, Float, Integer, IntegerType, Size};
+use rustc_abi::{Float, Integer, IntegerType, Size};
 use rustc_apfloat::Float as _;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -1719,10 +1719,7 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 /// the compiler to make some assumptions about its shape; if the user doesn't use a feature gate, they may
 /// cause an ICE that we otherwise may want to prevent.
 pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> {
-    if tcx.features().intrinsics()
-        && (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic)
-            || tcx.has_attr(def_id, sym::rustc_intrinsic))
-    {
+    if tcx.features().intrinsics() && tcx.has_attr(def_id, sym::rustc_intrinsic) {
         let must_be_overridden = match tcx.hir_node_by_def_id(def_id) {
             hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { has_body, .. }, .. }) => {
                 !has_body
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index e3b7a258c39..b341b30af6a 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -77,7 +77,7 @@ impl<'tcx> TyCtxt<'tcx> {
             }
 
             fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
-                match *r {
+                match r.kind() {
                     ty::ReBound(debruijn, _) if debruijn < self.outer_index => {
                         ControlFlow::Continue(())
                     }
@@ -205,7 +205,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
     }
 
     fn visit_region(&mut self, r: ty::Region<'tcx>) {
-        if let ty::ReBound(debruijn, br) = *r {
+        if let ty::ReBound(debruijn, br) = r.kind() {
             if debruijn == self.current_index {
                 self.regions.insert(br.kind);
             }
@@ -250,7 +250,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
     }
 
     fn visit_region(&mut self, r: ty::Region<'tcx>) {
-        if let ty::RePlaceholder(placeholder) = *r {
+        if let ty::RePlaceholder(placeholder) = r.kind() {
             self.max_universe = ty::UniverseIndex::from_u32(
                 self.max_universe.as_u32().max(placeholder.universe.as_u32()),
             );
diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
index 19669021eef..5918498f239 100644
--- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
@@ -145,7 +145,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
             let arm = &self.thir[*arm];
             let value = match arm.pattern.kind {
                 PatKind::Constant { value } => value,
-                PatKind::ExpandedConstant { ref subpattern, def_id: _, is_inline: false }
+                PatKind::ExpandedConstant { ref subpattern, def_id: _ }
                     if let PatKind::Constant { value } = subpattern.kind =>
                 {
                     value
diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs
index 333e69475c5..a9a07997410 100644
--- a/compiler/rustc_mir_build/src/builder/expr/into.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/into.rs
@@ -328,7 +328,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             destination,
                             target: Some(success),
                             unwind: UnwindAction::Unreachable,
-                            call_source: CallSource::Misc,
+                            call_source: CallSource::Use,
                             fn_span: expr_span,
                         },
                     );
diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
index 29d400a957b..9670c1716f5 100644
--- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
@@ -118,7 +118,7 @@ impl<'tcx> MatchPairTree<'tcx> {
         let place = place_builder.try_to_place(cx);
         let mut subpairs = Vec::new();
         let test_case = match pattern.kind {
-            PatKind::Wild | PatKind::Error(_) => None,
+            PatKind::Missing | PatKind::Wild | PatKind::Error(_) => None,
 
             PatKind::Or { ref pats } => Some(TestCase::Or {
                 pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(),
@@ -201,39 +201,10 @@ impl<'tcx> MatchPairTree<'tcx> {
                 None
             }
 
-            PatKind::ExpandedConstant { subpattern: ref pattern, def_id: _, is_inline: false } => {
+            PatKind::ExpandedConstant { subpattern: ref pattern, .. } => {
                 MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data);
                 None
             }
-            PatKind::ExpandedConstant { subpattern: ref pattern, def_id, is_inline: true } => {
-                MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data);
-
-                // Apply a type ascription for the inline constant to the value at `match_pair.place`
-                if let Some(source) = place {
-                    let span = pattern.span;
-                    let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id());
-                    let args = ty::InlineConstArgs::new(
-                        cx.tcx,
-                        ty::InlineConstArgsParts {
-                            parent_args: ty::GenericArgs::identity_for_item(cx.tcx, parent_id),
-                            ty: cx.infcx.next_ty_var(span),
-                        },
-                    )
-                    .args;
-                    let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::new(
-                        ty::UserTypeKind::TypeOf(def_id, ty::UserArgs { args, user_self_ty: None }),
-                    ));
-                    let annotation = ty::CanonicalUserTypeAnnotation {
-                        inferred_ty: pattern.ty,
-                        span,
-                        user_ty: Box::new(user_ty),
-                    };
-                    let variance = ty::Contravariant;
-                    extra_data.ascriptions.push(super::Ascription { annotation, source, variance });
-                }
-
-                None
-            }
 
             PatKind::Array { ref prefix, ref slice, ref suffix } => {
                 cx.prefix_slice_suffix(
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index 3acf2a6a2a6..977d4f3e931 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -920,6 +920,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             PatKind::Constant { .. }
             | PatKind::Range { .. }
+            | PatKind::Missing
             | PatKind::Wild
             | PatKind::Never
             | PatKind::Error(_) => {}
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 6fb9974fc8e..b6a856a6eb4 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -315,6 +315,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
     fn visit_pat(&mut self, pat: &'a Pat<'tcx>) {
         if self.in_union_destructure {
             match pat.kind {
+                PatKind::Missing => unreachable!(),
                 // binding to a variable allows getting stuff out of variable
                 PatKind::Binding { .. }
                 // match is conditional on having this value
@@ -403,9 +404,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                 visit::walk_pat(self, pat);
                 self.inside_adt = old_inside_adt;
             }
-            PatKind::ExpandedConstant { def_id, is_inline, .. } => {
+            PatKind::ExpandedConstant { def_id, .. } => {
                 if let Some(def) = def_id.as_local()
-                    && *is_inline
+                    && matches!(self.tcx.def_kind(def_id), DefKind::InlineConst)
                 {
                     self.visit_inner_body(def);
                 }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 9f5e2c06b22..78583a402fe 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -676,7 +676,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
             unpeeled_pat = subpattern;
         }
 
-        if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = unpeeled_pat.kind
+        if let PatKind::ExpandedConstant { def_id, .. } = unpeeled_pat.kind
             && let DefKind::Const = self.tcx.def_kind(def_id)
             && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
             // We filter out paths with multiple path::segments.
@@ -1296,7 +1296,8 @@ fn report_non_exhaustive_match<'p, 'tcx>(
 
     for &arm in arms {
         let arm = &thir.arms[arm];
-        if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = arm.pattern.kind
+        if let PatKind::ExpandedConstant { def_id, .. } = arm.pattern.kind
+            && !matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst)
             && let Ok(snippet) = cx.tcx.sess.source_map().span_to_snippet(arm.pattern.span)
             // We filter out paths with multiple path::segments.
             && snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 372453688d2..a40001bf745 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -182,7 +182,10 @@ impl<'tcx> ConstToPat<'tcx> {
             }
         }
 
-        inlined_const_as_pat
+        // Wrap the pattern in a marker node to indicate that it is the result of lowering a
+        // constant. This is used for diagnostics, and for unsafety checking of inline const blocks.
+        let kind = PatKind::ExpandedConstant { subpattern: inlined_const_as_pat, def_id: uv.def };
+        Box::new(Pat { kind, ty, span: self.span })
     }
 
     fn field_pats(
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index d20e051548b..73d60cf4442 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -13,14 +13,15 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::{self as hir, LangItem, RangeEnd};
 use rustc_index::Idx;
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::interpret::LitToConstInput;
 use rustc_middle::thir::{
     Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
 };
 use rustc_middle::ty::layout::IntegerExt;
-use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode};
 use rustc_middle::{bug, span_bug};
-use rustc_span::def_id::LocalDefId;
+use rustc_span::def_id::DefId;
 use rustc_span::{ErrorGuaranteed, Span};
 use tracing::{debug, instrument};
 
@@ -124,7 +125,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         expr: Option<&'tcx hir::PatExpr<'tcx>>,
         // Out-parameters collecting extra data to be reapplied by the caller
         ascriptions: &mut Vec<Ascription<'tcx>>,
-        inline_consts: &mut Vec<LocalDefId>,
+        expanded_consts: &mut Vec<DefId>,
     ) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
         let Some(expr) = expr else { return Ok(None) };
 
@@ -139,10 +140,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     ascriptions.push(ascription);
                     kind = subpattern.kind;
                 }
-                PatKind::ExpandedConstant { is_inline, def_id, subpattern } => {
-                    if is_inline {
-                        inline_consts.extend(def_id.as_local());
-                    }
+                PatKind::ExpandedConstant { def_id, subpattern } => {
+                    expanded_consts.push(def_id);
                     kind = subpattern.kind;
                 }
                 _ => break,
@@ -221,10 +220,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
         // Collect extra data while lowering the endpoints, to be reapplied later.
         let mut ascriptions = vec![];
-        let mut inline_consts = vec![];
+        let mut expanded_consts = vec![];
 
         let mut lower_endpoint =
-            |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut inline_consts);
+            |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut expanded_consts);
 
         let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
         let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
@@ -269,17 +268,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
         // constants somewhere. Have them on the range pattern.
         for ascription in ascriptions {
-            kind = PatKind::AscribeUserType {
-                ascription,
-                subpattern: Box::new(Pat { span, ty, kind }),
-            };
+            let subpattern = Box::new(Pat { span, ty, kind });
+            kind = PatKind::AscribeUserType { ascription, subpattern };
         }
-        for def in inline_consts {
-            kind = PatKind::ExpandedConstant {
-                def_id: def.to_def_id(),
-                is_inline: true,
-                subpattern: Box::new(Pat { span, ty, kind }),
-            };
+        for def_id in expanded_consts {
+            let subpattern = Box::new(Pat { span, ty, kind });
+            kind = PatKind::ExpandedConstant { def_id, subpattern };
         }
         Ok(kind)
     }
@@ -290,6 +284,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         let mut span = pat.span;
 
         let kind = match pat.kind {
+            hir::PatKind::Missing => PatKind::Missing,
+
             hir::PatKind::Wild => PatKind::Wild,
 
             hir::PatKind::Never => PatKind::Never,
@@ -567,15 +563,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         // Lower the named constant to a THIR pattern.
         let args = self.typeck_results.node_args(id);
         let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
-        let subpattern = self.const_to_pat(c, ty, id, span);
-
-        // Wrap the pattern in a marker node to indicate that it is the result
-        // of lowering a named constant. This marker is used for improved
-        // diagnostics in some situations, but has no effect at runtime.
-        let mut pattern = {
-            let kind = PatKind::ExpandedConstant { subpattern, def_id, is_inline: false };
-            Box::new(Pat { span, ty, kind })
-        };
+        let mut pattern = self.const_to_pat(c, ty, id, span);
 
         // If this is an associated constant with an explicit user-written
         // type, add an ascription node (e.g. `<Foo<'a> as MyTrait>::CONST`).
@@ -612,18 +600,37 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         let ty = tcx.typeck(def_id).node_type(block.hir_id);
 
         let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
-        let parent_args =
-            tcx.erase_regions(ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id));
+        let parent_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
         let args = ty::InlineConstArgs::new(tcx, ty::InlineConstArgsParts { parent_args, ty }).args;
 
-        debug_assert!(!args.has_free_regions());
-
         let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
-        let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span);
-
-        // Wrap the pattern in a marker node to indicate that it is the result
-        // of lowering an inline const block.
-        PatKind::ExpandedConstant { subpattern, def_id: def_id.to_def_id(), is_inline: true }
+        let c = ty::Const::new_unevaluated(self.tcx, ct);
+        let pattern = self.const_to_pat(c, ty, id, span);
+
+        // Apply a type ascription for the inline constant.
+        let annotation = {
+            let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
+            let args = ty::InlineConstArgs::new(
+                tcx,
+                ty::InlineConstArgsParts { parent_args, ty: infcx.next_ty_var(span) },
+            )
+            .args;
+            infcx.canonicalize_user_type_annotation(ty::UserType::new(ty::UserTypeKind::TypeOf(
+                def_id.to_def_id(),
+                ty::UserArgs { args, user_self_ty: None },
+            )))
+        };
+        let annotation =
+            CanonicalUserTypeAnnotation { user_ty: Box::new(annotation), span, inferred_ty: ty };
+        PatKind::AscribeUserType {
+            subpattern: pattern,
+            ascription: Ascription {
+                annotation,
+                // Note that we use `Contravariant` here. See the `variance` field documentation
+                // for details.
+                variance: ty::Contravariant,
+            },
+        }
     }
 
     /// Lowers the kinds of "expression" that can appear in a HIR pattern:
@@ -635,43 +642,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         expr: &'tcx hir::PatExpr<'tcx>,
         pat_ty: Option<Ty<'tcx>>,
     ) -> PatKind<'tcx> {
-        let (lit, neg) = match &expr.kind {
-            hir::PatExprKind::Path(qpath) => {
-                return self.lower_path(qpath, expr.hir_id, expr.span).kind;
-            }
+        match &expr.kind {
+            hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
             hir::PatExprKind::ConstBlock(anon_const) => {
-                return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
+                self.lower_inline_const(anon_const, expr.hir_id, expr.span)
             }
-            hir::PatExprKind::Lit { lit, negated } => (lit, *negated),
-        };
-
-        // We handle byte string literal patterns by using the pattern's type instead of the
-        // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
-        // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
-        // pattern's type means we'll properly translate it to a slice reference pattern. This works
-        // because slices and arrays have the same valtree representation.
-        // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if
-        // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR.
-        // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is
-        // superseded by a more general implementation of deref patterns.
-        let ct_ty = match pat_ty {
-            Some(pat_ty)
-                if let ty::Adt(def, _) = *pat_ty.kind()
-                    && self.tcx.is_lang_item(def.did(), LangItem::String) =>
-            {
-                if !self.tcx.features().string_deref_patterns() {
-                    span_bug!(
-                        expr.span,
-                        "matching on `String` went through without enabling string_deref_patterns"
-                    );
-                }
-                self.typeck_results.node_type(expr.hir_id)
+            hir::PatExprKind::Lit { lit, negated } => {
+                // We handle byte string literal patterns by using the pattern's type instead of the
+                // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
+                // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
+                // pattern's type means we'll properly translate it to a slice reference pattern. This works
+                // because slices and arrays have the same valtree representation.
+                // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if
+                // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR.
+                // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is
+                // superseded by a more general implementation of deref patterns.
+                let ct_ty = match pat_ty {
+                    Some(pat_ty)
+                        if let ty::Adt(def, _) = *pat_ty.kind()
+                            && self.tcx.is_lang_item(def.did(), LangItem::String) =>
+                    {
+                        if !self.tcx.features().string_deref_patterns() {
+                            span_bug!(
+                                expr.span,
+                                "matching on `String` went through without enabling string_deref_patterns"
+                            );
+                        }
+                        self.typeck_results.node_type(expr.hir_id)
+                    }
+                    Some(pat_ty) => pat_ty,
+                    None => self.typeck_results.node_type(expr.hir_id),
+                };
+                let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg: *negated };
+                let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
+                self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind
             }
-            Some(pat_ty) => pat_ty,
-            None => self.typeck_results.node_type(expr.hir_id),
-        };
-        let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
-        let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
-        self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind
+        }
     }
 }
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 16cef0ec3ac..37248941e2c 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -664,6 +664,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
         print_indented!(self, "kind: PatKind {", depth_lvl);
 
         match pat_kind {
+            PatKind::Missing => unreachable!(),
             PatKind::Wild => {
                 print_indented!(self, "Wild", depth_lvl + 1);
             }
@@ -740,10 +741,9 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl + 1);
             }
-            PatKind::ExpandedConstant { def_id, is_inline, subpattern } => {
+            PatKind::ExpandedConstant { def_id, subpattern } => {
                 print_indented!(self, "ExpandedConstant {", depth_lvl + 1);
                 print_indented!(self, format!("def_id: {def_id:?}"), depth_lvl + 2);
-                print_indented!(self, format!("is_inline: {is_inline:?}"), depth_lvl + 2);
                 print_indented!(self, "subpattern:", depth_lvl + 2);
                 self.print_pat(subpattern, depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl + 1);
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 68bc0ffce6b..8b8d1efbbd2 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -980,27 +980,17 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             }
         }
 
-        let tcx = self.tcx;
-        let mut projection = SmallVec::<[PlaceElem<'tcx>; 1]>::new();
-        loop {
-            if let Some(local) = self.try_as_local(copy_from_local_value, location) {
-                projection.reverse();
-                let place = Place { local, projection: tcx.mk_place_elems(projection.as_slice()) };
-                if rvalue.ty(self.local_decls, tcx) == place.ty(self.local_decls, tcx).ty {
-                    self.reused_locals.insert(local);
-                    *rvalue = Rvalue::Use(Operand::Copy(place));
-                    return Some(copy_from_value);
-                }
-                return None;
-            } else if let Value::Projection(pointer, proj) = *self.get(copy_from_local_value)
-                && let Some(proj) = self.try_as_place_elem(proj, location)
-            {
-                projection.push(proj);
-                copy_from_local_value = pointer;
-            } else {
-                return None;
+        // Allow introducing places with non-constant offsets, as those are still better than
+        // reconstructing an aggregate.
+        if let Some(place) = self.try_as_place(copy_from_local_value, location, true) {
+            if rvalue.ty(self.local_decls, self.tcx) == place.ty(self.local_decls, self.tcx).ty {
+                self.reused_locals.insert(place.local);
+                *rvalue = Rvalue::Use(Operand::Copy(place));
+                return Some(copy_from_local_value);
             }
         }
+
+        None
     }
 
     fn simplify_aggregate(
@@ -1672,14 +1662,14 @@ fn op_to_prop_const<'tcx>(
 }
 
 impl<'tcx> VnState<'_, 'tcx> {
-    /// If either [`Self::try_as_constant`] as [`Self::try_as_local`] succeeds,
+    /// If either [`Self::try_as_constant`] as [`Self::try_as_place`] succeeds,
     /// returns that result as an [`Operand`].
     fn try_as_operand(&mut self, index: VnIndex, location: Location) -> Option<Operand<'tcx>> {
         if let Some(const_) = self.try_as_constant(index) {
             Some(Operand::Constant(Box::new(const_)))
-        } else if let Some(local) = self.try_as_local(index, location) {
-            self.reused_locals.insert(local);
-            Some(Operand::Copy(local.into()))
+        } else if let Some(place) = self.try_as_place(index, location, false) {
+            self.reused_locals.insert(place.local);
+            Some(Operand::Copy(place))
         } else {
             None
         }
@@ -1712,6 +1702,35 @@ impl<'tcx> VnState<'_, 'tcx> {
         Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_ })
     }
 
+    /// Construct a place which holds the same value as `index` and for which all locals strictly
+    /// dominate `loc`. If you used this place, add its base local to `reused_locals` to remove
+    /// storage statements.
+    #[instrument(level = "trace", skip(self), ret)]
+    fn try_as_place(
+        &mut self,
+        mut index: VnIndex,
+        loc: Location,
+        allow_complex_projection: bool,
+    ) -> Option<Place<'tcx>> {
+        let mut projection = SmallVec::<[PlaceElem<'tcx>; 1]>::new();
+        loop {
+            if let Some(local) = self.try_as_local(index, loc) {
+                projection.reverse();
+                let place =
+                    Place { local, projection: self.tcx.mk_place_elems(projection.as_slice()) };
+                return Some(place);
+            } else if let Value::Projection(pointer, proj) = *self.get(index)
+                && (allow_complex_projection || proj.is_stable_offset())
+                && let Some(proj) = self.try_as_place_elem(proj, loc)
+            {
+                projection.push(proj);
+                index = pointer;
+            } else {
+                return None;
+            }
+        }
+    }
+
     /// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`,
     /// return it. If you used this local, add it to `reused_locals` to remove storage statements.
     fn try_as_local(&mut self, index: VnIndex, loc: Location) -> Option<Local> {
@@ -1762,11 +1781,12 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
             if let Some(value) = value {
                 if let Some(const_) = self.try_as_constant(value) {
                     *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_)));
-                } else if let Some(local) = self.try_as_local(value, location)
-                    && *rvalue != Rvalue::Use(Operand::Move(local.into()))
+                } else if let Some(place) = self.try_as_place(value, location, false)
+                    && *rvalue != Rvalue::Use(Operand::Move(place))
+                    && *rvalue != Rvalue::Use(Operand::Copy(place))
                 {
-                    *rvalue = Rvalue::Use(Operand::Copy(local.into()));
-                    self.reused_locals.insert(local);
+                    *rvalue = Rvalue::Use(Operand::Copy(place));
+                    self.reused_locals.insert(place.local);
                 }
             }
         }
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 6429d3f67ec..dfd07f0fb16 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -498,8 +498,11 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
     }
 
     // We only need to borrowck non-synthetic MIR.
-    let tainted_by_errors =
-        if !tcx.is_synthetic_mir(def) { tcx.mir_borrowck(def).tainted_by_errors } else { None };
+    let tainted_by_errors = if !tcx.is_synthetic_mir(def) {
+        tcx.mir_borrowck(tcx.typeck_root_def_id(def.to_def_id()).expect_local()).err()
+    } else {
+        None
+    };
 
     let is_fn_like = tcx.def_kind(def).is_fn_like();
     if is_fn_like {
@@ -795,7 +798,7 @@ fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec<Promoted, Body<'_
     }
 
     if !tcx.is_synthetic_mir(def) {
-        tcx.ensure_done().mir_borrowck(def);
+        tcx.ensure_done().mir_borrowck(tcx.typeck_root_def_id(def.to_def_id()).expect_local());
     }
     let mut promoted = tcx.mir_promoted(def).1.steal();
 
diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
index 838bfdab1ea..a484573f0d8 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
@@ -148,11 +148,7 @@ impl<'tcx> MoveCheckVisitor<'tcx> {
         span: Span,
     ) {
         let source_info = self.body.source_info(location);
-        for reported_span in &self.move_size_spans {
-            if reported_span.overlaps(span) {
-                return;
-            }
-        }
+
         let lint_root = source_info.scope.lint_root(&self.body.source_scopes);
         let Some(lint_root) = lint_root else {
             // This happens when the issue is in a function from a foreign crate that
@@ -162,13 +158,34 @@ impl<'tcx> MoveCheckVisitor<'tcx> {
             // but correct span? This would make the lint at least accept crate-level lint attributes.
             return;
         };
+
+        // If the source scope is inlined by the MIR inliner, report the lint on the call site.
+        let reported_span = self
+            .body
+            .source_scopes
+            .get(source_info.scope)
+            .and_then(|source_scope_data| source_scope_data.inlined)
+            .map(|(_, call_site)| call_site)
+            .unwrap_or(span);
+
+        for previously_reported_span in &self.move_size_spans {
+            if previously_reported_span.overlaps(reported_span) {
+                return;
+            }
+        }
+
         self.tcx.emit_node_span_lint(
             LARGE_ASSIGNMENTS,
             lint_root,
-            span,
-            LargeAssignmentsLint { span, size: too_large_size.bytes(), limit: limit as u64 },
+            reported_span,
+            LargeAssignmentsLint {
+                span: reported_span,
+                size: too_large_size.bytes(),
+                limit: limit as u64,
+            },
         );
-        self.move_size_spans.push(span);
+
+        self.move_size_spans.push(reported_span);
     }
 }
 
diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs
index f575fe03019..92cdc28a37b 100644
--- a/compiler/rustc_next_trait_solver/src/lib.rs
+++ b/compiler/rustc_next_trait_solver/src/lib.rs
@@ -6,7 +6,7 @@
 
 // tidy-alphabetical-start
 #![allow(rustc::usage_of_type_ir_inherent)]
-#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))]
+#![allow(rustc::usage_of_type_ir_traits)]
 // tidy-alphabetical-end
 
 pub mod canonicalizer;
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index de6d21da0f5..2d027f16e5d 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -134,7 +134,7 @@ where
                     // Add GAT where clauses from the trait's definition
                     // FIXME: We don't need these, since these are the type's own WF obligations.
                     ecx.add_goals(
-                        GoalSource::Misc,
+                        GoalSource::AliasWellFormed,
                         cx.own_predicates_of(goal.predicate.def_id())
                             .iter_instantiated(cx, goal.predicate.alias.args)
                             .map(|pred| goal.with(cx, pred)),
@@ -199,7 +199,7 @@ where
             // Add GAT where clauses from the trait's definition.
             // FIXME: We don't need these, since these are the type's own WF obligations.
             ecx.add_goals(
-                GoalSource::Misc,
+                GoalSource::AliasWellFormed,
                 cx.own_predicates_of(goal.predicate.def_id())
                     .iter_instantiated(cx, goal.predicate.alias.args)
                     .map(|pred| goal.with(cx, pred)),
@@ -232,7 +232,33 @@ where
             };
 
             if !cx.has_item_definition(target_item_def_id) {
-                return error_response(ecx, cx.delay_bug("missing item"));
+                // If the impl is missing an item, it's either because the user forgot to
+                // provide it, or the user is not *obligated* to provide it (because it
+                // has a trivially false `Sized` predicate). If it's the latter, we cannot
+                // delay a bug because we can have trivially false where clauses, so we
+                // treat it as rigid.
+                if cx.impl_self_is_guaranteed_unsized(impl_def_id) {
+                    match ecx.typing_mode() {
+                        ty::TypingMode::Coherence => {
+                            return ecx.evaluate_added_goals_and_make_canonical_response(
+                                Certainty::AMBIGUOUS,
+                            );
+                        }
+                        ty::TypingMode::Analysis { .. }
+                        | ty::TypingMode::Borrowck { .. }
+                        | ty::TypingMode::PostBorrowckAnalysis { .. }
+                        | ty::TypingMode::PostAnalysis => {
+                            ecx.structurally_instantiate_normalizes_to_term(
+                                goal,
+                                goal.predicate.alias,
+                            );
+                            return ecx
+                                .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
+                        }
+                    }
+                } else {
+                    return error_response(ecx, cx.delay_bug("missing item"));
+                }
             }
 
             let target_container_def_id = cx.parent(target_item_def_id);
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 9405b58ab3b..3647bf2c378 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -2987,9 +2987,7 @@ impl<'a> Parser<'a> {
                 }
                 match ty {
                     Ok(ty) => {
-                        let ident = Ident::new(kw::Empty, this.prev_token.span);
-                        let bm = BindingMode::NONE;
-                        let pat = this.mk_pat_ident(ty.span, bm, ident);
+                        let pat = this.mk_pat(ty.span, PatKind::Missing);
                         (pat, ty)
                     }
                     // If this is a C-variadic argument and we hit an error, return the error.
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 3b0861a9942..fafd1b1ae00 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -782,9 +782,16 @@ impl<'a> Parser<'a> {
             // Recovery is disabled when parsing macro arguments, so it must
             // also be disabled when reparsing pasted macro arguments,
             // otherwise we get inconsistent results (e.g. #137874).
-            let res = self.with_recovery(Recovery::Forbidden, |this| {
-                f(this).expect("failed to reparse {mv_kind:?}")
-            });
+            let res = self.with_recovery(Recovery::Forbidden, |this| f(this));
+
+            let res = match res {
+                Ok(res) => res,
+                Err(err) => {
+                    // This can occur in unusual error cases, e.g. #139445.
+                    err.delay_as_bug();
+                    return None;
+                }
+            };
 
             if let token::CloseDelim(delim) = self.token.kind
                 && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim
@@ -793,7 +800,12 @@ impl<'a> Parser<'a> {
                 self.bump();
                 Some(res)
             } else {
-                panic!("no close delim when reparsing {mv_kind:?}");
+                // This can occur when invalid syntax is passed to a decl macro. E.g. see #139248,
+                // where the reparse attempt of an invalid expr consumed the trailing invisible
+                // delimiter.
+                self.dcx()
+                    .span_delayed_bug(self.token.span, "no close delim with reparsing {mv_kind:?}");
+                None
             }
         } else {
             None
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 2cd09aa8959..e00fd40ecee 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -75,10 +75,11 @@ impl<'a> Parser<'a> {
 
         let stmt = if self.token.is_keyword(kw::Super) && self.is_keyword_ahead(1, &[kw::Let]) {
             self.collect_tokens(None, attrs, force_collect, |this, attrs| {
+                let super_span = this.token.span;
                 this.expect_keyword(exp!(Super))?;
-                this.psess.gated_spans.gate(sym::super_let, this.prev_token.span);
                 this.expect_keyword(exp!(Let))?;
-                let local = this.parse_local(attrs)?; // FIXME(mara): implement super let
+                this.psess.gated_spans.gate(sym::super_let, super_span);
+                let local = this.parse_local(Some(super_span), attrs)?;
                 let trailing = Trailing::from(capture_semi && this.token == token::Semi);
                 Ok((
                     this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)),
@@ -89,7 +90,7 @@ impl<'a> Parser<'a> {
         } else if self.token.is_keyword(kw::Let) {
             self.collect_tokens(None, attrs, force_collect, |this, attrs| {
                 this.expect_keyword(exp!(Let))?;
-                let local = this.parse_local(attrs)?;
+                let local = this.parse_local(None, attrs)?;
                 let trailing = Trailing::from(capture_semi && this.token == token::Semi);
                 Ok((
                     this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)),
@@ -294,7 +295,7 @@ impl<'a> Parser<'a> {
         force_collect: ForceCollect,
     ) -> PResult<'a, Stmt> {
         let stmt = self.collect_tokens(None, attrs, force_collect, |this, attrs| {
-            let local = this.parse_local(attrs)?;
+            let local = this.parse_local(None, attrs)?;
             // FIXME - maybe capture semicolon in recovery?
             Ok((
                 this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)),
@@ -308,8 +309,8 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a local variable declaration.
-    fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
-        let lo = self.prev_token.span;
+    fn parse_local(&mut self, super_: Option<Span>, attrs: AttrVec) -> PResult<'a, P<Local>> {
+        let lo = super_.unwrap_or(self.prev_token.span);
 
         if self.token.is_keyword(kw::Const) && self.look_ahead(1, |t| t.is_ident()) {
             self.dcx().emit_err(errors::ConstLetMutuallyExclusive { span: lo.to(self.token.span) });
@@ -411,6 +412,7 @@ impl<'a> Parser<'a> {
         };
         let hi = if self.token == token::Semi { self.token.span } else { self.prev_token.span };
         Ok(P(ast::Local {
+            super_,
             ty,
             pat,
             kind,
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 669349f3380..9161b23428a 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1598,7 +1598,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         if target == Target::ForeignMod
             && let hir::Node::Item(item) = self.tcx.hir_node(hir_id)
             && let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item
-            && !matches!(abi, ExternAbi::Rust | ExternAbi::RustIntrinsic)
+            && !matches!(abi, ExternAbi::Rust)
         {
             return;
         }
diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs
index 1278e98afcf..71815448172 100644
--- a/compiler/rustc_passes/src/input_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -295,6 +295,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         record_variants!(
             (self, p, p.kind, Some(p.hir_id), hir, Pat, PatKind),
             [
+                Missing,
                 Wild,
                 Binding,
                 Struct,
@@ -597,6 +598,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
         record_variants!(
             (self, p, p.kind, None, ast, Pat, PatKind),
             [
+                Missing,
                 Wild,
                 Ident,
                 Struct,
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index ed70d9ee91f..06eb76c30c5 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -96,7 +96,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt};
 use rustc_session::lint;
-use rustc_span::{BytePos, Span, Symbol, kw, sym};
+use rustc_span::{BytePos, Span, Symbol, sym};
 use tracing::{debug, instrument};
 
 use self::LiveNodeKind::*;
@@ -1481,9 +1481,6 @@ impl<'tcx> Liveness<'_, 'tcx> {
 
     fn should_warn(&self, var: Variable) -> Option<String> {
         let name = self.ir.variable_name(var);
-        if name == kw::Empty {
-            return None;
-        }
         let name = name.as_str();
         if name.as_bytes()[0] == b'_' {
             return None;
@@ -1655,7 +1652,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
                 // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
                 Some(mut_ty.ty.span.shrink_to_lo())
             };
-            let pre = if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " };
+            let pre = if lt.ident.span.is_empty() { "" } else { " " };
             Some(errors::UnusedAssignSuggestion {
                 ty_span,
                 pre,
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 31c4ee0fa0b..7c12f69f14c 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -1,5 +1,6 @@
 use std::fmt;
 use std::iter::once;
+use std::ops::ControlFlow;
 
 use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx};
 use rustc_arena::DroplessArena;
@@ -11,7 +12,8 @@ use rustc_middle::mir::{self, Const};
 use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary};
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{
-    self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef,
+    self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
+    TypeVisitableExt, TypeVisitor, VariantDef,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
@@ -135,11 +137,22 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
     /// Returns the hidden type corresponding to this key if the body under analysis is allowed to
     /// know it.
     fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> {
-        self.typeck_results
-            .concrete_opaque_types
-            .get(&key.def_id)
-            .map(|x| ty::EarlyBinder::bind(x.ty).instantiate(self.tcx, key.args))
+        if let Some(hidden_ty) = self.typeck_results.concrete_opaque_types.get(&key.def_id) {
+            let ty = ty::EarlyBinder::bind(hidden_ty.ty).instantiate(self.tcx, key.args);
+            if ty.visit_with(&mut RecursiveOpaque { def_id: key.def_id.into() }).is_continue() {
+                Some(ty)
+            } else {
+                // HACK: We skip revealing opaque types which recursively expand
+                // to themselves. This is because we may infer hidden types like
+                // `Opaque<T> = Opaque<Opaque<T>>` or `Opaque<T> = Opaque<(T,)>`
+                // in hir typeck.
+                None
+            }
+        } else {
+            None
+        }
     }
+
     // This can take a non-revealed `Ty` because it reveals opaques itself.
     pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
         !ty.inhabited_predicate(self.tcx).apply_revealing_opaque(
@@ -460,7 +473,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
             PatKind::AscribeUserType { subpattern, .. }
             | PatKind::ExpandedConstant { subpattern, .. } => return self.lower_pat(subpattern),
             PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
-            PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
+            PatKind::Missing | PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
                 ctor = Wildcard;
                 fields = vec![];
                 arity = 0;
@@ -1105,3 +1118,20 @@ pub fn analyze_match<'p, 'tcx>(
 
     Ok(report)
 }
+
+struct RecursiveOpaque {
+    def_id: DefId,
+}
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for RecursiveOpaque {
+    type Result = ControlFlow<()>;
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
+        if let ty::Alias(ty::Opaque, alias_ty) = t.kind() {
+            if alias_ty.def_id == self.def_id {
+                return ControlFlow::Break(());
+            }
+        }
+
+        if t.has_opaque_types() { t.super_visit_with(self) } else { ControlFlow::Continue(()) }
+    }
+}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 20e19caf909..1389e8c811e 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -4009,22 +4009,17 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             self.report_error(ident.span, error(ident));
         }
 
-        // Record as bound if it's valid:
-        let ident_valid = ident.name != kw::Empty;
-        if ident_valid {
-            bindings.last_mut().unwrap().1.insert(ident);
-        }
+        // Record as bound.
+        bindings.last_mut().unwrap().1.insert(ident);
 
         if already_bound_or {
             // `Variant1(a) | Variant2(a)`, ok
             // Reuse definition from the first `a`.
             self.innermost_rib_bindings(ValueNS)[&ident]
         } else {
+            // A completely fresh binding is added to the set.
             let res = Res::Local(pat_id);
-            if ident_valid {
-                // A completely fresh binding add to the set if it's valid.
-                self.innermost_rib_bindings(ValueNS).insert(ident, res);
-            }
+            self.innermost_rib_bindings(ValueNS).insert(ident, res);
             res
         }
     }
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
index 36b68cc1398..6e13b87c41d 100644
--- a/compiler/rustc_smir/src/rustc_internal/internal.rs
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -491,7 +491,6 @@ impl RustcInternal for Abi {
             Abi::CCmseNonSecureCall => rustc_abi::ExternAbi::CCmseNonSecureCall,
             Abi::CCmseNonSecureEntry => rustc_abi::ExternAbi::CCmseNonSecureEntry,
             Abi::System { unwind } => rustc_abi::ExternAbi::System { unwind },
-            Abi::RustIntrinsic => rustc_abi::ExternAbi::RustIntrinsic,
             Abi::RustCall => rustc_abi::ExternAbi::RustCall,
             Abi::Unadjusted => rustc_abi::ExternAbi::Unadjusted,
             Abi::RustCold => rustc_abi::ExternAbi::RustCold,
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index 1ba25aa0e97..28fc68d5e49 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -871,7 +871,6 @@ impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi {
             ExternAbi::CCmseNonSecureCall => Abi::CCmseNonSecureCall,
             ExternAbi::CCmseNonSecureEntry => Abi::CCmseNonSecureEntry,
             ExternAbi::System { unwind } => Abi::System { unwind },
-            ExternAbi::RustIntrinsic => Abi::RustIntrinsic,
             ExternAbi::RustCall => Abi::RustCall,
             ExternAbi::Unadjusted => Abi::Unadjusted,
             ExternAbi::RustCold => Abi::RustCold,
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index 1efa2fe13c5..3fcbbb0e138 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -1093,7 +1093,6 @@ pub enum Abi {
     CCmseNonSecureCall,
     CCmseNonSecureEntry,
     System { unwind: bool },
-    RustIntrinsic,
     RustCall,
     Unadjusted,
     RustCold,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 99d44bcd7eb..8edfd16016c 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -368,7 +368,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
     }
 
     fn print_region(&mut self, region: ty::Region<'_>) -> Result<(), PrintError> {
-        let i = match *region {
+        let i = match region.kind() {
             // Erased lifetimes use the index 0, for a
             // shorter mangling of `L_`.
             ty::ReErased => 0,
diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs
index 209d7483e61..c779720f97b 100644
--- a/compiler/rustc_target/src/callconv/loongarch.rs
+++ b/compiler/rustc_target/src/callconv/loongarch.rs
@@ -1,6 +1,6 @@
 use rustc_abi::{
-    BackendRepr, ExternAbi, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size,
-    TyAbiInterface, TyAndLayout, Variants,
+    BackendRepr, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size, TyAbiInterface,
+    TyAndLayout, Variants,
 };
 
 use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform};
@@ -364,15 +364,11 @@ where
     }
 }
 
-pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi)
+pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout + HasTargetSpec,
 {
-    if abi == ExternAbi::RustIntrinsic {
-        return;
-    }
-
     let grlen = cx.data_layout().pointer_size.bits();
 
     for arg in fn_abi.args.iter_mut() {
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 55e39d093e2..7ecc46cc69d 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -717,16 +717,16 @@ impl<'a, Ty> FnAbi<'a, Ty> {
         }
     }
 
-    pub fn adjust_for_rust_abi<C>(&mut self, cx: &C, abi: ExternAbi)
+    pub fn adjust_for_rust_abi<C>(&mut self, cx: &C)
     where
         Ty: TyAbiInterface<'a, C> + Copy,
         C: HasDataLayout + HasTargetSpec,
     {
         let spec = cx.target_spec();
         match &*spec.arch {
-            "x86" => x86::compute_rust_abi_info(cx, self, abi),
-            "riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi),
-            "loongarch64" => loongarch::compute_rust_abi_info(cx, self, abi),
+            "x86" => x86::compute_rust_abi_info(cx, self),
+            "riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self),
+            "loongarch64" => loongarch::compute_rust_abi_info(cx, self),
             "aarch64" => aarch64::compute_rust_abi_info(cx, self),
             _ => {}
         };
@@ -850,10 +850,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
                     //
                     // Note that the intrinsic ABI is exempt here as those are not
                     // real functions anyway, and the backend expects very specific types.
-                    if abi != ExternAbi::RustIntrinsic
-                        && spec.simd_types_indirect
-                        && !can_pass_simd_directly(arg)
-                    {
+                    if spec.simd_types_indirect && !can_pass_simd_directly(arg) {
                         arg.make_indirect();
                     }
                 }
diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs
index 7368e225efa..cd1d3cd1eee 100644
--- a/compiler/rustc_target/src/callconv/riscv.rs
+++ b/compiler/rustc_target/src/callconv/riscv.rs
@@ -5,8 +5,8 @@
 // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773
 
 use rustc_abi::{
-    BackendRepr, ExternAbi, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size,
-    TyAbiInterface, TyAndLayout, Variants,
+    BackendRepr, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size, TyAbiInterface,
+    TyAndLayout, Variants,
 };
 
 use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform};
@@ -370,15 +370,11 @@ where
     }
 }
 
-pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi)
+pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout + HasTargetSpec,
 {
-    if abi == ExternAbi::RustIntrinsic {
-        return;
-    }
-
     let xlen = cx.data_layout().pointer_size.bits();
 
     for arg in fn_abi.args.iter_mut() {
diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs
index ba3c1406211..8328f818f9b 100644
--- a/compiler/rustc_target/src/callconv/x86.rs
+++ b/compiler/rustc_target/src/callconv/x86.rs
@@ -1,6 +1,6 @@
 use rustc_abi::{
-    AddressSpace, Align, BackendRepr, ExternAbi, HasDataLayout, Primitive, Reg, RegKind,
-    TyAbiInterface, TyAndLayout,
+    AddressSpace, Align, BackendRepr, HasDataLayout, Primitive, Reg, RegKind, TyAbiInterface,
+    TyAndLayout,
 };
 
 use crate::callconv::{ArgAttribute, FnAbi, PassMode};
@@ -193,7 +193,7 @@ pub(crate) fn fill_inregs<'a, Ty, C>(
     }
 }
 
-pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi)
+pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout + HasTargetSpec,
@@ -201,10 +201,7 @@ where
     // Avoid returning floats in x87 registers on x86 as loading and storing from x87
     // registers will quiet signalling NaNs. Also avoid using SSE registers since they
     // are not always available (depending on target features).
-    if !fn_abi.ret.is_ignore()
-        // Intrinsics themselves are not "real" functions, so theres no need to change their ABIs.
-        && abi != ExternAbi::RustIntrinsic
-    {
+    if !fn_abi.ret.is_ignore() {
         let has_float = match fn_abi.ret.layout.backend_repr {
             BackendRepr::Scalar(s) => matches!(s.primitive(), Primitive::Float(_)),
             BackendRepr::ScalarPair(s1, s2) => {
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 79f73ef28b3..64171fcc7ab 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2962,14 +2962,9 @@ impl Target {
     pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
         use ExternAbi::*;
         match abi {
-            Rust
-            | C { .. }
-            | System { .. }
-            | RustIntrinsic
-            | RustCall
-            | Unadjusted
-            | Cdecl { .. }
-            | RustCold => true,
+            Rust | C { .. } | System { .. } | RustCall | Unadjusted | Cdecl { .. } | RustCold => {
+                true
+            }
             EfiApi => {
                 ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..])
             }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
index 683b5b528c6..fd2d2fa7210 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
@@ -42,7 +42,7 @@ pub fn find_param_with_region<'tcx>(
     anon_region: Region<'tcx>,
     replace_region: Region<'tcx>,
 ) -> Option<AnonymousParamInfo<'tcx>> {
-    let (id, kind) = match *anon_region {
+    let (id, kind) = match anon_region.kind() {
         ty::ReLateParam(late_param) => (late_param.scope, late_param.kind),
         ty::ReEarlyParam(ebr) => {
             let region_def = tcx.generics_of(generic_param_scope).region_param(ebr, tcx).def_id;
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index c7f0a88f951..49c6acedcfa 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -299,7 +299,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     self.tcx.param_env(generic_param_scope),
                     terr,
                 );
-                match (*sub, *sup) {
+                match (sub.kind(), sup.kind()) {
                     (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
                     (ty::RePlaceholder(_), _) => {
                         note_and_explain_region(
@@ -391,7 +391,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 })
             }
             infer::RelateParamBound(span, ty, opt_span) => {
-                let prefix = match *sub {
+                let prefix = match sub.kind() {
                     ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy,
                     _ => note_and_explain::PrefixKind::TypeOutlive,
                 };
@@ -967,7 +967,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 format!("...so that the {}", sup_trace.cause.as_requirement_str()),
             );
 
-            err.note_expected_found(&"", sup_expected, &"", sup_found);
+            err.note_expected_found("", sup_expected, "", sup_found);
             return if sub_region.is_error() | sup_region.is_error() {
                 err.delay_as_bug()
             } else {
@@ -1048,7 +1048,7 @@ pub(super) fn note_and_explain_region<'tcx>(
     suffix: &str,
     alt_span: Option<Span>,
 ) {
-    let (description, span) = match *region {
+    let (description, span) = match region.kind() {
         ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::RePlaceholder(_) | ty::ReStatic => {
             msg_span_from_named_region(tcx, generic_param_scope, region, alt_span)
         }
@@ -1085,7 +1085,7 @@ fn msg_span_from_named_region<'tcx>(
     region: ty::Region<'tcx>,
     alt_span: Option<Span>,
 ) -> (String, Option<Span>) {
-    match *region {
+    match region.kind() {
         ty::ReEarlyParam(br) => {
             let param_def_id = tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id;
             let span = tcx.def_span(param_def_id);
@@ -1185,7 +1185,7 @@ pub fn unexpected_hidden_region_diagnostic<'a, 'tcx>(
     });
 
     // Explain the region we are capturing.
-    match *hidden_region {
+    match hidden_region.kind() {
         ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => {
             // Assuming regionck succeeded (*), we ought to always be
             // capturing *some* region from the fn header, and hence it
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index bc45fc11e9b..5648021f613 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -2,6 +2,7 @@ use core::ops::ControlFlow;
 use std::borrow::Cow;
 use std::path::PathBuf;
 
+use rustc_abi::ExternAbi;
 use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::unord::UnordSet;
@@ -2799,32 +2800,57 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
 
         // Note any argument mismatches
-        let given_ty = params.skip_binder();
+        let ty::Tuple(given) = *params.skip_binder().kind() else {
+            return;
+        };
+
         let expected_ty = trait_pred.skip_binder().trait_ref.args.type_at(1);
-        if let ty::Tuple(given) = given_ty.kind()
-            && let ty::Tuple(expected) = expected_ty.kind()
-        {
-            if expected.len() != given.len() {
-                // Note number of types that were expected and given
-                err.note(
-                    format!(
-                        "expected a closure taking {} argument{}, but one taking {} argument{} was given",
-                        given.len(),
-                        pluralize!(given.len()),
-                        expected.len(),
-                        pluralize!(expected.len()),
-                    )
-                );
-            } else if !self.same_type_modulo_infer(given_ty, expected_ty) {
-                // Print type mismatch
-                let (expected_args, given_args) = self.cmp(given_ty, expected_ty);
-                err.note_expected_found(
-                    &"a closure with arguments",
-                    expected_args,
-                    &"a closure with arguments",
-                    given_args,
-                );
-            }
+        let ty::Tuple(expected) = *expected_ty.kind() else {
+            return;
+        };
+
+        if expected.len() != given.len() {
+            // Note number of types that were expected and given
+            err.note(format!(
+                "expected a closure taking {} argument{}, but one taking {} argument{} was given",
+                given.len(),
+                pluralize!(given.len()),
+                expected.len(),
+                pluralize!(expected.len()),
+            ));
+            return;
+        }
+
+        let given_ty = Ty::new_fn_ptr(
+            self.tcx,
+            params.rebind(self.tcx.mk_fn_sig(
+                given,
+                self.tcx.types.unit,
+                false,
+                hir::Safety::Safe,
+                ExternAbi::Rust,
+            )),
+        );
+        let expected_ty = Ty::new_fn_ptr(
+            self.tcx,
+            trait_pred.rebind(self.tcx.mk_fn_sig(
+                expected,
+                self.tcx.types.unit,
+                false,
+                hir::Safety::Safe,
+                ExternAbi::Rust,
+            )),
+        );
+
+        if !self.same_type_modulo_infer(given_ty, expected_ty) {
+            // Print type mismatch
+            let (expected_args, given_args) = self.cmp(expected_ty, given_ty);
+            err.note_expected_found(
+                "a closure with signature",
+                expected_args,
+                "a closure with signature",
+                given_args,
+            );
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 9f7bfe5101a..bb4aba9d29e 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -415,7 +415,7 @@ impl Subdiagnostic for RegionOriginNote<'_> {
                 label_or_note(span, fluent::trait_selection_subtype);
                 diag.arg("requirement", requirement);
 
-                diag.note_expected_found(&"", expected, &"", found);
+                diag.note_expected_found("", expected, "", found);
             }
             RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
                 // FIXME: this really should be handled at some earlier stage. Our
diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
index 46622246a17..e4ab78b6247 100644
--- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
@@ -20,7 +20,7 @@ impl<'a> DescriptionCtx<'a> {
         region: ty::Region<'tcx>,
         alt_span: Option<Span>,
     ) -> Option<Self> {
-        let (span, kind, arg) = match *region {
+        let (span, kind, arg) = match region.kind() {
             ty::ReEarlyParam(br) => {
                 let scope = tcx
                     .parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id)
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index c7b8f063196..309bf4dda3d 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -46,7 +46,7 @@ pub fn check_opaque_type_parameter_valid<'tcx>(
             GenericArgKind::Lifetime(lt) => match defining_scope_kind {
                 DefiningScopeKind::HirTypeck => continue,
                 DefiningScopeKind::MirBorrowck => {
-                    matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
+                    matches!(lt.kind(), ty::ReEarlyParam(_) | ty::ReLateParam(_))
                         || (lt.is_static() && opaque_env.param_equal_static(i))
                 }
             },
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index 3a939df25e0..9cbe4147fb4 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -291,6 +291,34 @@ impl<'tcx> BestObligation<'tcx> {
         }
     }
 
+    /// When a higher-ranked projection goal fails, check that the corresponding
+    /// higher-ranked trait goal holds or not. This is because the process of
+    /// instantiating and then re-canonicalizing the binder of the projection goal
+    /// forces us to be unable to see that the leak check failed in the nested
+    /// `NormalizesTo` goal, so we don't fall back to the rigid projection check
+    /// that should catch when a projection goal fails due to an unsatisfied trait
+    /// goal.
+    fn detect_error_in_higher_ranked_projection(
+        &mut self,
+        goal: &inspect::InspectGoal<'_, 'tcx>,
+    ) -> ControlFlow<PredicateObligation<'tcx>> {
+        let tcx = goal.infcx().tcx;
+        if let Some(projection_clause) = goal.goal().predicate.as_projection_clause()
+            && !projection_clause.bound_vars().is_empty()
+        {
+            let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx));
+            self.with_derived_obligation(self.obligation.with(tcx, pred), |this| {
+                goal.infcx().visit_proof_tree_at_depth(
+                    goal.goal().with(tcx, pred),
+                    goal.depth() + 1,
+                    this,
+                )
+            })
+        } else {
+            ControlFlow::Continue(())
+        }
+    }
+
     /// It is likely that `NormalizesTo` failed without any applicable candidates
     /// because the alias is not well-formed.
     ///
@@ -374,7 +402,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             source: CandidateSource::Impl(impl_def_id),
             result: _,
         } = candidate.kind()
-            && goal.infcx().tcx.do_not_recommend_impl(impl_def_id)
+            && tcx.do_not_recommend_impl(impl_def_id)
         {
             trace!("#[do_not_recommend] -> exit");
             return ControlFlow::Break(self.obligation.clone());
@@ -486,7 +514,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             if let Some(obligation) = goal
                 .infcx()
                 .visit_proof_tree_at_depth(
-                    goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(lhs.into())),
+                    goal.goal().with(tcx, ty::ClauseKind::WellFormed(lhs.into())),
                     goal.depth() + 1,
                     self,
                 )
@@ -496,7 +524,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             } else if let Some(obligation) = goal
                 .infcx()
                 .visit_proof_tree_at_depth(
-                    goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(rhs.into())),
+                    goal.goal().with(tcx, ty::ClauseKind::WellFormed(rhs.into())),
                     goal.depth() + 1,
                     self,
                 )
@@ -506,6 +534,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             }
         }
 
+        self.detect_error_in_higher_ranked_projection(goal)?;
+
         ControlFlow::Break(self.obligation.clone())
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 1fca2f4da7e..02521c9453d 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -382,7 +382,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                     for (new_region, old_region) in
                         iter::zip(new_args.regions(), old_args.regions())
                     {
-                        match (*new_region, *old_region) {
+                        match (new_region.kind(), old_region.kind()) {
                             // If both predicates have an `ReBound` (a HRTB) in the
                             // same spot, we do nothing.
                             (ty::ReBound(_, _), ty::ReBound(_, _)) => {}
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index bcc247ba53c..93c7dae9c5b 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -537,7 +537,7 @@ fn plug_infer_with_placeholders<'tcx>(
         }
 
         fn visit_region(&mut self, r: ty::Region<'tcx>) {
-            if let ty::ReVar(vid) = *r {
+            if let ty::ReVar(vid) = r.kind() {
                 let r = self
                     .infcx
                     .inner
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index fa6bbf1d6e5..bf9fcb0915a 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -797,7 +797,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEscapingBoundRegions<'tcx> {
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        if let ty::ReBound(debruijn, _) = *r
+        if let ty::ReBound(debruijn, _) = r.kind()
             && debruijn < self.binder
         {
             r
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 349569d750e..83591219b14 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -669,30 +669,11 @@ fn project<'cx, 'tcx>(
 
     match candidates {
         ProjectionCandidateSet::Single(candidate) => {
-            Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate)))
+            confirm_candidate(selcx, obligation, candidate)
         }
         ProjectionCandidateSet::None => {
             let tcx = selcx.tcx();
-            let term = match tcx.def_kind(obligation.predicate.def_id) {
-                DefKind::AssocTy => Ty::new_projection_from_args(
-                    tcx,
-                    obligation.predicate.def_id,
-                    obligation.predicate.args,
-                )
-                .into(),
-                DefKind::AssocConst => ty::Const::new_unevaluated(
-                    tcx,
-                    ty::UnevaluatedConst::new(
-                        obligation.predicate.def_id,
-                        obligation.predicate.args,
-                    ),
-                )
-                .into(),
-                kind => {
-                    bug!("unknown projection def-id: {}", kind.descr(obligation.predicate.def_id))
-                }
-            };
-
+            let term = obligation.predicate.to_term(tcx);
             Ok(Projected::NoProgress(term))
         }
         // Error occurred while trying to processing impls.
@@ -1244,18 +1225,16 @@ fn confirm_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTermObligation<'tcx>,
     candidate: ProjectionCandidate<'tcx>,
-) -> Progress<'tcx> {
+) -> Result<Projected<'tcx>, ProjectionError<'tcx>> {
     debug!(?obligation, ?candidate, "confirm_candidate");
-    let mut progress = match candidate {
+    let mut result = match candidate {
         ProjectionCandidate::ParamEnv(poly_projection)
-        | ProjectionCandidate::Object(poly_projection) => {
-            confirm_param_env_candidate(selcx, obligation, poly_projection, false)
-        }
-
-        ProjectionCandidate::TraitDef(poly_projection) => {
-            confirm_param_env_candidate(selcx, obligation, poly_projection, true)
-        }
-
+        | ProjectionCandidate::Object(poly_projection) => Ok(Projected::Progress(
+            confirm_param_env_candidate(selcx, obligation, poly_projection, false),
+        )),
+        ProjectionCandidate::TraitDef(poly_projection) => Ok(Projected::Progress(
+            confirm_param_env_candidate(selcx, obligation, poly_projection, true),
+        )),
         ProjectionCandidate::Select(impl_source) => {
             confirm_select_candidate(selcx, obligation, impl_source)
         }
@@ -1266,23 +1245,26 @@ fn confirm_candidate<'cx, 'tcx>(
     // with new region variables, we need to resolve them to existing variables
     // when possible for this to work. See `auto-trait-projection-recursion.rs`
     // for a case where this matters.
-    if progress.term.has_infer_regions() {
+    if let Ok(Projected::Progress(progress)) = &mut result
+        && progress.term.has_infer_regions()
+    {
         progress.term = progress.term.fold_with(&mut OpportunisticRegionResolver::new(selcx.infcx));
     }
-    progress
+
+    result
 }
 
 fn confirm_select_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTermObligation<'tcx>,
     impl_source: Selection<'tcx>,
-) -> Progress<'tcx> {
+) -> Result<Projected<'tcx>, ProjectionError<'tcx>> {
     match impl_source {
         ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
         ImplSource::Builtin(BuiltinImplSource::Misc | BuiltinImplSource::Trivial, data) => {
             let tcx = selcx.tcx();
             let trait_def_id = obligation.predicate.trait_def_id(tcx);
-            if tcx.is_lang_item(trait_def_id, LangItem::Coroutine) {
+            let progress = if tcx.is_lang_item(trait_def_id, LangItem::Coroutine) {
                 confirm_coroutine_candidate(selcx, obligation, data)
             } else if tcx.is_lang_item(trait_def_id, LangItem::Future) {
                 confirm_future_candidate(selcx, obligation, data)
@@ -1304,7 +1286,8 @@ fn confirm_select_candidate<'cx, 'tcx>(
                 confirm_async_fn_kind_helper_candidate(selcx, obligation, data)
             } else {
                 confirm_builtin_candidate(selcx, obligation, data)
-            }
+            };
+            Ok(Projected::Progress(progress))
         }
         ImplSource::Builtin(BuiltinImplSource::Object { .. }, _)
         | ImplSource::Param(..)
@@ -2000,7 +1983,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTermObligation<'tcx>,
     impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
+) -> Result<Projected<'tcx>, ProjectionError<'tcx>> {
     let tcx = selcx.tcx();
 
     let ImplSourceUserDefinedData { impl_def_id, args, mut nested } = impl_impl_source;
@@ -2011,19 +1994,33 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let param_env = obligation.param_env;
     let assoc_ty = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) {
         Ok(assoc_ty) => assoc_ty,
-        Err(guar) => return Progress::error(tcx, guar),
+        Err(guar) => return Ok(Projected::Progress(Progress::error(tcx, guar))),
     };
+
+    // This means that the impl is missing a definition for the
+    // associated type. This is either because the associate item
+    // has impossible-to-satisfy predicates (since those were
+    // allowed in <https://github.com/rust-lang/rust/pull/135480>),
+    // or because the impl is literally missing the definition.
     if !assoc_ty.item.defaultness(tcx).has_value() {
-        // This means that the impl is missing a definition for the
-        // associated type. This error will be reported by the type
-        // checker method `check_impl_items_against_trait`, so here we
-        // just return Error.
         debug!(
             "confirm_impl_candidate: no associated type {:?} for {:?}",
             assoc_ty.item.name, obligation.predicate
         );
-        return Progress { term: Ty::new_misc_error(tcx).into(), obligations: nested };
+        if tcx.impl_self_is_guaranteed_unsized(impl_def_id) {
+            // We treat this projection as rigid here, which is represented via
+            // `Projected::NoProgress`. This will ensure that the projection is
+            // checked for well-formedness, and it's either satisfied by a trivial
+            // where clause in its env or it results in an error.
+            return Ok(Projected::NoProgress(obligation.predicate.to_term(tcx)));
+        } else {
+            return Ok(Projected::Progress(Progress {
+                term: Ty::new_misc_error(tcx).into(),
+                obligations: nested,
+            }));
+        }
     }
+
     // If we're trying to normalize `<Vec<u32> as X>::A<S>` using
     //`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
     //
@@ -2033,6 +2030,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args);
     let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node);
     let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
+
     let term: ty::EarlyBinder<'tcx, ty::Term<'tcx>> = if is_const {
         let did = assoc_ty.item.def_id;
         let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did);
@@ -2041,7 +2039,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     } else {
         tcx.type_of(assoc_ty.item.def_id).map_bound(|ty| ty.into())
     };
-    if !tcx.check_args_compatible(assoc_ty.item.def_id, args) {
+
+    let progress = if !tcx.check_args_compatible(assoc_ty.item.def_id, args) {
         let err = Ty::new_error_with_message(
             tcx,
             obligation.cause.span,
@@ -2051,7 +2050,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     } else {
         assoc_ty_own_obligations(selcx, obligation, &mut nested);
         Progress { term: term.instantiate(tcx, args), obligations: nested }
-    }
+    };
+    Ok(Projected::Progress(progress))
 }
 
 // Get obligations corresponding to the predicates from the where-clause of the
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 5dbb4382fd1..507932699c7 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -144,7 +144,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
 
     #[inline]
     fn visit_region(&mut self, r: ty::Region<'tcx>) {
-        match *r {
+        match r.kind() {
             ty::ReBound(debruijn, _) if debruijn > self.outer_index => {
                 self.escaping =
                     self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize());
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 2cb7d2d8931..69e7b2a43ff 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -317,7 +317,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     obligation.cause.clone(),
                     obligation.recursion_depth + 1,
                     obligation.param_env,
-                    obligation.predicate.rebind(trait_ref),
+                    trait_ref,
                 )
             };
 
@@ -343,7 +343,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     obligation.cause.clone(),
                     obligation.recursion_depth + 1,
                     obligation.param_env,
-                    obligation.predicate.rebind(outlives),
+                    outlives,
                 )
             };
 
@@ -404,7 +404,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
         }
 
-        let predicate = obligation.predicate.skip_binder();
+        let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
 
         let mut assume = predicate.trait_ref.args.const_at(2);
         // FIXME(mgca): We should shallowly normalize this.
@@ -1090,26 +1090,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             {
                 // See `assemble_candidates_for_unsizing` for more info.
                 // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
-                let iter = data_a
-                    .principal()
-                    .filter(|_| {
-                        // optionally drop the principal, if we're unsizing to no principal
-                        data_b.principal().is_some()
-                    })
-                    .map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
-                    .into_iter()
-                    .chain(
+                let existential_predicates = if data_b.principal().is_some() {
+                    tcx.mk_poly_existential_predicates_from_iter(
                         data_a
-                            .projection_bounds()
-                            .map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
+                            .principal()
+                            .map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
+                            .into_iter()
+                            .chain(
+                                data_a
+                                    .projection_bounds()
+                                    .map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
+                            )
+                            .chain(
+                                data_b
+                                    .auto_traits()
+                                    .map(ty::ExistentialPredicate::AutoTrait)
+                                    .map(ty::Binder::dummy),
+                            ),
                     )
-                    .chain(
+                } else {
+                    // If we're unsizing to a dyn type that has no principal, then drop
+                    // the principal and projections from the type. We use the auto traits
+                    // from the RHS type since as we noted that we've checked for auto
+                    // trait compatibility during unsizing.
+                    tcx.mk_poly_existential_predicates_from_iter(
                         data_b
                             .auto_traits()
                             .map(ty::ExistentialPredicate::AutoTrait)
                             .map(ty::Binder::dummy),
-                    );
-                let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
+                    )
+                };
                 let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, dyn_a);
 
                 // Require that the traits involved in this upcast are **equal**;
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 15f5cf916a4..9f20cd7eacb 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -289,7 +289,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
+        match r.kind() {
             ty::ReBound(debruijn, _)
                 if debruijn.as_usize()
                     >= self.current_index.as_usize() + self.universe_indices.len() =>
@@ -407,7 +407,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
     }
 
     fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        let r1 = match *r0 {
+        let r1 = match r0.kind() {
             ty::ReVar(vid) => self
                 .infcx
                 .inner
@@ -417,7 +417,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
             _ => r0,
         };
 
-        let r2 = match *r1 {
+        let r2 = match r1.kind() {
             ty::RePlaceholder(p) => {
                 let replace_var = self.mapped_regions.get(&p);
                 match replace_var {
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 48d5a4a0fcb..3d4ab33240a 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -244,7 +244,7 @@ fn fn_sig_for_fn_abi<'tcx>(
 fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv {
     use rustc_abi::ExternAbi::*;
     match tcx.sess.target.adjust_abi(abi, c_variadic) {
-        RustIntrinsic | Rust | RustCall => Conv::Rust,
+        Rust | RustCall => Conv::Rust,
 
         // This is intentionally not using `Conv::Cold`, as that has to preserve
         // even SIMD registers, which is generally not a good trade-off.
@@ -660,7 +660,7 @@ fn fn_abi_adjust_for_abi<'tcx>(
     let tcx = cx.tcx();
 
     if abi.is_rustic_abi() {
-        fn_abi.adjust_for_rust_abi(cx, abi);
+        fn_abi.adjust_for_rust_abi(cx);
 
         // Look up the deduced parameter attributes for this function, if we have its def ID and
         // we're optimizing in non-incremental mode. We'll tag its parameters with those attributes
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 088d5e76b86..6fa763f18ef 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -4,9 +4,9 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt, fold_regions};
+use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
 
 pub(crate) fn provide(providers: &mut Providers) {
@@ -21,7 +21,8 @@ pub(crate) fn provide(providers: &mut Providers) {
 }
 
 fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
-    match tcx.def_kind(def_id) {
+    let kind = tcx.def_kind(def_id);
+    match kind {
         DefKind::Fn => {
             let sig = tcx.fn_sig(def_id).instantiate_identity();
             let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
@@ -75,7 +76,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
                     {
                         let orig_lt =
                             tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
-                        if matches!(*orig_lt, ty::ReLateParam(..)) {
+                        if matches!(orig_lt.kind(), ty::ReLateParam(..)) {
                             mapping.insert(
                                 orig_lt,
                                 ty::Region::new_early_param(
@@ -121,32 +122,38 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
             }
         }
         DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
-        DefKind::OpaqueTy => bug!("implied bounds are not defined for opaques"),
-        DefKind::Mod
+        DefKind::Static { .. }
+        | DefKind::Const
+        | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::Struct
         | DefKind::Union
         | DefKind::Enum
-        | DefKind::Variant
         | DefKind::Trait
-        | DefKind::TyAlias
-        | DefKind::ForeignTy
         | DefKind::TraitAlias
+        | DefKind::TyAlias => ty::List::empty(),
+        DefKind::OpaqueTy
+        | DefKind::Mod
+        | DefKind::Variant
+        | DefKind::ForeignTy
         | DefKind::TyParam
-        | DefKind::Const
         | DefKind::ConstParam
-        | DefKind::Static { .. }
         | DefKind::Ctor(_, _)
         | DefKind::Macro(_)
         | DefKind::ExternCrate
         | DefKind::Use
         | DefKind::ForeignMod
-        | DefKind::AnonConst
-        | DefKind::InlineConst
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::Closure
-        | DefKind::SyntheticCoroutineBody => ty::List::empty(),
+        | DefKind::SyntheticCoroutineBody => {
+            span_bug!(
+                tcx.def_span(def_id),
+                "`assumed_wf_types` not defined for {} `{def_id:?}`",
+                kind.descr(def_id.to_def_id())
+            );
+        }
     }
 }
 
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 3aad97d86cc..cd730aeeea9 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -3,10 +3,10 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit;
 use rustc_hir::intravisit::Visitor;
-use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
 use tracing::{instrument, trace};
 
@@ -320,9 +320,12 @@ fn opaque_types_defined_by<'tcx>(
         | DefKind::AnonConst => {
             collector.collect_taits_declared_in_body();
         }
+        // Closures and coroutines are type checked with their parent
+        DefKind::Closure | DefKind::InlineConst => {
+            collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item)));
+        }
+        DefKind::AssocTy | DefKind::TyAlias | DefKind::GlobalAsm => {}
         DefKind::OpaqueTy
-        | DefKind::TyAlias
-        | DefKind::AssocTy
         | DefKind::Mod
         | DefKind::Struct
         | DefKind::Union
@@ -340,12 +343,13 @@ fn opaque_types_defined_by<'tcx>(
         | DefKind::ForeignMod
         | DefKind::Field
         | DefKind::LifetimeParam
-        | DefKind::GlobalAsm
         | DefKind::Impl { .. }
-        | DefKind::SyntheticCoroutineBody => {}
-        // Closures and coroutines are type checked with their parent
-        DefKind::Closure | DefKind::InlineConst => {
-            collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item)));
+        | DefKind::SyntheticCoroutineBody => {
+            span_bug!(
+                tcx.def_span(item),
+                "`opaque_types_defined_by` not defined for {} `{item:?}`",
+                kind.descr(item.to_def_id())
+            );
         }
     }
     tcx.mk_local_def_ids(&collector.opaques)
diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs
index 5bb96f90029..dc6009116ac 100644
--- a/compiler/rustc_ty_utils/src/sig_types.rs
+++ b/compiler/rustc_ty_utils/src/sig_types.rs
@@ -116,7 +116,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
                 "{kind:?} has not seen any uses of `walk_types` yet, ping oli-obk if you'd like any help"
             )
         }
-        // These don't have any types.
+        // These don't have any types, but are visited during privacy checking.
         | DefKind::ExternCrate
         | DefKind::ForeignMod
         | DefKind::ForeignTy
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 9dc4f11e456..31d69eef5ec 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -3,6 +3,7 @@ use rustc_hir as hir;
 use rustc_hir::LangItem;
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::DenseBitSet;
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{
@@ -312,6 +313,61 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> DenseBitSe
     unsizing_params
 }
 
+fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId) -> bool {
+    debug_assert_eq!(tcx.def_kind(impl_def_id), DefKind::Impl { of_trait: true });
+
+    let infcx = tcx.infer_ctxt().ignoring_regions().build(ty::TypingMode::non_body_analysis());
+
+    let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
+    let cause = traits::ObligationCause::dummy();
+    let param_env = tcx.param_env(impl_def_id);
+
+    let tail = tcx.struct_tail_raw(
+        tcx.type_of(impl_def_id).instantiate_identity(),
+        |ty| {
+            ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| {
+                Ty::new_error_with_message(
+                    tcx,
+                    tcx.def_span(impl_def_id),
+                    "struct tail should be computable",
+                )
+            })
+        },
+        || (),
+    );
+
+    match tail.kind() {
+        ty::Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true,
+        ty::Bool
+        | ty::Char
+        | ty::Int(_)
+        | ty::Uint(_)
+        | ty::Float(_)
+        | ty::Adt(_, _)
+        | ty::Foreign(_)
+        | ty::Array(_, _)
+        | ty::Pat(_, _)
+        | ty::RawPtr(_, _)
+        | ty::Ref(_, _, _)
+        | ty::FnDef(_, _)
+        | ty::FnPtr(_, _)
+        | ty::UnsafeBinder(_)
+        | ty::Closure(_, _)
+        | ty::CoroutineClosure(_, _)
+        | ty::Coroutine(_, _)
+        | ty::CoroutineWitness(_, _)
+        | ty::Never
+        | ty::Tuple(_)
+        | ty::Alias(_, _)
+        | ty::Param(_)
+        | ty::Bound(_, _)
+        | ty::Placeholder(_)
+        | ty::Infer(_)
+        | ty::Error(_)
+        | ty::Dynamic(_, _, ty::DynStar) => false,
+    }
+}
+
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
         asyncness,
@@ -320,6 +376,7 @@ pub(crate) fn provide(providers: &mut Providers) {
         param_env_normalized_for_post_analysis,
         defaultness,
         unsizing_params_for_adt,
+        impl_self_is_guaranteed_unsized,
         ..*providers
     };
 }
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index 4adf7157926..83d3d78298e 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2024"
 # tidy-alphabetical-start
 bitflags = "2.4.1"
 derive-where = "1.2.7"
+ena = "0.14.3"
 indexmap = "2.0.0"
 rustc-hash = "1.1.0"
 rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
diff --git a/compiler/rustc_type_ir/src/data_structures/mod.rs b/compiler/rustc_type_ir/src/data_structures/mod.rs
index 30c67d10d0e..a72669cbd18 100644
--- a/compiler/rustc_type_ir/src/data_structures/mod.rs
+++ b/compiler/rustc_type_ir/src/data_structures/mod.rs
@@ -1,5 +1,6 @@
 use std::hash::BuildHasherDefault;
 
+pub use ena::unify::{NoError, UnifyKey, UnifyValue};
 use rustc_hash::FxHasher;
 pub use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
 
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 59c2d3c2fc8..6e6c40580d8 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -155,6 +155,39 @@ pub trait Ty<I: Interner<Ty = Self>>:
     fn is_known_rigid(self) -> bool {
         self.kind().is_known_rigid()
     }
+
+    fn is_guaranteed_unsized_raw(self) -> bool {
+        match self.kind() {
+            ty::Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true,
+            ty::Bool
+            | ty::Char
+            | ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Adt(_, _)
+            | ty::Foreign(_)
+            | ty::Array(_, _)
+            | ty::Pat(_, _)
+            | ty::RawPtr(_, _)
+            | ty::Ref(_, _, _)
+            | ty::FnDef(_, _)
+            | ty::FnPtr(_, _)
+            | ty::UnsafeBinder(_)
+            | ty::Closure(_, _)
+            | ty::CoroutineClosure(_, _)
+            | ty::Coroutine(_, _)
+            | ty::CoroutineWitness(_, _)
+            | ty::Never
+            | ty::Tuple(_)
+            | ty::Alias(_, _)
+            | ty::Param(_)
+            | ty::Bound(_, _)
+            | ty::Placeholder(_)
+            | ty::Infer(_)
+            | ty::Error(_)
+            | ty::Dynamic(_, _, ty::DynStar) => false,
+        }
+    }
 }
 
 pub trait Tys<I: Interner<Tys = Self>>:
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index fce93b735d7..a9e6764e218 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -255,6 +255,8 @@ pub trait Interner:
         def_id: Self::DefId,
     ) -> ty::EarlyBinder<Self, impl IntoIterator<Item = ty::Binder<Self, ty::TraitRef<Self>>>>;
 
+    fn impl_self_is_guaranteed_unsized(self, def_id: Self::DefId) -> bool;
+
     fn has_target_features(self, def_id: Self::DefId) -> bool;
 
     fn require_lang_item(self, lang_item: TraitSolverLangItem) -> Self::DefId;
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 4e2baca2785..bdc61e956f8 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -1,12 +1,12 @@
 // tidy-alphabetical-start
 #![allow(rustc::usage_of_ty_tykind)]
 #![allow(rustc::usage_of_type_ir_inherent)]
+#![allow(rustc::usage_of_type_ir_traits)]
 #![cfg_attr(
     feature = "nightly",
     feature(associated_type_defaults, never_type, rustc_attrs, negative_impls)
 )]
 #![cfg_attr(feature = "nightly", allow(internal_features))]
-#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))]
 // tidy-alphabetical-end
 
 extern crate self as rustc_type_ir;
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index 3aec4804b27..4e9b87fdf74 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -83,8 +83,11 @@ pub enum GoalSource {
     /// Instantiating a higher-ranked goal and re-proving it.
     InstantiateHigherRanked,
     /// Predicate required for an alias projection to be well-formed.
-    /// This is used in two places: projecting to an opaque whose hidden type
-    /// is already registered in the opaque type storage, and for rigid projections.
+    /// This is used in three places:
+    /// 1. projecting to an opaque whose hidden type is already registered in
+    ///    the opaque type storage,
+    /// 2. for rigid projections's trait goal,
+    /// 3. for GAT where clauses.
     AliasWellFormed,
     /// In case normalizing aliases in nested goals cycles, eagerly normalizing these
     /// aliases in the context of the parent may incorrectly change the cycle kind.
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index d35b22d517c..753a72a051a 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -6,9 +6,8 @@ use rustc_ast_ir::Mutability;
 #[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 #[cfg(feature = "nightly")]
-use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue};
-#[cfg(feature = "nightly")]
 use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
+use rustc_type_ir::data_structures::{NoError, UnifyKey, UnifyValue};
 use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
 
 use self::TyKind::*;
@@ -796,7 +795,6 @@ pub enum InferTy {
 
 /// Raw `TyVid` are used as the unification key for `sub_relations`;
 /// they carry no values.
-#[cfg(feature = "nightly")]
 impl UnifyKey for TyVid {
     type Value = ();
     #[inline]
@@ -812,7 +810,6 @@ impl UnifyKey for TyVid {
     }
 }
 
-#[cfg(feature = "nightly")]
 impl UnifyValue for IntVarValue {
     type Error = NoError;
 
@@ -832,7 +829,6 @@ impl UnifyValue for IntVarValue {
     }
 }
 
-#[cfg(feature = "nightly")]
 impl UnifyKey for IntVid {
     type Value = IntVarValue;
     #[inline] // make this function eligible for inlining - it is quite hot.
@@ -848,7 +844,6 @@ impl UnifyKey for IntVid {
     }
 }
 
-#[cfg(feature = "nightly")]
 impl UnifyValue for FloatVarValue {
     type Error = NoError;
 
@@ -866,7 +861,6 @@ impl UnifyValue for FloatVarValue {
     }
 }
 
-#[cfg(feature = "nightly")]
 impl UnifyKey for FloatVid {
     type Value = FloatVarValue;
     #[inline]