about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/ast.rs29
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs4
-rw-r--r--compiler/rustc_ast/src/entry.rs20
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs1
-rw-r--r--compiler/rustc_ast/src/visit.rs1
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs36
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs10
-rw-r--r--compiler/rustc_ast_passes/messages.ftl10
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs31
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs11
-rw-r--r--compiler/rustc_attr/src/builtin.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs49
-rw-r--r--compiler/rustc_borrowck/src/lib.rs10
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs12
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs57
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs12
-rw-r--r--compiler/rustc_codegen_cranelift/example/std_example.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/back/lto.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs16
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs20
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs34
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/back/lto.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs41
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs14
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs11
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs27
-rw-r--r--compiler/rustc_const_eval/src/interpret/call.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs22
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs12
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs49
-rw-r--r--compiler/rustc_const_eval/src/interpret/mod.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs84
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs9
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs259
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs535
-rw-r--r--compiler/rustc_const_eval/src/interpret/visitor.rs13
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs32
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0074.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0075.md18
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0076.md10
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0077.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0511.md4
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs28
-rw-r--r--compiler/rustc_errors/src/lib.rs94
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs16
-rw-r--r--compiler/rustc_hir/src/hir.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs104
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs10
-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/coherence/mod.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs18
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs49
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs39
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs51
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs32
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs33
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs8
-rw-r--r--compiler/rustc_index/src/interval.rs2
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs18
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_lint/src/builtin.rs12
-rw-r--r--compiler/rustc_lint/src/expect.rs90
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs12
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs9
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs36
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs7
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs5
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs8
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs60
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs8
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs8
-rw-r--r--compiler/rustc_middle/src/ty/region.rs2
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs39
-rw-r--r--compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse.rs12
-rw-r--r--compiler/rustc_mir_transform/src/add_call_guards.rs6
-rw-r--r--compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs45
-rw-r--r--compiler/rustc_mir_transform/src/add_retag.rs10
-rw-r--r--compiler/rustc_mir_transform/src/add_subtyping_projections.rs18
-rw-r--r--compiler/rustc_mir_transform/src/check_const_item_mutation.rs25
-rw-r--r--compiler/rustc_mir_transform/src/copy_prop.rs48
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters.rs234
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs3
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs3
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs15
-rw-r--r--compiler/rustc_mir_transform/src/deduplicate_blocks.rs7
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs14
-rw-r--r--compiler/rustc_mir_transform/src/early_otherwise_branch.rs4
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs16
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs5
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs4
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs97
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs3
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs8
-rw-r--r--compiler/rustc_mir_transform/src/jump_threading.rs42
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs31
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs350
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs50
-rw-r--r--compiler/rustc_mir_transform/src/lower_slice_len.rs26
-rw-r--r--compiler/rustc_mir_transform/src/match_branches.rs14
-rw-r--r--compiler/rustc_mir_transform/src/mentioned_items.rs12
-rw-r--r--compiler/rustc_mir_transform/src/pass_manager.rs6
-rw-r--r--compiler/rustc_mir_transform/src/post_drop_elaboration.rs13
-rw-r--r--compiler/rustc_mir_transform/src/prettify.rs4
-rw-r--r--compiler/rustc_mir_transform/src/promote_consts.rs39
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs15
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs113
-rw-r--r--compiler/rustc_mir_transform/src/remove_uninit_drops.rs5
-rw-r--r--compiler/rustc_mir_transform/src/required_consts.rs19
-rw-r--r--compiler/rustc_mir_transform/src/reveal_all.rs6
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs8
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs48
-rw-r--r--compiler/rustc_mir_transform/src/simplify_comparison_integral.rs22
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_enum_branching.rs6
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_prop.rs8
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs30
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs6
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs6
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs1
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs2
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs2
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs2
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs12
-rw-r--r--compiler/rustc_parse/src/parser/item.rs12
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs10
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs28
-rw-r--r--compiler/rustc_parse/src/parser/path.rs12
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs12
-rw-r--r--compiler/rustc_passes/messages.ftl3
-rw-r--r--compiler/rustc_passes/src/check_attr.rs23
-rw-r--r--compiler/rustc_passes/src/dead.rs2
-rw-r--r--compiler/rustc_passes/src/errors.rs7
-rw-r--r--compiler/rustc_passes/src/liveness.rs16
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs48
-rw-r--r--compiler/rustc_passes/src/stability.rs18
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs6
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs107
-rw-r--r--compiler/rustc_resolve/src/ident.rs12
-rw-r--r--compiler/rustc_resolve/src/imports.rs36
-rw-r--r--compiler/rustc_resolve/src/late.rs18
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs35
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs8
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs12
-rw-r--r--compiler/rustc_session/messages.ftl2
-rw-r--r--compiler/rustc_session/src/config.rs5
-rw-r--r--compiler/rustc_session/src/errors.rs6
-rw-r--r--compiler/rustc_session/src/filesearch.rs2
-rw-r--r--compiler/rustc_session/src/options.rs35
-rw-r--r--compiler/rustc_session/src/search_paths.rs2
-rw-r--r--compiler/rustc_session/src/session.rs12
-rw-r--r--compiler/rustc_span/src/source_map.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs6
-rw-r--r--compiler/rustc_target/src/abi/call/sparc64.rs6
-rw-r--r--compiler/rustc_target/src/abi/call/xtensa.rs40
-rw-r--r--compiler/rustc_target/src/spec/base/apple/mod.rs40
-rw-r--r--compiler/rustc_target/src/spec/mod.rs76
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs5
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs3
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs28
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs13
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs38
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs6
-rw-r--r--compiler/rustc_type_ir/src/elaborate.rs2
-rw-r--r--compiler/rustc_type_ir/src/interner.rs5
-rw-r--r--compiler/rustc_type_ir/src/search_graph/global_cache.rs14
-rw-r--r--compiler/rustc_type_ir/src/search_graph/mod.rs2
202 files changed, 2683 insertions, 2198 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 85d38a0e28b..9dfebfae5ed 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2418,11 +2418,22 @@ impl InlineAsmOperand {
     }
 }
 
+#[derive(Clone, Copy, Encodable, Decodable, Debug, HashStable_Generic)]
+pub enum AsmMacro {
+    /// The `asm!` macro
+    Asm,
+    /// The `global_asm!` macro
+    GlobalAsm,
+    /// The `naked_asm!` macro
+    NakedAsm,
+}
+
 /// Inline assembly.
 ///
 /// E.g., `asm!("NOP");`.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct InlineAsm {
+    pub asm_macro: AsmMacro,
     pub template: Vec<InlineAsmTemplatePiece>,
     pub template_strs: Box<[(Symbol, Option<Symbol>, Span)]>,
     pub operands: Vec<(InlineAsmOperand, Span)>,
@@ -2591,12 +2602,12 @@ impl CoroutineKind {
         }
     }
 
-    pub fn is_async(self) -> bool {
-        matches!(self, CoroutineKind::Async { .. })
-    }
-
-    pub fn is_gen(self) -> bool {
-        matches!(self, CoroutineKind::Gen { .. })
+    pub fn as_str(self) -> &'static str {
+        match self {
+            CoroutineKind::Async { .. } => "async",
+            CoroutineKind::Gen { .. } => "gen",
+            CoroutineKind::AsyncGen { .. } => "async gen",
+        }
     }
 
     pub fn closure_id(self) -> NodeId {
@@ -3475,7 +3486,7 @@ impl From<ForeignItemKind> for ItemKind {
     fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
         match foreign_item_kind {
             ForeignItemKind::Static(box static_foreign_item) => {
-                ItemKind::Static(Box::new(static_foreign_item.into()))
+                ItemKind::Static(Box::new(static_foreign_item))
             }
             ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
             ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
@@ -3489,9 +3500,7 @@ impl TryFrom<ItemKind> for ForeignItemKind {
 
     fn try_from(item_kind: ItemKind) -> Result<ForeignItemKind, ItemKind> {
         Ok(match item_kind {
-            ItemKind::Static(box static_item) => {
-                ForeignItemKind::Static(Box::new(static_item.into()))
-            }
+            ItemKind::Static(box static_item) => ForeignItemKind::Static(Box::new(static_item)),
             ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind),
             ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind),
             ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 6b95fb7dd36..60f8c6e1048 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -153,7 +153,7 @@ impl HasTokens for StmtKind {
             StmtKind::Let(local) => local.tokens.as_ref(),
             StmtKind::Item(item) => item.tokens(),
             StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens(),
-            StmtKind::Empty => return None,
+            StmtKind::Empty => None,
             StmtKind::MacCall(mac) => mac.tokens.as_ref(),
         }
     }
@@ -162,7 +162,7 @@ impl HasTokens for StmtKind {
             StmtKind::Let(local) => Some(&mut local.tokens),
             StmtKind::Item(item) => item.tokens_mut(),
             StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens_mut(),
-            StmtKind::Empty => return None,
+            StmtKind::Empty => None,
             StmtKind::MacCall(mac) => Some(&mut mac.tokens),
         }
     }
diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs
index 60a12614f06..53276e0847a 100644
--- a/compiler/rustc_ast/src/entry.rs
+++ b/compiler/rustc_ast/src/entry.rs
@@ -45,18 +45,16 @@ pub fn entry_point_type(
         EntryPointType::Start
     } else if attr::contains_name(attrs, sym::rustc_main) {
         EntryPointType::RustcMainAttr
-    } else {
-        if let Some(name) = name
-            && name == sym::main
-        {
-            if at_root {
-                // This is a top-level function so it can be `main`.
-                EntryPointType::MainNamed
-            } else {
-                EntryPointType::OtherMain
-            }
+    } else if let Some(name) = name
+        && name == sym::main
+    {
+        if at_root {
+            // This is a top-level function so it can be `main`.
+            EntryPointType::MainNamed
         } else {
-            EntryPointType::None
+            EntryPointType::OtherMain
         }
+    } else {
+        EntryPointType::None
     }
 }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 7c8af6c4a55..1bef51aa73f 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1388,6 +1388,7 @@ fn walk_anon_const<T: MutVisitor>(vis: &mut T, AnonConst { id, value }: &mut Ano
 fn walk_inline_asm<T: MutVisitor>(vis: &mut T, asm: &mut InlineAsm) {
     // FIXME: Visit spans inside all this currently ignored stuff.
     let InlineAsm {
+        asm_macro: _,
         template: _,
         template_strs: _,
         operands,
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 7b041768983..bae7ad93f90 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -976,6 +976,7 @@ pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonCo
 
 pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result {
     let InlineAsm {
+        asm_macro: _,
         template: _,
         template_strs: _,
         operands,
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index e077c544965..4413c259efb 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -474,8 +474,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         );
         let line_spans =
             self.arena.alloc_from_iter(asm.line_spans.iter().map(|span| self.lower_span(*span)));
-        let hir_asm =
-            hir::InlineAsm { template, template_strs, operands, options: asm.options, line_spans };
+        let hir_asm = hir::InlineAsm {
+            asm_macro: asm.asm_macro,
+            template,
+            template_strs,
+            operands,
+            options: asm.options,
+            line_spans,
+        };
         self.arena.alloc(hir_asm)
     }
 }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index a6c7714a182..b887908f904 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1837,7 +1837,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             Safety::Default,
             sym::allow,
             sym::unreachable_code,
-            self.lower_span(span),
+            try_span,
         );
         let attrs: AttrVec = thin_vec![attr];
 
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 23729124e21..f90a0612db6 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -78,26 +78,24 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
 
         // Make sure that the DepNode of some node coincides with the HirId
         // owner of that node.
-        if cfg!(debug_assertions) {
-            if hir_id.owner != self.owner {
-                span_bug!(
-                    span,
-                    "inconsistent HirId at `{:?}` for `{:?}`: \
+        if cfg!(debug_assertions) && hir_id.owner != self.owner {
+            span_bug!(
+                span,
+                "inconsistent HirId at `{:?}` for `{:?}`: \
                      current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})",
-                    self.tcx.sess.source_map().span_to_diagnostic_string(span),
-                    node,
-                    self.tcx
-                        .definitions_untracked()
-                        .def_path(self.owner.def_id)
-                        .to_string_no_crate_verbose(),
-                    self.owner,
-                    self.tcx
-                        .definitions_untracked()
-                        .def_path(hir_id.owner.def_id)
-                        .to_string_no_crate_verbose(),
-                    hir_id.owner,
-                )
-            }
+                self.tcx.sess.source_map().span_to_diagnostic_string(span),
+                node,
+                self.tcx
+                    .definitions_untracked()
+                    .def_path(self.owner.def_id)
+                    .to_string_no_crate_verbose(),
+                self.owner,
+                self.tcx
+                    .definitions_untracked()
+                    .def_path(hir_id.owner.def_id)
+                    .to_string_no_crate_verbose(),
+                hir_id.owner,
+            )
         }
 
         self.nodes[hir_id.local_id] = ParentedNode { parent: self.parent_node, node };
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index c8ec8f308a8..73c604bf28a 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -628,13 +628,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
                                 .map_or(Const::No, |attr| Const::Yes(attr.span)),
                             _ => Const::No,
                         }
+                    } else if self.tcx.is_const_trait(def_id) {
+                        // FIXME(effects) span
+                        Const::Yes(self.tcx.def_ident_span(def_id).unwrap())
                     } else {
-                        if self.tcx.is_const_trait(def_id) {
-                            // FIXME(effects) span
-                            Const::Yes(self.tcx.def_ident_span(def_id).unwrap())
-                        } else {
-                            Const::No
-                        }
+                        Const::No
                     }
                 } else {
                     Const::No
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index df5c639382f..c361c35b723 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -40,15 +40,15 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
 
 ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
 
-ast_passes_const_and_async = functions cannot be both `const` and `async`
-    .const = `const` because of this
-    .async = `async` because of this
-    .label = {""}
-
 ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
     .const = `const` because of this
     .variadic = C-variadic because of this
 
+ast_passes_const_and_coroutine = functions cannot be both `const` and `{$coroutine_kind}`
+    .const = `const` because of this
+    .coroutine = `{$coroutine_kind}` because of this
+    .label = {""}
+
 ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types
 
 ast_passes_const_without_body =
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index ed9672a9e79..93881f5ed42 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -447,13 +447,13 @@ impl<'a> AstValidator<'a> {
     fn check_item_safety(&self, span: Span, safety: Safety) {
         match self.extern_mod_safety {
             Some(extern_safety) => {
-                if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) {
-                    if extern_safety == Safety::Default {
-                        self.dcx().emit_err(errors::InvalidSafetyOnExtern {
-                            item_span: span,
-                            block: Some(self.current_extern_span().shrink_to_lo()),
-                        });
-                    }
+                if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_))
+                    && extern_safety == Safety::Default
+                {
+                    self.dcx().emit_err(errors::InvalidSafetyOnExtern {
+                        item_span: span,
+                        block: Some(self.current_extern_span().shrink_to_lo()),
+                    });
                 }
             }
             None => {
@@ -1418,21 +1418,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
         // Functions cannot both be `const async` or `const gen`
         if let Some(&FnHeader {
-            constness: Const::Yes(cspan),
+            constness: Const::Yes(const_span),
             coroutine_kind: Some(coroutine_kind),
             ..
         }) = fk.header()
         {
-            let aspan = match coroutine_kind {
-                CoroutineKind::Async { span: aspan, .. }
-                | CoroutineKind::Gen { span: aspan, .. }
-                | CoroutineKind::AsyncGen { span: aspan, .. } => aspan,
-            };
-            // FIXME(gen_blocks): Report a different error for `const gen`
-            self.dcx().emit_err(errors::ConstAndAsync {
-                spans: vec![cspan, aspan],
-                cspan,
-                aspan,
+            self.dcx().emit_err(errors::ConstAndCoroutine {
+                spans: vec![coroutine_kind.span(), const_span],
+                const_span,
+                coroutine_span: coroutine_kind.span(),
+                coroutine_kind: coroutine_kind.as_str(),
                 span,
             });
         }
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 67c0396333c..5cce47ce7bd 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -657,16 +657,17 @@ pub(crate) enum TildeConstReason {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_const_and_async)]
-pub(crate) struct ConstAndAsync {
+#[diag(ast_passes_const_and_coroutine)]
+pub(crate) struct ConstAndCoroutine {
     #[primary_span]
     pub spans: Vec<Span>,
     #[label(ast_passes_const)]
-    pub cspan: Span,
-    #[label(ast_passes_async)]
-    pub aspan: Span,
+    pub const_span: Span,
+    #[label(ast_passes_coroutine)]
+    pub coroutine_span: Span,
     #[label]
     pub span: Span,
+    pub coroutine_kind: &'static str,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index e46dabc7a6e..309049b98f0 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -1240,5 +1240,5 @@ pub fn parse_confusables(attr: &Attribute) -> Option<Vec<Symbol>> {
         candidates.push(meta_lit.symbol);
     }
 
-    return Some(candidates);
+    Some(candidates)
 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index a47518fca3f..5dec019126a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -2574,33 +2574,31 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         }
         impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
             fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
-                if e.span.contains(self.capture_span) {
-                    if let hir::ExprKind::Closure(&hir::Closure {
+                if e.span.contains(self.capture_span)
+                    && let hir::ExprKind::Closure(&hir::Closure {
                         kind: hir::ClosureKind::Closure,
                         body,
                         fn_arg_span,
                         fn_decl: hir::FnDecl { inputs, .. },
                         ..
                     }) = e.kind
-                        && let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id)
-                    {
-                        self.suggest_arg = "this: &Self".to_string();
-                        if inputs.len() > 0 {
-                            self.suggest_arg.push_str(", ");
-                        }
-                        self.in_closure = true;
-                        self.closure_arg_span = fn_arg_span;
-                        self.visit_expr(body);
-                        self.in_closure = false;
+                    && let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id)
+                {
+                    self.suggest_arg = "this: &Self".to_string();
+                    if inputs.len() > 0 {
+                        self.suggest_arg.push_str(", ");
                     }
+                    self.in_closure = true;
+                    self.closure_arg_span = fn_arg_span;
+                    self.visit_expr(body);
+                    self.in_closure = false;
                 }
-                if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e {
-                    if let hir::QPath::Resolved(_, hir::Path { segments: [seg], .. }) = path
-                        && seg.ident.name == kw::SelfLower
-                        && self.in_closure
-                    {
-                        self.closure_change_spans.push(e.span);
-                    }
+                if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e
+                    && let hir::QPath::Resolved(_, hir::Path { segments: [seg], .. }) = path
+                    && seg.ident.name == kw::SelfLower
+                    && self.in_closure
+                {
+                    self.closure_change_spans.push(e.span);
                 }
                 hir::intravisit::walk_expr(self, e);
             }
@@ -2609,8 +2607,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 if let hir::Pat { kind: hir::PatKind::Binding(_, hir_id, _ident, _), .. } =
                     local.pat
                     && let Some(init) = local.init
-                {
-                    if let hir::Expr {
+                    && let hir::Expr {
                         kind:
                             hir::ExprKind::Closure(&hir::Closure {
                                 kind: hir::ClosureKind::Closure,
@@ -2618,11 +2615,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                             }),
                         ..
                     } = init
-                        && init.span.contains(self.capture_span)
-                    {
-                        self.closure_local_id = Some(*hir_id);
-                    }
+                    && init.span.contains(self.capture_span)
+                {
+                    self.closure_local_id = Some(*hir_id);
                 }
+
                 hir::intravisit::walk_local(self, local);
             }
 
@@ -3669,7 +3666,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 reinits.push(location);
                 return true;
             }
-            return false;
+            false
         };
 
         while let Some(location) = stack.pop() {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index d5f297a5913..d98c66b0f3b 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -2069,12 +2069,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
                 // no move out from an earlier location) then this is an attempt at initialization
                 // of the union - we should error in that case.
                 let tcx = this.infcx.tcx;
-                if base.ty(this.body(), tcx).ty.is_union() {
-                    if this.move_data.path_map[mpi].iter().any(|moi| {
+                if base.ty(this.body(), tcx).ty.is_union()
+                    && this.move_data.path_map[mpi].iter().any(|moi| {
                         this.move_data.moves[*moi].source.is_predecessor_of(location, this.body)
-                    }) {
-                        return;
-                    }
+                    })
+                {
+                    return;
                 }
 
                 this.report_use_of_moved_or_uninitialized(
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index d62f2067729..30dc062ae7c 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -118,10 +118,8 @@ impl LivenessValues {
         debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location);
         if let Some(points) = &mut self.points {
             points.insert(region, point);
-        } else {
-            if self.elements.point_in_range(point) {
-                self.live_regions.as_mut().unwrap().insert(region);
-            }
+        } else if self.elements.point_in_range(point) {
+            self.live_regions.as_mut().unwrap().insert(region);
         }
 
         // When available, record the loans flowing into this region as live at the given point.
@@ -137,10 +135,8 @@ impl LivenessValues {
         debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points);
         if let Some(this) = &mut self.points {
             this.union_row(region, points);
-        } else {
-            if points.iter().any(|point| self.elements.point_in_range(point)) {
-                self.live_regions.as_mut().unwrap().insert(region);
-            }
+        } else if points.iter().any(|point| self.elements.point_in_range(point)) {
+            self.live_regions.as_mut().unwrap().insert(region);
         }
 
         // When available, record the loans flowing into this region as live at the given points.
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 4d47863ae76..1ac27573453 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -353,11 +353,11 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
             let location = self.cx.elements.to_location(drop_point);
             debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,);
 
-            if self.cx.initialized_at_terminator(location.block, mpi) {
-                if self.drop_live_at.insert(drop_point) {
-                    self.drop_locations.push(location);
-                    self.stack.push(drop_point);
-                }
+            if self.cx.initialized_at_terminator(location.block, mpi)
+                && self.drop_live_at.insert(drop_point)
+            {
+                self.drop_locations.push(location);
+                self.stack.push(drop_point);
             }
         }
 
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index bb4a58930e1..421f4e2efe0 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -214,7 +214,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
         let delegate = FnMutDelegate {
             regions: &mut |br: ty::BoundRegion| {
                 if let Some(ex_reg_var) = reg_map.get(&br) {
-                    return *ex_reg_var;
+                    *ex_reg_var
                 } else {
                     let ex_reg_var = self.next_existential_region_var(true, br.kind.get_name());
                     debug!(?ex_reg_var);
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index ae2627d6938..0e1ec3b3cad 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -3,6 +3,7 @@ use lint::BuiltinLintDiag;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter};
 use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::AsmMacro;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::PResult;
 use rustc_expand::base::*;
@@ -234,13 +235,11 @@ pub fn parse_asm_args<'a>(
                 continue;
             }
             args.named_args.insert(name, slot);
-        } else {
-            if !args.named_args.is_empty() || !args.reg_args.is_empty() {
-                let named = args.named_args.values().map(|p| args.operands[*p].1).collect();
-                let explicit = args.reg_args.iter().map(|p| args.operands[p].1).collect();
+        } else if !args.named_args.is_empty() || !args.reg_args.is_empty() {
+            let named = args.named_args.values().map(|p| args.operands[*p].1).collect();
+            let explicit = args.reg_args.iter().map(|p| args.operands[p].1).collect();
 
-                dcx.emit_err(errors::AsmPositionalAfter { span, named, explicit });
-            }
+            dcx.emit_err(errors::AsmPositionalAfter { span, named, explicit });
         }
     }
 
@@ -484,6 +483,7 @@ fn parse_reg<'a>(
 
 fn expand_preparsed_asm(
     ecx: &mut ExtCtxt<'_>,
+    asm_macro: ast::AsmMacro,
     args: AsmArgs,
 ) -> ExpandResult<Result<ast::InlineAsm, ErrorGuaranteed>, ()> {
     let mut template = vec![];
@@ -774,6 +774,7 @@ fn expand_preparsed_asm(
     }
 
     ExpandResult::Ready(Ok(ast::InlineAsm {
+        asm_macro,
         template,
         template_strs: template_strs.into_boxed_slice(),
         operands: args.operands,
@@ -790,7 +791,7 @@ pub(super) fn expand_asm<'cx>(
 ) -> MacroExpanderResult<'cx> {
     ExpandResult::Ready(match parse_args(ecx, sp, tts, false) {
         Ok(args) => {
-            let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else {
+            let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::Asm, args) else {
                 return ExpandResult::Retry(());
             };
             let expr = match mac {
@@ -812,6 +813,45 @@ pub(super) fn expand_asm<'cx>(
     })
 }
 
+pub(super) fn expand_naked_asm<'cx>(
+    ecx: &'cx mut ExtCtxt<'_>,
+    sp: Span,
+    tts: TokenStream,
+) -> MacroExpanderResult<'cx> {
+    ExpandResult::Ready(match parse_args(ecx, sp, tts, false) {
+        Ok(args) => {
+            let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::NakedAsm, args)
+            else {
+                return ExpandResult::Retry(());
+            };
+            let expr = match mac {
+                Ok(mut inline_asm) => {
+                    // for future compatibility, we always set the NORETURN option.
+                    //
+                    // When we turn `asm!` into `naked_asm!` with this implementation, we can drop
+                    // the `options(noreturn)`, which makes the upgrade smooth when `naked_asm!`
+                    // starts disallowing the `noreturn` option in the future
+                    inline_asm.options |= ast::InlineAsmOptions::NORETURN;
+
+                    P(ast::Expr {
+                        id: ast::DUMMY_NODE_ID,
+                        kind: ast::ExprKind::InlineAsm(P(inline_asm)),
+                        span: sp,
+                        attrs: ast::AttrVec::new(),
+                        tokens: None,
+                    })
+                }
+                Err(guar) => DummyResult::raw_expr(sp, Some(guar)),
+            };
+            MacEager::expr(expr)
+        }
+        Err(err) => {
+            let guar = err.emit();
+            DummyResult::any(sp, guar)
+        }
+    })
+}
+
 pub(super) fn expand_global_asm<'cx>(
     ecx: &'cx mut ExtCtxt<'_>,
     sp: Span,
@@ -819,7 +859,8 @@ pub(super) fn expand_global_asm<'cx>(
 ) -> MacroExpanderResult<'cx> {
     ExpandResult::Ready(match parse_args(ecx, sp, tts, true) {
         Ok(args) => {
-            let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else {
+            let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::GlobalAsm, args)
+            else {
                 return ExpandResult::Retry(());
             };
             match mac {
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 30e1c8d2622..ebe5e2b5442 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -94,6 +94,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
         line: source_util::expand_line,
         log_syntax: log_syntax::expand_log_syntax,
         module_path: source_util::expand_mod,
+        naked_asm: asm::expand_naked_asm,
         option_env: env::expand_option_env,
         pattern_type: pattern_type::expand,
         std_panic: edition_panic::expand_panic,
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 1b76a5f3234..40dc75339ef 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -277,6 +277,8 @@ pub(crate) fn expand_test_or_bench(
                 cx.attr_nested_word(sym::cfg, sym::test, attr_sp),
                 // #[rustc_test_marker = "test_case_sort_key"]
                 cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp),
+                // #[doc(hidden)]
+                cx.attr_nested_word(sym::doc, sym::hidden, attr_sp),
             ],
             // const $ident: test::TestDescAndFn =
             ast::ItemKind::Const(
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index a9e44345811..400557ca260 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -326,6 +326,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     let main_attr = ecx.attr_word(sym::rustc_main, sp);
     // #[coverage(off)]
     let coverage_attr = ecx.attr_nested_word(sym::coverage, sym::off, sp);
+    // #[doc(hidden)]
+    let doc_hidden_attr = ecx.attr_nested_word(sym::doc, sym::hidden, sp);
 
     // pub fn main() { ... }
     let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(ThinVec::new()));
@@ -355,7 +357,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
 
     let main = P(ast::Item {
         ident: main_id,
-        attrs: thin_vec![main_attr, coverage_attr],
+        attrs: thin_vec![main_attr, coverage_attr, doc_hidden_attr],
         id: ast::DUMMY_NODE_ID,
         kind: main,
         vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None },
diff --git a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs
index c54574d801d..ad46e18c11c 100644
--- a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs
+++ b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs
@@ -9,13 +9,13 @@
 
 #[repr(simd)]
 #[derive(Copy, Clone, PartialEq, Debug)]
-struct f32x4(pub f32, pub f32, pub f32, pub f32);
+struct f32x4(pub [f32; 4]);
 
 use std::intrinsics::simd::*;
 
 fn main() {
-    let x = f32x4(1.0, 2.0, 3.0, 4.0);
-    let y = f32x4(2.0, 1.0, 4.0, 3.0);
+    let x = f32x4([1.0, 2.0, 3.0, 4.0]);
+    let y = f32x4([2.0, 1.0, 4.0, 3.0]);
 
     #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
     let nan = f32::NAN;
@@ -24,13 +24,13 @@ fn main() {
     #[cfg(any(target_arch = "mips", target_arch = "mips64"))]
     let nan = f32::from_bits(f32::NAN.to_bits() - 1);
 
-    let n = f32x4(nan, nan, nan, nan);
+    let n = f32x4([nan, nan, nan, nan]);
 
     unsafe {
         let min0 = simd_fmin(x, y);
         let min1 = simd_fmin(y, x);
         assert_eq!(min0, min1);
-        let e = f32x4(1.0, 1.0, 3.0, 3.0);
+        let e = f32x4([1.0, 1.0, 3.0, 3.0]);
         assert_eq!(min0, e);
         let minn = simd_fmin(x, n);
         assert_eq!(minn, x);
@@ -40,7 +40,7 @@ fn main() {
         let max0 = simd_fmax(x, y);
         let max1 = simd_fmax(y, x);
         assert_eq!(max0, max1);
-        let e = f32x4(2.0, 2.0, 4.0, 4.0);
+        let e = f32x4([2.0, 2.0, 4.0, 4.0]);
         assert_eq!(max0, e);
         let maxn = simd_fmax(x, n);
         assert_eq!(maxn, x);
diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index e99763e2722..f27d4ef57e0 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -166,7 +166,7 @@ fn main() {
         enum Never {}
     }
 
-    foo(I64X2(0, 0));
+    foo(I64X2([0, 0]));
 
     transmute_fat_pointer();
 
@@ -204,7 +204,7 @@ fn rust_call_abi() {
 }
 
 #[repr(simd)]
-struct I64X2(i64, i64);
+struct I64X2([i64; 2]);
 
 #[allow(improper_ctypes_definitions)]
 extern "C" fn foo(_a: I64X2) {}
diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs
index 6b2dbbbed67..c2adab7137f 100644
--- a/compiler/rustc_codegen_gcc/src/back/lto.rs
+++ b/compiler/rustc_codegen_gcc/src/back/lto.rs
@@ -272,7 +272,6 @@ fn fat_lto(
             }*/
         }
     };
-    let mut serialized_bitcode = Vec::new();
     {
         info!("using {:?} as a base module", module.name);
 
@@ -317,7 +316,6 @@ fn fat_lto(
                     unimplemented!("from uncompressed file")
                 }
             }
-            serialized_bitcode.push(bc_decoded);
         }
         save_temp_bitcode(cgcx, &module, "lto.input");
 
@@ -337,7 +335,7 @@ fn fat_lto(
     // of now.
     module.module_llvm.temp_dir = Some(tmp_path);
 
-    Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: serialized_bitcode })
+    Ok(LtoModuleCodegen::Fat(module))
 }
 
 pub struct ModuleBuffer(PathBuf);
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index aa6842c75ce..2ebe0be53aa 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -92,11 +92,9 @@ fn prepare_lto(
                     dcx.emit_err(LtoDylib);
                     return Err(FatalError);
                 }
-            } else if *crate_type == CrateType::ProcMacro {
-                if !cgcx.opts.unstable_opts.dylib_lto {
-                    dcx.emit_err(LtoProcMacro);
-                    return Err(FatalError);
-                }
+            } else if *crate_type == CrateType::ProcMacro && !cgcx.opts.unstable_opts.dylib_lto {
+                dcx.emit_err(LtoProcMacro);
+                return Err(FatalError);
             }
         }
 
@@ -314,7 +312,6 @@ fn fat_lto(
             }
         }
     };
-    let mut serialized_bitcode = Vec::new();
     {
         let (llcx, llmod) = {
             let llvm = &module.module_llvm;
@@ -342,9 +339,7 @@ fn fat_lto(
         serialized_modules.sort_by(|module1, module2| module1.1.cmp(&module2.1));
 
         // For all serialized bitcode files we parse them and link them in as we did
-        // above, this is all mostly handled in C++. Like above, though, we don't
-        // know much about the memory management here so we err on the side of being
-        // save and persist everything with the original module.
+        // above, this is all mostly handled in C++.
         let mut linker = Linker::new(llmod);
         for (bc_decoded, name) in serialized_modules {
             let _timer = cgcx
@@ -355,7 +350,6 @@ fn fat_lto(
             info!("linking {:?}", name);
             let data = bc_decoded.data();
             linker.add(data).map_err(|()| write::llvm_err(dcx, LlvmError::LoadBitcode { name }))?;
-            serialized_bitcode.push(bc_decoded);
         }
         drop(linker);
         save_temp_bitcode(cgcx, &module, "lto.input");
@@ -372,7 +366,7 @@ fn fat_lto(
         }
     }
 
-    Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: serialized_bitcode })
+    Ok(LtoModuleCodegen::Fat(module))
 }
 
 pub(crate) struct Linker<'a>(&'a mut llvm::Linker<'a>);
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 01aae24ab56..73c2c15717f 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -27,7 +27,7 @@ use rustc_span::source_map::Spanned;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{HasDataLayout, TargetDataLayout, VariantIdx};
-use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
+use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel};
 use smallvec::SmallVec;
 
 use crate::back::write::to_llvm_code_model;
@@ -387,6 +387,24 @@ pub(crate) unsafe fn create_module<'ll>(
         }
     }
 
+    match (sess.opts.unstable_opts.small_data_threshold, sess.target.small_data_threshold_support())
+    {
+        // Set up the small-data optimization limit for architectures that use
+        // an LLVM module flag to control this.
+        (Some(threshold), SmallDataThresholdSupport::LlvmModuleFlag(flag)) => {
+            let flag = SmallCStr::new(flag.as_ref());
+            unsafe {
+                llvm::LLVMRustAddModuleFlagU32(
+                    llmod,
+                    llvm::LLVMModFlagBehavior::Error,
+                    flag.as_c_str().as_ptr(),
+                    threshold as u32,
+                )
+            }
+        }
+        _ => (),
+    };
+
     // Insert `llvm.ident` metadata.
     //
     // On the wasm targets it will get hooked up to the "producer" sections
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index d55220ba5c3..29afe6f6bfc 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -14,7 +14,7 @@ use rustc_middle::bug;
 use rustc_session::config::{PrintKind, PrintRequest};
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
-use rustc_target::spec::{MergeFunctions, PanicStrategy};
+use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
 use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
 
 use crate::back::write::create_informational_target_machine;
@@ -125,6 +125,18 @@ unsafe fn configure_llvm(sess: &Session) {
         for arg in sess_args {
             add(&(*arg), true);
         }
+
+        match (
+            sess.opts.unstable_opts.small_data_threshold,
+            sess.target.small_data_threshold_support(),
+        ) {
+            // Set up the small-data optimization limit for architectures that use
+            // an LLVM argument to control this.
+            (Some(threshold), SmallDataThresholdSupport::LlvmArg(arg)) => {
+                add(&format!("--{arg}={threshold}"), false)
+            }
+            _ => (),
+        };
     }
 
     if sess.opts.unstable_opts.llvm_time_trace {
@@ -290,7 +302,7 @@ pub(crate) fn check_tied_features(
             }
         }
     }
-    return None;
+    None
 }
 
 /// Used to generate cfg variables and apply features
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index e8143b9a5f3..40eb35deea5 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -281,12 +281,10 @@ pub fn each_linked_rlib(
         let used_crate_source = &info.used_crate_source[&cnum];
         if let Some((path, _)) = &used_crate_source.rlib {
             f(cnum, path);
+        } else if used_crate_source.rmeta.is_some() {
+            return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name });
         } else {
-            if used_crate_source.rmeta.is_some() {
-                return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name });
-            } else {
-                return Err(errors::LinkRlibError::NotFound { crate_name });
-            }
+            return Err(errors::LinkRlibError::NotFound { crate_name });
         }
     }
     Ok(())
@@ -438,7 +436,7 @@ fn link_rlib<'a>(
         ab.add_file(&lib)
     }
 
-    return Ok(ab);
+    Ok(ab)
 }
 
 /// Extract all symbols defined in raw-dylib libraries, collated by library name.
@@ -628,12 +626,10 @@ fn link_staticlib(
         let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum];
         if let Some((path, _)) = &used_crate_source.dylib {
             all_rust_dylibs.push(&**path);
+        } else if used_crate_source.rmeta.is_some() {
+            sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name });
         } else {
-            if used_crate_source.rmeta.is_some() {
-                sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name });
-            } else {
-                sess.dcx().emit_fatal(errors::LinkRlibError::NotFound { crate_name });
-            }
+            sess.dcx().emit_fatal(errors::LinkRlibError::NotFound { crate_name });
         }
     }
 
@@ -1319,7 +1315,7 @@ fn link_sanitizer_runtime(
     fn find_sanitizer_runtime(sess: &Session, filename: &str) -> PathBuf {
         let path = sess.target_tlib_path.dir.join(filename);
         if path.exists() {
-            return sess.target_tlib_path.dir.clone();
+            sess.target_tlib_path.dir.clone()
         } else {
             let default_sysroot =
                 filesearch::get_or_default_sysroot().expect("Failed finding sysroot");
@@ -1327,7 +1323,7 @@ fn link_sanitizer_runtime(
                 &default_sysroot,
                 sess.opts.target_triple.triple(),
             );
-            return default_tlib;
+            default_tlib
         }
     }
 
@@ -1972,10 +1968,8 @@ fn add_late_link_args(
         if let Some(args) = sess.target.late_link_args_dynamic.get(&flavor) {
             cmd.verbatim_args(args.iter().map(Deref::deref));
         }
-    } else {
-        if let Some(args) = sess.target.late_link_args_static.get(&flavor) {
-            cmd.verbatim_args(args.iter().map(Deref::deref));
-        }
+    } else if let Some(args) = sess.target.late_link_args_static.get(&flavor) {
+        cmd.verbatim_args(args.iter().map(Deref::deref));
     }
     if let Some(args) = sess.target.late_link_args.get(&flavor) {
         cmd.verbatim_args(args.iter().map(Deref::deref));
@@ -2635,10 +2629,8 @@ fn add_native_libs_from_crate(
                     if link_static {
                         cmd.link_staticlib_by_name(name, verbatim, false);
                     }
-                } else {
-                    if link_dynamic {
-                        cmd.link_dylib_by_name(name, verbatim, true);
-                    }
+                } else if link_dynamic {
+                    cmd.link_dylib_by_name(name, verbatim, true);
                 }
             }
             NativeLibKind::Framework { as_needed } => {
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index cb266247e0d..7f5f9f03868 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -791,14 +791,12 @@ impl<'a> Linker for GccLinker<'a> {
             self.link_arg("-exported_symbols_list").link_arg(path);
         } else if self.sess.target.is_like_solaris {
             self.link_arg("-M").link_arg(path);
+        } else if is_windows {
+            self.link_arg(path);
         } else {
-            if is_windows {
-                self.link_arg(path);
-            } else {
-                let mut arg = OsString::from("--version-script=");
-                arg.push(path);
-                self.link_arg(arg).link_arg("--no-undefined-version");
-            }
+            let mut arg = OsString::from("--version-script=");
+            arg.push(path);
+            self.link_arg(arg).link_arg("--no-undefined-version");
         }
     }
 
@@ -1484,7 +1482,6 @@ impl<'a> Linker for L4Bender<'a> {
     fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) {
         // ToDo, not implemented, copy from GCC
         self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented);
-        return;
     }
 
     fn subsystem(&mut self, subsystem: &str) {
diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs
index 8b6f6b5a220..1e1e039882b 100644
--- a/compiler/rustc_codegen_ssa/src/back/lto.rs
+++ b/compiler/rustc_codegen_ssa/src/back/lto.rs
@@ -41,18 +41,14 @@ pub struct ThinShared<B: WriteBackendMethods> {
 }
 
 pub enum LtoModuleCodegen<B: WriteBackendMethods> {
-    Fat {
-        module: ModuleCodegen<B::Module>,
-        _serialized_bitcode: Vec<SerializedModule<B::ModuleBuffer>>,
-    },
-
+    Fat(ModuleCodegen<B::Module>),
     Thin(ThinModule<B>),
 }
 
 impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
     pub fn name(&self) -> &str {
         match *self {
-            LtoModuleCodegen::Fat { .. } => "everything",
+            LtoModuleCodegen::Fat(_) => "everything",
             LtoModuleCodegen::Thin(ref m) => m.name(),
         }
     }
@@ -68,7 +64,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
         cgcx: &CodegenContext<B>,
     ) -> Result<ModuleCodegen<B::Module>, FatalError> {
         match self {
-            LtoModuleCodegen::Fat { mut module, .. } => {
+            LtoModuleCodegen::Fat(mut module) => {
                 B::optimize_fat(cgcx, &mut module)?;
                 Ok(module)
             }
@@ -81,7 +77,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
     pub fn cost(&self) -> u64 {
         match *self {
             // Only one module with fat LTO, so the cost doesn't matter.
-            LtoModuleCodegen::Fat { .. } => 0,
+            LtoModuleCodegen::Fat(_) => 0,
             LtoModuleCodegen::Thin(ref m) => m.cost(),
         }
     }
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 0fd9d7fffe8..6215616e510 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -171,10 +171,10 @@ pub(super) fn get_metadata_xcoff<'a>(path: &Path, data: &'a [u8]) -> Result<&'a
                 "Metadata at offset {offset} with size {len} is beyond .info section"
             ));
         }
-        return Ok(&info_data[offset..(offset + len)]);
+        Ok(&info_data[offset..(offset + len)])
     } else {
-        return Err(format!("Unable to find symbol {AIX_METADATA_SYMBOL_NAME}"));
-    };
+        Err(format!("Unable to find symbol {AIX_METADATA_SYMBOL_NAME}"))
+    }
 }
 
 pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static>> {
@@ -413,7 +413,7 @@ fn macho_object_build_version_for_target(target: &Target) -> object::write::Mach
 
 /// Is Apple's CPU subtype `arm64e`s
 fn macho_is_arm64e(target: &Target) -> bool {
-    return target.llvm_target.starts_with("arm64e");
+    target.llvm_target.starts_with("arm64e")
 }
 
 pub enum MetadataPosition {
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 4ab20c154cc..9149c602296 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -617,32 +617,29 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
     // purpose functions as they wouldn't have the right target features
     // enabled. For that reason we also forbid #[inline(always)] as it can't be
     // respected.
-    if !codegen_fn_attrs.target_features.is_empty() {
-        if codegen_fn_attrs.inline == InlineAttr::Always {
-            if let Some(span) = inline_span {
-                tcx.dcx().span_err(
-                    span,
-                    "cannot use `#[inline(always)]` with \
+    if !codegen_fn_attrs.target_features.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always
+    {
+        if let Some(span) = inline_span {
+            tcx.dcx().span_err(
+                span,
+                "cannot use `#[inline(always)]` with \
                      `#[target_feature]`",
-                );
-            }
+            );
         }
     }
 
-    if !codegen_fn_attrs.no_sanitize.is_empty() {
-        if codegen_fn_attrs.inline == InlineAttr::Always {
-            if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
-                let hir_id = tcx.local_def_id_to_hir_id(did);
-                tcx.node_span_lint(
-                    lint::builtin::INLINE_NO_SANITIZE,
-                    hir_id,
-                    no_sanitize_span,
-                    |lint| {
-                        lint.primary_message("`no_sanitize` will have no effect after inlining");
-                        lint.span_note(inline_span, "inlining requested here");
-                    },
-                )
-            }
+    if !codegen_fn_attrs.no_sanitize.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always {
+        if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
+            let hir_id = tcx.local_def_id_to_hir_id(did);
+            tcx.node_span_lint(
+                lint::builtin::INLINE_NO_SANITIZE,
+                hir_id,
+                no_sanitize_span,
+                |lint| {
+                    lint.primary_message("`no_sanitize` will have no effect after inlining");
+                    lint.span_note(inline_span, "inlining requested here");
+                },
+            )
         }
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 5103b2f3158..e34fbfe3f76 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -236,15 +236,13 @@ fn push_debuginfo_type_name<'tcx>(
             let has_enclosing_parens = if cpp_like_debuginfo {
                 output.push_str("dyn$<");
                 false
+            } else if trait_data.len() > 1 && auto_traits.len() != 0 {
+                // We need enclosing parens because there is more than one trait
+                output.push_str("(dyn ");
+                true
             } else {
-                if trait_data.len() > 1 && auto_traits.len() != 0 {
-                    // We need enclosing parens because there is more than one trait
-                    output.push_str("(dyn ");
-                    true
-                } else {
-                    output.push_str("dyn ");
-                    false
-                }
+                output.push_str("dyn ");
+                false
             };
 
             if let Some(principal) = trait_data.principal() {
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 96b3ec6f187..da4173f9032 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -75,12 +75,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
 
     // This can't use `init_stack_frame` since `body` is not a function,
     // so computing its ABI would fail. It's also not worth it since there are no arguments to pass.
-    ecx.push_stack_frame_raw(
-        cid.instance,
-        body,
-        &ret.clone().into(),
-        StackPopCleanup::Root { cleanup: false },
-    )?;
+    ecx.push_stack_frame_raw(cid.instance, body, &ret, StackPopCleanup::Root { cleanup: false })?;
     ecx.storage_live_for_always_live_locals()?;
 
     // The main interpreter loop.
@@ -94,7 +89,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
     let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret);
 
     // Since evaluation had no errors, validate the resulting constant.
-    const_validate_mplace(&ecx, &ret, cid)?;
+    const_validate_mplace(ecx, &ret, cid)?;
 
     // Only report this after validation, as validaiton produces much better diagnostics.
     // FIXME: ensure validation always reports this and stop making interning care about it.
@@ -391,7 +386,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
 
 #[inline(always)]
 fn const_validate_mplace<'tcx>(
-    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
+    ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
     mplace: &MPlaceTy<'tcx>,
     cid: GlobalId<'tcx>,
 ) -> Result<(), ErrorHandled> {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 9c1fef095f5..7405ca09342 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -1,16 +1,16 @@
-use std::borrow::Borrow;
+use std::borrow::{Borrow, Cow};
 use std::fmt;
 use std::hash::Hash;
 use std::ops::ControlFlow;
 
 use rustc_ast::Mutability;
-use rustc_data_structures::fx::{FxIndexMap, IndexEntry};
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self as hir, LangItem, CRATE_HIR_ID};
 use rustc_middle::mir::AssertMessage;
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{bug, mir};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
@@ -24,8 +24,8 @@ use crate::fluent_generated as fluent;
 use crate::interpret::{
     self, compile_time_machine, err_ub, throw_exhaust, throw_inval, throw_ub_custom, throw_unsup,
     throw_unsup_format, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame,
-    GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar,
-    StackPopCleanup,
+    GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic,
+    RangeSet, Scalar, StackPopCleanup,
 };
 
 /// When hitting this many interpreted terminators we emit a deny by default lint
@@ -65,6 +65,9 @@ pub struct CompileTimeMachine<'tcx> {
     /// storing the result in the given `AllocId`.
     /// Used to prevent reads from a static's base allocation, as that may allow for self-initialization loops.
     pub(crate) static_root_ids: Option<(AllocId, LocalDefId)>,
+
+    /// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes).
+    union_data_ranges: FxHashMap<Ty<'tcx>, RangeSet>,
 }
 
 #[derive(Copy, Clone)]
@@ -99,6 +102,7 @@ impl<'tcx> CompileTimeMachine<'tcx> {
             can_access_mut_global,
             check_alignment,
             static_root_ids: None,
+            union_data_ranges: FxHashMap::default(),
         }
     }
 }
@@ -766,6 +770,19 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
         }
         Ok(())
     }
+
+    fn cached_union_data_range<'e>(
+        ecx: &'e mut InterpCx<'tcx, Self>,
+        ty: Ty<'tcx>,
+        compute_range: impl FnOnce() -> RangeSet,
+    ) -> Cow<'e, RangeSet> {
+        if ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks {
+            Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range))
+        } else {
+            // Don't bother caching, we're only doing one validation at the end anyway.
+            Cow::Owned(compute_range())
+        }
+    }
 }
 
 // Please do not add any code below the above `Machine` trait impl. I (oli-obk) plan more cleanups
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 568a9a3a637..0f2b22f035b 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -235,13 +235,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         if self.layout_compat(caller_abi.layout, callee_abi.layout)? {
             // Ensure that our checks imply actual ABI compatibility for this concrete call.
             assert!(caller_abi.eq_abi(callee_abi));
-            return Ok(true);
+            Ok(true)
         } else {
             trace!(
                 "check_argument_compat: incompatible ABIs:\ncaller: {:?}\ncallee: {:?}",
                 caller_abi, callee_abi
             );
-            return Ok(false);
+            Ok(false)
         }
     }
 
@@ -823,7 +823,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             (Abi::Rust, fn_abi),
             &[FnArg::Copy(arg.into())],
             false,
-            &ret.into(),
+            &ret,
             Some(target),
             unwind,
         )
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 0008a15722b..de93ed85704 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -7,7 +7,7 @@ use rustc_target::abi::{self, TagEncoding, VariantIdx, Variants};
 use tracing::{instrument, trace};
 
 use super::{
-    err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable,
+    err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Projectable, Scalar, Writeable,
 };
 
 impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
@@ -60,7 +60,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     #[instrument(skip(self), level = "trace")]
     pub fn read_discriminant(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, VariantIdx> {
         let ty = op.layout().ty;
         trace!("read_discriminant_value {:#?}", op.layout());
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index dd744c51f23..16d40fcceb6 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -16,7 +16,7 @@ use rustc_span::Span;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
 use rustc_trait_selection::traits::ObligationCtxt;
-use tracing::{debug, trace};
+use tracing::{debug, instrument, trace};
 
 use super::{
     err_inval, throw_inval, throw_ub, throw_ub_custom, Frame, FrameInfo, GlobalId, InterpErrorInfo,
@@ -315,6 +315,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
     /// Check if the two things are equal in the current param_env, using an infctx to get proper
     /// equality checks.
+    #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn eq_in_param_env<T>(&self, a: T, b: T) -> bool
     where
         T: PartialEq + TypeFoldable<TyCtxt<'tcx>> + ToTrace<'tcx>,
@@ -330,13 +331,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // equate the two trait refs after normalization
         let a = ocx.normalize(&cause, self.param_env, a);
         let b = ocx.normalize(&cause, self.param_env, b);
-        if ocx.eq(&cause, self.param_env, a, b).is_ok() {
-            if ocx.select_all_or_error().is_empty() {
-                // All good.
-                return true;
-            }
+
+        if let Err(terr) = ocx.eq(&cause, self.param_env, a, b) {
+            trace!(?terr);
+            return false;
+        }
+
+        let errors = ocx.select_all_or_error();
+        if !errors.is_empty() {
+            trace!(?errors);
+            return false;
         }
-        return false;
+
+        // All good.
+        true
     }
 
     /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 6cfd7be48e6..8cab3c34eed 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -10,6 +10,7 @@ use rustc_apfloat::{Float, FloatConvert};
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::Ty;
 use rustc_middle::{mir, ty};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
@@ -19,7 +20,7 @@ use rustc_target::spec::abi::Abi as CallAbi;
 use super::{
     throw_unsup, throw_unsup_format, AllocBytes, AllocId, AllocKind, AllocRange, Allocation,
     ConstAllocation, CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy,
-    MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, CTFE_ALLOC_SALT,
+    MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, CTFE_ALLOC_SALT,
 };
 
 /// Data returned by [`Machine::after_stack_pop`], and consumed by
@@ -578,6 +579,15 @@ pub trait Machine<'tcx>: Sized {
         ecx: &InterpCx<'tcx, Self>,
         instance: Option<ty::Instance<'tcx>>,
     ) -> usize;
+
+    fn cached_union_data_range<'e>(
+        _ecx: &'e mut InterpCx<'tcx, Self>,
+        _ty: Ty<'tcx>,
+        compute_range: impl FnOnce() -> RangeSet,
+    ) -> Cow<'e, RangeSet> {
+        // Default to no caching.
+        Cow::Owned(compute_range())
+    }
 }
 
 /// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 45a5eb9bd52..d87588496c0 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -8,9 +8,8 @@
 
 use std::assert_matches::assert_matches;
 use std::borrow::Cow;
-use std::cell::Cell;
 use std::collections::VecDeque;
-use std::{fmt, ptr};
+use std::{fmt, mem, ptr};
 
 use rustc_ast::Mutability;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
@@ -118,7 +117,7 @@ pub struct Memory<'tcx, M: Machine<'tcx>> {
     /// This stores whether we are currently doing reads purely for the purpose of validation.
     /// Those reads do not trigger the machine's hooks for memory reads.
     /// Needless to say, this must only be set with great care!
-    validation_in_progress: Cell<bool>,
+    validation_in_progress: bool,
 }
 
 /// A reference to some allocation that was already bounds-checked for the given region
@@ -145,7 +144,7 @@ impl<'tcx, M: Machine<'tcx>> Memory<'tcx, M> {
             alloc_map: M::MemoryMap::default(),
             extra_fn_ptr_map: FxIndexMap::default(),
             dead_alloc_map: FxIndexMap::default(),
-            validation_in_progress: Cell::new(false),
+            validation_in_progress: false,
         }
     }
 
@@ -682,7 +681,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // We want to call the hook on *all* accesses that involve an AllocId, including zero-sized
         // accesses. That means we cannot rely on the closure above or the `Some` branch below. We
         // do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked.
-        if !self.memory.validation_in_progress.get() {
+        if !self.memory.validation_in_progress {
             if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) {
                 M::before_alloc_read(self, alloc_id)?;
             }
@@ -690,7 +689,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
         if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc {
             let range = alloc_range(offset, size);
-            if !self.memory.validation_in_progress.get() {
+            if !self.memory.validation_in_progress {
                 M::before_memory_read(
                     self.tcx,
                     &self.machine,
@@ -766,11 +765,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         let parts = self.get_ptr_access(ptr, size)?;
         if let Some((alloc_id, offset, prov)) = parts {
             let tcx = self.tcx;
+            let validation_in_progress = self.memory.validation_in_progress;
             // FIXME: can we somehow avoid looking up the allocation twice here?
             // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`.
             let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?;
             let range = alloc_range(offset, size);
-            M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?;
+            if !validation_in_progress {
+                M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?;
+            }
             Ok(Some(AllocRefMut { alloc, range, tcx: *tcx, alloc_id }))
         } else {
             Ok(None)
@@ -1014,16 +1016,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     ///
     /// We do this so Miri's allocation access tracking does not show the validation
     /// reads as spurious accesses.
-    pub fn run_for_validation<R>(&self, f: impl FnOnce() -> R) -> R {
+    pub fn run_for_validation<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
         // This deliberately uses `==` on `bool` to follow the pattern
         // `assert!(val.replace(new) == old)`.
         assert!(
-            self.memory.validation_in_progress.replace(true) == false,
+            mem::replace(&mut self.memory.validation_in_progress, true) == false,
             "`validation_in_progress` was already set"
         );
-        let res = f();
+        let res = f(self);
         assert!(
-            self.memory.validation_in_progress.replace(false) == true,
+            mem::replace(&mut self.memory.validation_in_progress, false) == true,
             "`validation_in_progress` was unset by someone else"
         );
         res
@@ -1115,6 +1117,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> {
 impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes>
     AllocRefMut<'a, 'tcx, Prov, Extra, Bytes>
 {
+    pub fn as_ref<'b>(&'b self) -> AllocRef<'b, 'tcx, Prov, Extra, Bytes> {
+        AllocRef { alloc: self.alloc, range: self.range, tcx: self.tcx, alloc_id: self.alloc_id }
+    }
+
     /// `range` is relative to this allocation reference, not the base of the allocation.
     pub fn write_scalar(&mut self, range: AllocRange, val: Scalar<Prov>) -> InterpResult<'tcx> {
         let range = self.range.subrange(range);
@@ -1130,13 +1136,30 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes>
         self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size), val)
     }
 
+    /// Mark the given sub-range (relative to this allocation reference) as uninitialized.
+    pub fn write_uninit(&mut self, range: AllocRange) -> InterpResult<'tcx> {
+        let range = self.range.subrange(range);
+        Ok(self
+            .alloc
+            .write_uninit(&self.tcx, range)
+            .map_err(|e| e.to_interp_error(self.alloc_id))?)
+    }
+
     /// Mark the entire referenced range as uninitialized
-    pub fn write_uninit(&mut self) -> InterpResult<'tcx> {
+    pub fn write_uninit_full(&mut self) -> InterpResult<'tcx> {
         Ok(self
             .alloc
             .write_uninit(&self.tcx, self.range)
             .map_err(|e| e.to_interp_error(self.alloc_id))?)
     }
+
+    /// Remove all provenance in the reference range.
+    pub fn clear_provenance(&mut self) -> InterpResult<'tcx> {
+        Ok(self
+            .alloc
+            .clear_provenance(&self.tcx, self.range)
+            .map_err(|e| e.to_interp_error(self.alloc_id))?)
+    }
 }
 
 impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> {
@@ -1278,7 +1301,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         };
         let src_alloc = self.get_alloc_raw(src_alloc_id)?;
         let src_range = alloc_range(src_offset, size);
-        assert!(!self.memory.validation_in_progress.get(), "we can't be copying during validation");
+        assert!(!self.memory.validation_in_progress, "we can't be copying during validation");
         M::before_memory_read(
             tcx,
             &self.machine,
diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs
index 511756e3f86..561d681f804 100644
--- a/compiler/rustc_const_eval/src/interpret/mod.rs
+++ b/compiler/rustc_const_eval/src/interpret/mod.rs
@@ -33,11 +33,11 @@ pub(crate) use self::intrinsics::eval_nullary_intrinsic;
 pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, ReturnAction};
 pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
 use self::operand::Operand;
-pub use self::operand::{ImmTy, Immediate, OpTy, Readable};
+pub use self::operand::{ImmTy, Immediate, OpTy};
 pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable};
 use self::place::{MemPlace, Place};
 pub use self::projection::{OffsetMode, Projectable};
 pub use self::stack::{Frame, FrameInfo, LocalState, StackPopCleanup, StackPopInfo};
 pub(crate) use self::util::create_static_alloc;
-pub use self::validity::{CtfeValidationMode, RefTracking};
+pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking};
 pub use self::visitor::ValueVisitor;
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 9a8ccaa7cc5..bb7e58b83ac 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -111,6 +111,46 @@ impl<Prov: Provenance> Immediate<Prov> {
             Immediate::Uninit => bug!("Got uninit where a scalar or scalar pair was expected"),
         }
     }
+
+    /// Assert that this immediate is a valid value for the given ABI.
+    pub fn assert_matches_abi(self, abi: Abi, cx: &impl HasDataLayout) {
+        match (self, abi) {
+            (Immediate::Scalar(scalar), Abi::Scalar(s)) => {
+                assert_eq!(scalar.size(), s.size(cx));
+                if !matches!(s.primitive(), abi::Pointer(..)) {
+                    assert!(matches!(scalar, Scalar::Int(..)));
+                }
+            }
+            (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => {
+                assert_eq!(a_val.size(), a.size(cx));
+                if !matches!(a.primitive(), abi::Pointer(..)) {
+                    assert!(matches!(a_val, Scalar::Int(..)));
+                }
+                assert_eq!(b_val.size(), b.size(cx));
+                if !matches!(b.primitive(), abi::Pointer(..)) {
+                    assert!(matches!(b_val, Scalar::Int(..)));
+                }
+            }
+            (Immediate::Uninit, _) => {}
+            _ => {
+                bug!("value {self:?} does not match ABI {abi:?})",)
+            }
+        }
+    }
+
+    pub fn clear_provenance<'tcx>(&mut self) -> InterpResult<'tcx> {
+        match self {
+            Immediate::Scalar(s) => {
+                s.clear_provenance()?;
+            }
+            Immediate::ScalarPair(a, b) => {
+                a.clear_provenance()?;
+                b.clear_provenance()?;
+            }
+            Immediate::Uninit => {}
+        }
+        Ok(())
+    }
 }
 
 // ScalarPair needs a type to interpret, so we often have an immediate and a type together
@@ -393,6 +433,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for ImmTy<'tcx, Prov> {
         Ok(self.offset_(offset, layout, ecx))
     }
 
+    #[inline(always)]
     fn to_op<M: Machine<'tcx, Provenance = Prov>>(
         &self,
         _ecx: &InterpCx<'tcx, M>,
@@ -482,6 +523,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> {
         }
     }
 
+    #[inline(always)]
     fn to_op<M: Machine<'tcx, Provenance = Prov>>(
         &self,
         _ecx: &InterpCx<'tcx, M>,
@@ -490,32 +532,6 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> {
     }
 }
 
-/// The `Readable` trait describes interpreter values that one can read from.
-pub trait Readable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> {
-    fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>>;
-}
-
-impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for OpTy<'tcx, Prov> {
-    #[inline(always)]
-    fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
-        self.as_mplace_or_imm()
-    }
-}
-
-impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
-    #[inline(always)]
-    fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
-        Left(self.clone())
-    }
-}
-
-impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for ImmTy<'tcx, Prov> {
-    #[inline(always)]
-    fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
-        Right(self.clone())
-    }
-}
-
 impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     /// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
     /// Returns `None` if the layout does not permit loading this as a value.
@@ -588,9 +604,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     /// ConstProp needs it, though.
     pub fn read_immediate_raw(
         &self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, Either<MPlaceTy<'tcx, M::Provenance>, ImmTy<'tcx, M::Provenance>>> {
-        Ok(match src.as_mplace_or_imm() {
+        Ok(match src.to_op(self)?.as_mplace_or_imm() {
             Left(ref mplace) => {
                 if let Some(val) = self.read_immediate_from_mplace_raw(mplace)? {
                     Right(val)
@@ -608,7 +624,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     #[inline(always)]
     pub fn read_immediate(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         if !matches!(
             op.layout().abi,
@@ -627,7 +643,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     /// Read a scalar from a place
     pub fn read_scalar(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
         Ok(self.read_immediate(op)?.to_scalar())
     }
@@ -638,21 +654,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     /// Read a pointer from a place.
     pub fn read_pointer(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
         self.read_scalar(op)?.to_pointer(self)
     }
     /// Read a pointer-sized unsigned integer from a place.
     pub fn read_target_usize(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, u64> {
         self.read_scalar(op)?.to_target_usize(self)
     }
     /// Read a pointer-sized signed integer from a place.
     pub fn read_target_isize(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, i64> {
         self.read_scalar(op)?.to_target_isize(self)
     }
@@ -717,7 +733,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
         match place.as_mplace_or_local() {
             Left(mplace) => Ok(mplace.into()),
-            Right((local, offset, locals_addr)) => {
+            Right((local, offset, locals_addr, _)) => {
                 debug_assert!(place.layout.is_sized()); // only sized locals can ever be `Place::Local`.
                 debug_assert_eq!(locals_addr, self.frame().locals_addr());
                 let base = self.local_to_op(local, None)?;
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index e9ba12dbcc4..b390bb87789 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -303,8 +303,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let pointee_layout = self.layout_of(pointee_ty)?;
                 assert!(pointee_layout.abi.is_sized());
 
-                // We cannot overflow i64 as a type's size must be <= isize::MAX.
+                // The size always fits in `i64` as it can be at most `isize::MAX`.
                 let pointee_size = i64::try_from(pointee_layout.size.bytes()).unwrap();
+                // This uses the same type as `right`, which can be `isize` or `usize`.
+                // `pointee_size` is guaranteed to fit into both types.
                 let pointee_size = ImmTy::from_int(pointee_size, right.layout);
                 // Multiply element size and element count.
                 let (val, overflowed) = self
@@ -316,6 +318,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 }
 
                 let offset_bytes = val.to_target_isize(self)?;
+                if !right.layout.abi.is_signed() && offset_bytes < 0 {
+                    // We were supposed to do an unsigned offset but the result is negative -- this
+                    // can only mean that the cast wrapped around.
+                    throw_ub!(PointerArithOverflow)
+                }
                 let offset_ptr = self.ptr_offset_inbounds(ptr, offset_bytes)?;
                 Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout))
             }
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 840f7986c6e..1eca92812df 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -15,7 +15,7 @@ use tracing::{instrument, trace};
 use super::{
     alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance,
     ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy,
-    Operand, Pointer, Projectable, Provenance, Readable, Scalar,
+    Operand, Pointer, Projectable, Provenance, Scalar,
 };
 
 #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
@@ -166,6 +166,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
         Ok(MPlaceTy { mplace: self.mplace.offset_with_meta_(offset, mode, meta, ecx)?, layout })
     }
 
+    #[inline(always)]
     fn to_op<M: Machine<'tcx, Provenance = Prov>>(
         &self,
         _ecx: &InterpCx<'tcx, M>,
@@ -180,7 +181,8 @@ pub(super) enum Place<Prov: Provenance = CtfeProvenance> {
     Ptr(MemPlace<Prov>),
 
     /// To support alloc-free locals, we are able to write directly to a local. The offset indicates
-    /// where in the local this place is located; if it is `None`, no projection has been applied.
+    /// where in the local this place is located; if it is `None`, no projection has been applied
+    /// and the type of the place is exactly the type of the local.
     /// Such projections are meaningful even if the offset is 0, since they can change layouts.
     /// (Without that optimization, we'd just always be a `MemPlace`.)
     /// `Local` places always refer to the current stack frame, so they are unstable under
@@ -231,10 +233,12 @@ impl<'tcx, Prov: Provenance> PlaceTy<'tcx, Prov> {
     #[inline(always)]
     pub fn as_mplace_or_local(
         &self,
-    ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize)> {
+    ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)> {
         match self.place {
             Place::Ptr(mplace) => Left(MPlaceTy { mplace, layout: self.layout }),
-            Place::Local { local, offset, locals_addr } => Right((local, offset, locals_addr)),
+            Place::Local { local, offset, locals_addr } => {
+                Right((local, offset, locals_addr, self.layout))
+            }
         }
     }
 
@@ -277,7 +281,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
     ) -> InterpResult<'tcx, Self> {
         Ok(match self.as_mplace_or_local() {
             Left(mplace) => mplace.offset_with_meta(offset, mode, meta, layout, ecx)?.into(),
-            Right((local, old_offset, locals_addr)) => {
+            Right((local, old_offset, locals_addr, _)) => {
                 debug_assert!(layout.is_sized(), "unsized locals should live in memory");
                 assert_matches!(meta, MemPlaceMeta::None); // we couldn't store it anyway...
                 // `Place::Local` are always in-bounds of their surrounding local, so we can just
@@ -296,6 +300,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
         })
     }
 
+    #[inline(always)]
     fn to_op<M: Machine<'tcx, Provenance = Prov>>(
         &self,
         ecx: &InterpCx<'tcx, M>,
@@ -328,9 +333,7 @@ impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> {
 
 /// The `Weiteable` trait describes interpreter values that can be written to.
 pub trait Writeable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> {
-    fn as_mplace_or_local(
-        &self,
-    ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)>;
+    fn to_place(&self) -> PlaceTy<'tcx, Prov>;
 
     fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
         &self,
@@ -340,11 +343,8 @@ pub trait Writeable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> {
 
 impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
     #[inline(always)]
-    fn as_mplace_or_local(
-        &self,
-    ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)> {
-        self.as_mplace_or_local()
-            .map_right(|(local, offset, locals_addr)| (local, offset, locals_addr, self.layout))
+    fn to_place(&self) -> PlaceTy<'tcx, Prov> {
+        self.clone()
     }
 
     #[inline(always)]
@@ -358,10 +358,8 @@ impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
 
 impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
     #[inline(always)]
-    fn as_mplace_or_local(
-        &self,
-    ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)> {
-        Left(self.clone())
+    fn to_place(&self) -> PlaceTy<'tcx, Prov> {
+        self.clone().into()
     }
 
     #[inline(always)]
@@ -436,7 +434,7 @@ where
     #[instrument(skip(self), level = "trace")]
     pub fn deref_pointer(
         &self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
         if src.layout().ty.is_box() {
             // Derefer should have removed all Box derefs.
@@ -562,6 +560,41 @@ where
         Ok(place)
     }
 
+    /// Given a place, returns either the underlying mplace or a reference to where the value of
+    /// this place is stored.
+    #[inline(always)]
+    fn as_mplace_or_mutable_local(
+        &mut self,
+        place: &PlaceTy<'tcx, M::Provenance>,
+    ) -> InterpResult<
+        'tcx,
+        Either<MPlaceTy<'tcx, M::Provenance>, (&mut Immediate<M::Provenance>, TyAndLayout<'tcx>)>,
+    > {
+        Ok(match place.to_place().as_mplace_or_local() {
+            Left(mplace) => Left(mplace),
+            Right((local, offset, locals_addr, layout)) => {
+                if offset.is_some() {
+                    // This has been projected to a part of this local, or had the type changed.
+                    // FIMXE: there are cases where we could still avoid allocating an mplace.
+                    Left(place.force_mplace(self)?)
+                } else {
+                    debug_assert_eq!(locals_addr, self.frame().locals_addr());
+                    debug_assert_eq!(self.layout_of_local(self.frame(), local, None)?, layout);
+                    match self.frame_mut().locals[local].access_mut()? {
+                        Operand::Indirect(mplace) => {
+                            // The local is in memory.
+                            Left(MPlaceTy { mplace: *mplace, layout })
+                        }
+                        Operand::Immediate(local_val) => {
+                            // The local still has the optimized representation.
+                            Right((local_val, layout))
+                        }
+                    }
+                }
+            }
+        })
+    }
+
     /// Write an immediate to a place
     #[inline(always)]
     #[instrument(skip(self), level = "trace")]
@@ -574,9 +607,11 @@ where
 
         if M::enforce_validity(self, dest.layout()) {
             // Data got changed, better make sure it matches the type!
+            // Also needed to reset padding.
             self.validate_operand(
-                &dest.to_op(self)?,
+                &dest.to_place(),
                 M::enforce_validity_recursively(self, dest.layout()),
+                /*reset_provenance_and_padding*/ true,
             )?;
         }
 
@@ -606,67 +641,27 @@ where
     /// Write an immediate to a place.
     /// If you use this you are responsible for validating that things got copied at the
     /// right type.
-    fn write_immediate_no_validate(
+    pub(super) fn write_immediate_no_validate(
         &mut self,
         src: Immediate<M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
         assert!(dest.layout().is_sized(), "Cannot write unsized immediate data");
 
-        // See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`,
-        // but not factored as a separate function.
-        let mplace = match dest.as_mplace_or_local() {
-            Right((local, offset, locals_addr, layout)) => {
-                if offset.is_some() {
-                    // This has been projected to a part of this local. We could have complicated
-                    // logic to still keep this local as an `Operand`... but it's much easier to
-                    // just fall back to the indirect path.
-                    dest.force_mplace(self)?
-                } else {
-                    debug_assert_eq!(locals_addr, self.frame().locals_addr());
-                    match self.frame_mut().locals[local].access_mut()? {
-                        Operand::Immediate(local_val) => {
-                            // Local can be updated in-place.
-                            *local_val = src;
-                            // Double-check that the value we are storing and the local fit to each other.
-                            // (*After* doing the update for borrow checker reasons.)
-                            if cfg!(debug_assertions) {
-                                let local_layout =
-                                    self.layout_of_local(&self.frame(), local, None)?;
-                                match (src, local_layout.abi) {
-                                    (Immediate::Scalar(scalar), Abi::Scalar(s)) => {
-                                        assert_eq!(scalar.size(), s.size(self))
-                                    }
-                                    (
-                                        Immediate::ScalarPair(a_val, b_val),
-                                        Abi::ScalarPair(a, b),
-                                    ) => {
-                                        assert_eq!(a_val.size(), a.size(self));
-                                        assert_eq!(b_val.size(), b.size(self));
-                                    }
-                                    (Immediate::Uninit, _) => {}
-                                    (src, abi) => {
-                                        bug!(
-                                            "value {src:?} cannot be written into local with type {} (ABI {abi:?})",
-                                            local_layout.ty
-                                        )
-                                    }
-                                };
-                            }
-                            return Ok(());
-                        }
-                        Operand::Indirect(mplace) => {
-                            // The local is in memory, go on below.
-                            MPlaceTy { mplace: *mplace, layout }
-                        }
-                    }
+        match self.as_mplace_or_mutable_local(&dest.to_place())? {
+            Right((local_val, local_layout)) => {
+                // Local can be updated in-place.
+                *local_val = src;
+                // Double-check that the value we are storing and the local fit to each other.
+                if cfg!(debug_assertions) {
+                    src.assert_matches_abi(local_layout.abi, self);
                 }
             }
-            Left(mplace) => mplace, // already referring to memory
-        };
-
-        // This is already in memory, write there.
-        self.write_immediate_to_mplace_no_validate(src, mplace.layout, mplace.mplace)
+            Left(mplace) => {
+                self.write_immediate_to_mplace_no_validate(src, mplace.layout, mplace.mplace)?;
+            }
+        }
+        Ok(())
     }
 
     /// Write an immediate to memory.
@@ -678,6 +673,9 @@ where
         layout: TyAndLayout<'tcx>,
         dest: MemPlace<M::Provenance>,
     ) -> InterpResult<'tcx> {
+        if cfg!(debug_assertions) {
+            value.assert_matches_abi(layout.abi, self);
+        }
         // Note that it is really important that the type here is the right one, and matches the
         // type things are read at. In case `value` is a `ScalarPair`, we don't do any magic here
         // to handle padding properly, which is only correct if we never look at this data with the
@@ -691,15 +689,7 @@ where
 
         match value {
             Immediate::Scalar(scalar) => {
-                let Abi::Scalar(s) = layout.abi else {
-                    span_bug!(
-                        self.cur_span(),
-                        "write_immediate_to_mplace: invalid Scalar layout: {layout:#?}",
-                    )
-                };
-                let size = s.size(&tcx);
-                assert_eq!(size, layout.size, "abi::Scalar size does not match layout size");
-                alloc.write_scalar(alloc_range(Size::ZERO, size), scalar)
+                alloc.write_scalar(alloc_range(Size::ZERO, scalar.size()), scalar)
             }
             Immediate::ScalarPair(a_val, b_val) => {
                 let Abi::ScalarPair(a, b) = layout.abi else {
@@ -709,18 +699,19 @@ where
                         layout
                     )
                 };
-                let (a_size, b_size) = (a.size(&tcx), b.size(&tcx));
-                let b_offset = a_size.align_to(b.align(&tcx).abi);
+                let b_offset = a.size(&tcx).align_to(b.align(&tcx).abi);
                 assert!(b_offset.bytes() > 0); // in `operand_field` we use the offset to tell apart the fields
 
                 // It is tempting to verify `b_offset` against `layout.fields.offset(1)`,
                 // but that does not work: We could be a newtype around a pair, then the
                 // fields do not match the `ScalarPair` components.
 
-                alloc.write_scalar(alloc_range(Size::ZERO, a_size), a_val)?;
-                alloc.write_scalar(alloc_range(b_offset, b_size), b_val)
+                alloc.write_scalar(alloc_range(Size::ZERO, a_val.size()), a_val)?;
+                alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val)?;
+                // We don't have to reset padding here, `write_immediate` will anyway do a validation run.
+                Ok(())
             }
-            Immediate::Uninit => alloc.write_uninit(),
+            Immediate::Uninit => alloc.write_uninit_full(),
         }
     }
 
@@ -728,35 +719,38 @@ where
         &mut self,
         dest: &impl Writeable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
-        let mplace = match dest.as_mplace_or_local() {
-            Left(mplace) => mplace,
-            Right((local, offset, locals_addr, layout)) => {
-                if offset.is_some() {
-                    // This has been projected to a part of this local. We could have complicated
-                    // logic to still keep this local as an `Operand`... but it's much easier to
-                    // just fall back to the indirect path.
-                    // FIXME: share the logic with `write_immediate_no_validate`.
-                    dest.force_mplace(self)?
-                } else {
-                    debug_assert_eq!(locals_addr, self.frame().locals_addr());
-                    match self.frame_mut().locals[local].access_mut()? {
-                        Operand::Immediate(local) => {
-                            *local = Immediate::Uninit;
-                            return Ok(());
-                        }
-                        Operand::Indirect(mplace) => {
-                            // The local is in memory, go on below.
-                            MPlaceTy { mplace: *mplace, layout }
-                        }
-                    }
-                }
+        match self.as_mplace_or_mutable_local(&dest.to_place())? {
+            Right((local_val, _local_layout)) => {
+                *local_val = Immediate::Uninit;
             }
-        };
-        let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else {
-            // Zero-sized access
-            return Ok(());
-        };
-        alloc.write_uninit()?;
+            Left(mplace) => {
+                let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else {
+                    // Zero-sized access
+                    return Ok(());
+                };
+                alloc.write_uninit_full()?;
+            }
+        }
+        Ok(())
+    }
+
+    /// Remove all provenance in the given place.
+    pub fn clear_provenance(
+        &mut self,
+        dest: &impl Writeable<'tcx, M::Provenance>,
+    ) -> InterpResult<'tcx> {
+        match self.as_mplace_or_mutable_local(&dest.to_place())? {
+            Right((local_val, _local_layout)) => {
+                local_val.clear_provenance()?;
+            }
+            Left(mplace) => {
+                let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else {
+                    // Zero-sized access
+                    return Ok(());
+                };
+                alloc.clear_provenance()?;
+            }
+        }
         Ok(())
     }
 
@@ -768,7 +762,7 @@ where
     #[inline(always)]
     pub(super) fn copy_op_no_dest_validation(
         &mut self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
         self.copy_op_inner(
@@ -781,7 +775,7 @@ where
     #[inline(always)]
     pub fn copy_op_allow_transmute(
         &mut self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
         self.copy_op_inner(
@@ -794,7 +788,7 @@ where
     #[inline(always)]
     pub fn copy_op(
         &mut self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
         self.copy_op_inner(
@@ -808,28 +802,35 @@ where
     #[instrument(skip(self), level = "trace")]
     fn copy_op_inner(
         &mut self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
         allow_transmute: bool,
         validate_dest: bool,
     ) -> InterpResult<'tcx> {
-        // Generally for transmutation, data must be valid both at the old and new type.
-        // But if the types are the same, the 2nd validation below suffices.
-        if src.layout().ty != dest.layout().ty && M::enforce_validity(self, src.layout()) {
-            self.validate_operand(
-                &src.to_op(self)?,
-                M::enforce_validity_recursively(self, src.layout()),
-            )?;
-        }
+        // These are technically *two* typed copies: `src` is a not-yet-loaded value,
+        // so we're going a typed copy at `src` type from there to some intermediate storage.
+        // And then we're doing a second typed copy from that intermediate storage to `dest`.
+        // But as an optimization, we only make a single direct copy here.
 
         // Do the actual copy.
         self.copy_op_no_validate(src, dest, allow_transmute)?;
 
         if validate_dest && M::enforce_validity(self, dest.layout()) {
-            // Data got changed, better make sure it matches the type!
+            let dest = dest.to_place();
+            // Given that there were two typed copies, we have to ensure this is valid at both types,
+            // and we have to ensure this loses provenance and padding according to both types.
+            // But if the types are identical, we only do one pass.
+            if allow_transmute && src.layout().ty != dest.layout().ty {
+                self.validate_operand(
+                    &dest.transmute(src.layout(), self)?,
+                    M::enforce_validity_recursively(self, src.layout()),
+                    /*reset_provenance_and_padding*/ true,
+                )?;
+            }
             self.validate_operand(
-                &dest.to_op(self)?,
+                &dest,
                 M::enforce_validity_recursively(self, dest.layout()),
+                /*reset_provenance_and_padding*/ true,
             )?;
         }
 
@@ -843,7 +844,7 @@ where
     #[instrument(skip(self), level = "trace")]
     fn copy_op_no_validate(
         &mut self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
         allow_transmute: bool,
     ) -> InterpResult<'tcx> {
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 26b7251f6db..fb24f983ca9 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -4,6 +4,7 @@
 //! That's useful because it means other passes (e.g. promotion) can rely on `const`s
 //! to be const-safe.
 
+use std::borrow::Cow;
 use std::fmt::Write;
 use std::hash::Hash;
 use std::num::NonZero;
@@ -16,22 +17,22 @@ use rustc_hir as hir;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::ValidationErrorKind::{self, *};
 use rustc_middle::mir::interpret::{
-    ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
+    alloc_range, ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
     UnsupportedOpInfo, ValidationErrorInfo,
 };
-use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::{
-    Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
+    Abi, FieldIdx, FieldsShape, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
 };
 use tracing::trace;
 
 use super::machine::AllocMap;
 use super::{
     err_ub, format_interp_error, throw_ub, AllocId, AllocKind, CheckInAllocMsg, GlobalAlloc, ImmTy,
-    Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Pointer, Projectable,
-    Scalar, ValueVisitor,
+    Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, PlaceTy, Pointer,
+    Projectable, Scalar, ValueVisitor,
 };
 
 // for the validation errors
@@ -125,6 +126,7 @@ pub enum PathElem {
     EnumTag,
     CoroutineTag,
     DynDowncast,
+    Vtable,
 }
 
 /// Extra things to check for during validation of CTFE results.
@@ -163,22 +165,22 @@ impl<T: Clone + Eq + Hash + std::fmt::Debug, PATH: Default> RefTracking<T, PATH>
     pub fn empty() -> Self {
         RefTracking { seen: FxHashSet::default(), todo: vec![] }
     }
-    pub fn new(op: T) -> Self {
+    pub fn new(val: T) -> Self {
         let mut ref_tracking_for_consts =
-            RefTracking { seen: FxHashSet::default(), todo: vec![(op.clone(), PATH::default())] };
-        ref_tracking_for_consts.seen.insert(op);
+            RefTracking { seen: FxHashSet::default(), todo: vec![(val.clone(), PATH::default())] };
+        ref_tracking_for_consts.seen.insert(val);
         ref_tracking_for_consts
     }
     pub fn next(&mut self) -> Option<(T, PATH)> {
         self.todo.pop()
     }
 
-    fn track(&mut self, op: T, path: impl FnOnce() -> PATH) {
-        if self.seen.insert(op.clone()) {
-            trace!("Recursing below ptr {:#?}", op);
+    fn track(&mut self, val: T, path: impl FnOnce() -> PATH) {
+        if self.seen.insert(val.clone()) {
+            trace!("Recursing below ptr {:#?}", val);
             let path = path();
             // Remember to come back to this later.
-            self.todo.push((op, path));
+            self.todo.push((val, path));
         }
     }
 }
@@ -204,11 +206,62 @@ fn write_path(out: &mut String, path: &[PathElem]) {
             // not the root.
             Deref => write!(out, ".<deref>"),
             DynDowncast => write!(out, ".<dyn-downcast>"),
+            Vtable => write!(out, ".<vtable>"),
         }
         .unwrap()
     }
 }
 
+/// Represents a set of `Size` values as a sorted list of ranges.
+// These are (offset, length) pairs, and they are sorted and mutually disjoint,
+// and never adjacent (i.e. there's always a gap between two of them).
+#[derive(Debug, Clone)]
+pub struct RangeSet(Vec<(Size, Size)>);
+
+impl RangeSet {
+    fn add_range(&mut self, offset: Size, size: Size) {
+        if size.bytes() == 0 {
+            // No need to track empty ranges.
+            return;
+        }
+        let v = &mut self.0;
+        // We scan for a partition point where the left partition is all the elements that end
+        // strictly before we start. Those are elements that are too "low" to merge with us.
+        let idx =
+            v.partition_point(|&(other_offset, other_size)| other_offset + other_size < offset);
+        // Now we want to either merge with the first element of the second partition, or insert ourselves before that.
+        if let Some(&(other_offset, other_size)) = v.get(idx)
+            && offset + size >= other_offset
+        {
+            // Their end is >= our start (otherwise it would not be in the 2nd partition) and
+            // our end is >= their start. This means we can merge the ranges.
+            let new_start = other_offset.min(offset);
+            let mut new_end = (other_offset + other_size).max(offset + size);
+            // We grew to the right, so merge with overlapping/adjacent elements.
+            // (We also may have grown to the left, but that can never make us adjacent with
+            // anything there since we selected the first such candidate via `partition_point`.)
+            let mut scan_right = 1;
+            while let Some(&(next_offset, next_size)) = v.get(idx + scan_right)
+                && new_end >= next_offset
+            {
+                // Increase our size to absorb the next element.
+                new_end = new_end.max(next_offset + next_size);
+                // Look at the next element.
+                scan_right += 1;
+            }
+            // Update the element we grew.
+            v[idx] = (new_start, new_end - new_start);
+            // Remove the elements we absorbed (if any).
+            if scan_right > 1 {
+                drop(v.drain((idx + 1)..(idx + scan_right)));
+            }
+        } else {
+            // Insert new element.
+            v.insert(idx, (offset, size));
+        }
+    }
+}
+
 struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
     /// The `path` may be pushed to, but the part that is present when a function
     /// starts must not be changed!  `visit_fields` and `visit_array` rely on
@@ -217,7 +270,17 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
     ref_tracking: Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>>,
     /// `None` indicates this is not validating for CTFE (but for runtime).
     ctfe_mode: Option<CtfeValidationMode>,
-    ecx: &'rt InterpCx<'tcx, M>,
+    ecx: &'rt mut InterpCx<'tcx, M>,
+    /// Whether provenance should be reset outside of pointers (emulating the effect of a typed
+    /// copy).
+    reset_provenance_and_padding: bool,
+    /// This tracks which byte ranges in this value contain data; the remaining bytes are padding.
+    /// The ideal representation here would be pointer-length pairs, but to keep things more compact
+    /// we only store a (range) set of offsets -- the base pointer is the same throughout the entire
+    /// visit, after all.
+    /// If this is `Some`, then `reset_provenance_and_padding` must be true (but not vice versa:
+    /// we might not track data vs padding bytes if the operand isn't stored in memory anyway).
+    data_bytes: Option<RangeSet>,
 }
 
 impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
@@ -287,8 +350,14 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
             // arrays/slices
             ty::Array(..) | ty::Slice(..) => PathElem::ArrayElem(field),
 
+            // dyn* vtables
+            ty::Dynamic(_, _, ty::DynKind::DynStar) if field == 1 => PathElem::Vtable,
+
             // dyn traits
-            ty::Dynamic(..) => PathElem::DynDowncast,
+            ty::Dynamic(..) => {
+                assert_eq!(field, 0);
+                PathElem::DynDowncast
+            }
 
             // nothing else has an aggregate layout
             _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", layout.ty),
@@ -314,11 +383,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
 
     fn read_immediate(
         &self,
-        op: &OpTy<'tcx, M::Provenance>,
+        val: &PlaceTy<'tcx, M::Provenance>,
         expected: ExpectedKind,
     ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         Ok(try_validation!(
-            self.ecx.read_immediate(op),
+            self.ecx.read_immediate(val),
             self.path,
             Ub(InvalidUninitBytes(None)) =>
                 Uninit { expected },
@@ -332,10 +401,40 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
 
     fn read_scalar(
         &self,
-        op: &OpTy<'tcx, M::Provenance>,
+        val: &PlaceTy<'tcx, M::Provenance>,
         expected: ExpectedKind,
     ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
-        Ok(self.read_immediate(op, expected)?.to_scalar())
+        Ok(self.read_immediate(val, expected)?.to_scalar())
+    }
+
+    fn deref_pointer(
+        &mut self,
+        val: &PlaceTy<'tcx, M::Provenance>,
+        expected: ExpectedKind,
+    ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
+        // Not using `ecx.deref_pointer` since we want to use our `read_immediate` wrapper.
+        let imm = self.read_immediate(val, expected)?;
+        // Reset provenance: ensure slice tail metadata does not preserve provenance,
+        // and ensure all pointers do not preserve partial provenance.
+        if self.reset_provenance_and_padding {
+            if matches!(imm.layout.abi, Abi::Scalar(..)) {
+                // A thin pointer. If it has provenance, we don't have to do anything.
+                // If it does not, ensure we clear the provenance in memory.
+                if matches!(imm.to_scalar(), Scalar::Int(..)) {
+                    self.ecx.clear_provenance(val)?;
+                }
+            } else {
+                // A wide pointer. This means we have to worry both about the pointer itself and the
+                // metadata. We do the lazy thing and just write back the value we got. Just
+                // clearing provenance in a targeted manner would be more efficient, but unless this
+                // is a perf hotspot it's just not worth the effort.
+                self.ecx.write_immediate_no_validate(*imm, val)?;
+            }
+            // The entire thing is data, not padding.
+            self.add_data_range_place(val);
+        }
+        // Now turn it into a place.
+        self.ecx.ref_to_mplace(&imm)
     }
 
     fn check_wide_ptr_meta(
@@ -376,11 +475,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
     /// Check a reference or `Box`.
     fn check_safe_pointer(
         &mut self,
-        value: &OpTy<'tcx, M::Provenance>,
+        value: &PlaceTy<'tcx, M::Provenance>,
         ptr_kind: PointerKind,
     ) -> InterpResult<'tcx> {
-        // Not using `deref_pointer` since we want to use our `read_immediate` wrapper.
-        let place = self.ecx.ref_to_mplace(&self.read_immediate(value, ptr_kind.into())?)?;
+        let place = self.deref_pointer(value, ptr_kind.into())?;
         // Handle wide pointers.
         // Check metadata early, for better diagnostics
         if place.layout.is_unsized() {
@@ -564,31 +662,39 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
     /// Note that not all of these have `FieldsShape::Primitive`, e.g. wide references.
     fn try_visit_primitive(
         &mut self,
-        value: &OpTy<'tcx, M::Provenance>,
+        value: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, bool> {
         // Go over all the primitive types
         let ty = value.layout.ty;
         match ty.kind() {
             ty::Bool => {
-                let value = self.read_scalar(value, ExpectedKind::Bool)?;
+                let scalar = self.read_scalar(value, ExpectedKind::Bool)?;
                 try_validation!(
-                    value.to_bool(),
+                    scalar.to_bool(),
                     self.path,
                     Ub(InvalidBool(..)) => ValidationErrorKind::InvalidBool {
-                        value: format!("{value:x}"),
+                        value: format!("{scalar:x}"),
                     }
                 );
+                if self.reset_provenance_and_padding {
+                    self.ecx.clear_provenance(value)?;
+                    self.add_data_range_place(value);
+                }
                 Ok(true)
             }
             ty::Char => {
-                let value = self.read_scalar(value, ExpectedKind::Char)?;
+                let scalar = self.read_scalar(value, ExpectedKind::Char)?;
                 try_validation!(
-                    value.to_char(),
+                    scalar.to_char(),
                     self.path,
                     Ub(InvalidChar(..)) => ValidationErrorKind::InvalidChar {
-                        value: format!("{value:x}"),
+                        value: format!("{scalar:x}"),
                     }
                 );
+                if self.reset_provenance_and_padding {
+                    self.ecx.clear_provenance(value)?;
+                    self.add_data_range_place(value);
+                }
                 Ok(true)
             }
             ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
@@ -602,11 +708,14 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                         ExpectedKind::Int
                     },
                 )?;
+                if self.reset_provenance_and_padding {
+                    self.ecx.clear_provenance(value)?;
+                    self.add_data_range_place(value);
+                }
                 Ok(true)
             }
             ty::RawPtr(..) => {
-                let place =
-                    self.ecx.ref_to_mplace(&self.read_immediate(value, ExpectedKind::RawPtr)?)?;
+                let place = self.deref_pointer(value, ExpectedKind::RawPtr)?;
                 if place.layout.is_unsized() {
                     self.check_wide_ptr_meta(place.meta(), place.layout)?;
                 }
@@ -617,11 +726,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                 Ok(true)
             }
             ty::FnPtr(..) => {
-                let value = self.read_scalar(value, ExpectedKind::FnPtr)?;
+                let scalar = self.read_scalar(value, ExpectedKind::FnPtr)?;
 
                 // If we check references recursively, also check that this points to a function.
                 if let Some(_) = self.ref_tracking {
-                    let ptr = value.to_pointer(self.ecx)?;
+                    let ptr = scalar.to_pointer(self.ecx)?;
                     let _fn = try_validation!(
                         self.ecx.get_ptr_fn(ptr),
                         self.path,
@@ -631,10 +740,18 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                     // FIXME: Check if the signature matches
                 } else {
                     // Otherwise (for standalone Miri), we have to still check it to be non-null.
-                    if self.ecx.scalar_may_be_null(value)? {
+                    if self.ecx.scalar_may_be_null(scalar)? {
                         throw_validation_failure!(self.path, NullFnPtr);
                     }
                 }
+                if self.reset_provenance_and_padding {
+                    // Make sure we do not preserve partial provenance. This matches the thin
+                    // pointer handling in `deref_pointer`.
+                    if matches!(scalar, Scalar::Int(..)) {
+                        self.ecx.clear_provenance(value)?;
+                    }
+                    self.add_data_range_place(value);
+                }
                 Ok(true)
             }
             ty::Never => throw_validation_failure!(self.path, NeverVal),
@@ -716,13 +833,178 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
         }
     }
 
-    fn in_mutable_memory(&self, op: &OpTy<'tcx, M::Provenance>) -> bool {
-        if let Some(mplace) = op.as_mplace_or_imm().left() {
+    fn in_mutable_memory(&self, val: &PlaceTy<'tcx, M::Provenance>) -> bool {
+        if let Some(mplace) = val.as_mplace_or_local().left() {
             if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) {
-                return mutability(self.ecx, alloc_id).is_mut();
+                mutability(self.ecx, alloc_id).is_mut()
+            } else {
+                // No memory at all.
+                false
+            }
+        } else {
+            // A local variable -- definitely mutable.
+            true
+        }
+    }
+
+    /// Add the given pointer-length pair to the "data" range of this visit.
+    fn add_data_range(&mut self, ptr: Pointer<Option<M::Provenance>>, size: Size) {
+        if let Some(data_bytes) = self.data_bytes.as_mut() {
+            // We only have to store the offset, the rest is the same for all pointers here.
+            let (_prov, offset) = ptr.into_parts();
+            // Add this.
+            data_bytes.add_range(offset, size);
+        };
+    }
+
+    /// Add the entire given place to the "data" range of this visit.
+    fn add_data_range_place(&mut self, place: &PlaceTy<'tcx, M::Provenance>) {
+        // Only sized places can be added this way.
+        debug_assert!(place.layout.abi.is_sized());
+        if let Some(data_bytes) = self.data_bytes.as_mut() {
+            let offset = Self::data_range_offset(self.ecx, place);
+            data_bytes.add_range(offset, place.layout.size);
+        }
+    }
+
+    /// Convert a place into the offset it starts at, for the purpose of data_range tracking.
+    /// Must only be called if `data_bytes` is `Some(_)`.
+    fn data_range_offset(ecx: &InterpCx<'tcx, M>, place: &PlaceTy<'tcx, M::Provenance>) -> Size {
+        // The presence of `data_bytes` implies that our place is in memory.
+        let ptr = ecx
+            .place_to_op(place)
+            .expect("place must be in memory")
+            .as_mplace_or_imm()
+            .expect_left("place must be in memory")
+            .ptr();
+        let (_prov, offset) = ptr.into_parts();
+        offset
+    }
+
+    fn reset_padding(&mut self, place: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
+        let Some(data_bytes) = self.data_bytes.as_mut() else { return Ok(()) };
+        // Our value must be in memory, otherwise we would not have set up `data_bytes`.
+        let mplace = self.ecx.force_allocation(place)?;
+        // Determine starting offset and size.
+        let (_prov, start_offset) = mplace.ptr().into_parts();
+        let (size, _align) = self
+            .ecx
+            .size_and_align_of_mplace(&mplace)?
+            .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
+        // If there is no padding at all, we can skip the rest: check for
+        // a single data range covering the entire value.
+        if data_bytes.0 == &[(start_offset, size)] {
+            return Ok(());
+        }
+        // Get a handle for the allocation. Do this only once, to avoid looking up the same
+        // allocation over and over again. (Though to be fair, iterating the value already does
+        // exactly that.)
+        let Some(mut alloc) = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)? else {
+            // A ZST, no padding to clear.
+            return Ok(());
+        };
+        // Add a "finalizer" data range at the end, so that the iteration below finds all gaps
+        // between ranges.
+        data_bytes.0.push((start_offset + size, Size::ZERO));
+        // Iterate, and reset gaps.
+        let mut padding_cleared_until = start_offset;
+        for &(offset, size) in data_bytes.0.iter() {
+            assert!(
+                offset >= padding_cleared_until,
+                "reset_padding on {}: previous field ended at offset {}, next field starts at {} (and has a size of {} bytes)",
+                mplace.layout.ty,
+                (padding_cleared_until - start_offset).bytes(),
+                (offset - start_offset).bytes(),
+                size.bytes(),
+            );
+            if offset > padding_cleared_until {
+                // We found padding. Adjust the range to be relative to `alloc`, and make it uninit.
+                let padding_start = padding_cleared_until - start_offset;
+                let padding_size = offset - padding_cleared_until;
+                let range = alloc_range(padding_start, padding_size);
+                trace!("reset_padding on {}: resetting padding range {range:?}", mplace.layout.ty);
+                alloc.write_uninit(range)?;
+            }
+            padding_cleared_until = offset + size;
+        }
+        assert!(padding_cleared_until == start_offset + size);
+        Ok(())
+    }
+
+    /// Computes the data range of this union type:
+    /// which bytes are inside a field (i.e., not padding.)
+    fn union_data_range<'e>(
+        ecx: &'e mut InterpCx<'tcx, M>,
+        layout: TyAndLayout<'tcx>,
+    ) -> Cow<'e, RangeSet> {
+        assert!(layout.ty.is_union());
+        assert!(layout.abi.is_sized(), "there are no unsized unions");
+        let layout_cx = LayoutCx { tcx: *ecx.tcx, param_env: ecx.param_env };
+        return M::cached_union_data_range(ecx, layout.ty, || {
+            let mut out = RangeSet(Vec::new());
+            union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out);
+            out
+        });
+
+        /// Helper for recursive traversal: add data ranges of the given type to `out`.
+        fn union_data_range_uncached<'tcx>(
+            cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+            layout: TyAndLayout<'tcx>,
+            base_offset: Size,
+            out: &mut RangeSet,
+        ) {
+            // If this is a ZST, we don't contain any data. In particular, this helps us to quickly
+            // skip over huge arrays of ZST.
+            if layout.is_zst() {
+                return;
+            }
+            // Just recursively add all the fields of everything to the output.
+            match &layout.fields {
+                FieldsShape::Primitive => {
+                    out.add_range(base_offset, layout.size);
+                }
+                &FieldsShape::Union(fields) => {
+                    // Currently, all fields start at offset 0 (relative to `base_offset`).
+                    for field in 0..fields.get() {
+                        let field = layout.field(cx, field);
+                        union_data_range_uncached(cx, field, base_offset, out);
+                    }
+                }
+                &FieldsShape::Array { stride, count } => {
+                    let elem = layout.field(cx, 0);
+
+                    // Fast-path for large arrays of simple types that do not contain any padding.
+                    if elem.abi.is_scalar() {
+                        out.add_range(base_offset, elem.size * count);
+                    } else {
+                        for idx in 0..count {
+                            // This repeats the same computation for every array element... but the alternative
+                            // is to allocate temporary storage for a dedicated `out` set for the array element,
+                            // and replicating that N times. Is that better?
+                            union_data_range_uncached(cx, elem, base_offset + idx * stride, out);
+                        }
+                    }
+                }
+                FieldsShape::Arbitrary { offsets, .. } => {
+                    for (field, &offset) in offsets.iter_enumerated() {
+                        let field = layout.field(cx, field.as_usize());
+                        union_data_range_uncached(cx, field, base_offset + offset, out);
+                    }
+                }
+            }
+            // Don't forget potential other variants.
+            match &layout.variants {
+                Variants::Single { .. } => {
+                    // Fully handled above.
+                }
+                Variants::Multiple { variants, .. } => {
+                    for variant in variants.indices() {
+                        let variant = layout.for_variant(cx, variant);
+                        union_data_range_uncached(cx, variant, base_offset, out);
+                    }
+                }
             }
         }
-        false
     }
 }
 
@@ -774,7 +1056,7 @@ fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId)
 }
 
 impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, 'tcx, M> {
-    type V = OpTy<'tcx, M::Provenance>;
+    type V = PlaceTy<'tcx, M::Provenance>;
 
     #[inline(always)]
     fn ecx(&self) -> &InterpCx<'tcx, M> {
@@ -783,11 +1065,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
 
     fn read_discriminant(
         &mut self,
-        op: &OpTy<'tcx, M::Provenance>,
+        val: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, VariantIdx> {
         self.with_elem(PathElem::EnumTag, move |this| {
             Ok(try_validation!(
-                this.ecx.read_discriminant(op),
+                this.ecx.read_discriminant(val),
                 this.path,
                 Ub(InvalidTag(val)) => InvalidEnumTag {
                     value: format!("{val:x}"),
@@ -802,44 +1084,54 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
     #[inline]
     fn visit_field(
         &mut self,
-        old_op: &OpTy<'tcx, M::Provenance>,
+        old_val: &PlaceTy<'tcx, M::Provenance>,
         field: usize,
-        new_op: &OpTy<'tcx, M::Provenance>,
+        new_val: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
-        let elem = self.aggregate_field_path_elem(old_op.layout, field);
-        self.with_elem(elem, move |this| this.visit_value(new_op))
+        let elem = self.aggregate_field_path_elem(old_val.layout, field);
+        self.with_elem(elem, move |this| this.visit_value(new_val))
     }
 
     #[inline]
     fn visit_variant(
         &mut self,
-        old_op: &OpTy<'tcx, M::Provenance>,
+        old_val: &PlaceTy<'tcx, M::Provenance>,
         variant_id: VariantIdx,
-        new_op: &OpTy<'tcx, M::Provenance>,
+        new_val: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
-        let name = match old_op.layout.ty.kind() {
+        let name = match old_val.layout.ty.kind() {
             ty::Adt(adt, _) => PathElem::Variant(adt.variant(variant_id).name),
             // Coroutines also have variants
             ty::Coroutine(..) => PathElem::CoroutineState(variant_id),
-            _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty),
+            _ => bug!("Unexpected type with variant: {:?}", old_val.layout.ty),
         };
-        self.with_elem(name, move |this| this.visit_value(new_op))
+        self.with_elem(name, move |this| this.visit_value(new_val))
     }
 
     #[inline(always)]
     fn visit_union(
         &mut self,
-        op: &OpTy<'tcx, M::Provenance>,
+        val: &PlaceTy<'tcx, M::Provenance>,
         _fields: NonZero<usize>,
     ) -> InterpResult<'tcx> {
         // Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory.
         if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
-            if !op.layout.is_zst() && !op.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) {
-                if !self.in_mutable_memory(op) {
+            if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) {
+                if !self.in_mutable_memory(val) {
                     throw_validation_failure!(self.path, UnsafeCellInImmutable);
                 }
             }
         }
+        if self.reset_provenance_and_padding
+            && let Some(data_bytes) = self.data_bytes.as_mut()
+        {
+            let base_offset = Self::data_range_offset(self.ecx, val);
+            // Determine and add data range for this union.
+            let union_data_range = Self::union_data_range(self.ecx, val.layout);
+            for &(offset, size) in union_data_range.0.iter() {
+                data_bytes.add_range(base_offset + offset, size);
+            }
+        }
         Ok(())
     }
 
@@ -847,39 +1139,41 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
     fn visit_box(
         &mut self,
         _box_ty: Ty<'tcx>,
-        op: &OpTy<'tcx, M::Provenance>,
+        val: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
-        self.check_safe_pointer(op, PointerKind::Box)?;
+        self.check_safe_pointer(val, PointerKind::Box)?;
         Ok(())
     }
 
     #[inline]
-    fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
-        trace!("visit_value: {:?}, {:?}", *op, op.layout);
+    fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
+        trace!("visit_value: {:?}, {:?}", *val, val.layout);
 
         // Check primitive types -- the leaves of our recursive descent.
+        // This is called even for enum discriminants (which are "fields" of their enum),
+        // so for integer-typed discriminants the provenance reset will happen here.
         // We assume that the Scalar validity range does not restrict these values
         // any further than `try_visit_primitive` does!
-        if self.try_visit_primitive(op)? {
+        if self.try_visit_primitive(val)? {
             return Ok(());
         }
 
         // Special check preventing `UnsafeCell` in the inner part of constants
         if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
-            if !op.layout.is_zst()
-                && let Some(def) = op.layout.ty.ty_adt_def()
+            if !val.layout.is_zst()
+                && let Some(def) = val.layout.ty.ty_adt_def()
                 && def.is_unsafe_cell()
             {
-                if !self.in_mutable_memory(op) {
+                if !self.in_mutable_memory(val) {
                     throw_validation_failure!(self.path, UnsafeCellInImmutable);
                 }
             }
         }
 
         // Recursively walk the value at its type. Apply optimizations for some large types.
-        match op.layout.ty.kind() {
+        match val.layout.ty.kind() {
             ty::Str => {
-                let mplace = op.assert_mem_place(); // strings are unsized and hence never immediate
+                let mplace = val.assert_mem_place(); // strings are unsized and hence never immediate
                 let len = mplace.len(self.ecx)?;
                 try_validation!(
                     self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr(), Size::from_bytes(len)),
@@ -889,11 +1183,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
                 );
             }
             ty::Array(tys, ..) | ty::Slice(tys)
-                // This optimization applies for types that can hold arbitrary bytes (such as
-                // integer and floating point types) or for structs or tuples with no fields.
-                // FIXME(wesleywiser) This logic could be extended further to arbitrary structs
-                // or tuples made up of integer/floating point types or inhabited ZSTs with no
-                // padding.
+                // This optimization applies for types that can hold arbitrary non-provenance bytes (such as
+                // integer and floating point types).
+                // FIXME(wesleywiser) This logic could be extended further to arbitrary structs or
+                // tuples made up of integer/floating point types or inhabited ZSTs with no padding.
                 if matches!(tys.kind(), ty::Int(..) | ty::Uint(..) | ty::Float(..))
                 =>
             {
@@ -901,18 +1194,19 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
                 // Optimized handling for arrays of integer/float type.
 
                 // This is the length of the array/slice.
-                let len = op.len(self.ecx)?;
+                let len = val.len(self.ecx)?;
                 // This is the element type size.
                 let layout = self.ecx.layout_of(*tys)?;
                 // This is the size in bytes of the whole array. (This checks for overflow.)
                 let size = layout.size * len;
                 // If the size is 0, there is nothing to check.
-                // (`size` can only be 0 of `len` is 0, and empty arrays are always valid.)
+                // (`size` can only be 0 if `len` is 0, and empty arrays are always valid.)
                 if size == Size::ZERO {
                     return Ok(());
                 }
-                // Now that we definitely have a non-ZST array, we know it lives in memory.
-                let mplace = match op.as_mplace_or_imm() {
+                // Now that we definitely have a non-ZST array, we know it lives in memory -- except it may
+                // be an uninitialized local variable, those are also "immediate".
+                let mplace = match val.to_op(self.ecx)?.as_mplace_or_imm() {
                     Left(mplace) => mplace,
                     Right(imm) => match *imm {
                         Immediate::Uninit =>
@@ -958,20 +1252,30 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
                         }
                     }
                 }
+
+                // Don't forget that these are all non-pointer types, and thus do not preserve
+                // provenance.
+                if self.reset_provenance_and_padding {
+                    // We can't share this with above as above, we might be looking at read-only memory.
+                    let mut alloc = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)?.expect("we already excluded size 0");
+                    alloc.clear_provenance()?;
+                    // Also, mark this as containing data, not padding.
+                    self.add_data_range(mplace.ptr(), size);
+                }
             }
             // Fast path for arrays and slices of ZSTs. We only need to check a single ZST element
             // of an array and not all of them, because there's only a single value of a specific
             // ZST type, so either validation fails for all elements or none.
             ty::Array(tys, ..) | ty::Slice(tys) if self.ecx.layout_of(*tys)?.is_zst() => {
                 // Validate just the first element (if any).
-                if op.len(self.ecx)? > 0 {
-                    self.visit_field(op, 0, &self.ecx.project_index(op, 0)?)?;
+                if val.len(self.ecx)? > 0 {
+                    self.visit_field(val, 0, &self.ecx.project_index(val, 0)?)?;
                 }
             }
             _ => {
                 // default handler
                 try_validation!(
-                    self.walk_value(op),
+                    self.walk_value(val),
                     self.path,
                     // It's not great to catch errors here, since we can't give a very good path,
                     // but it's better than ICEing.
@@ -992,15 +1296,15 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
         // FIXME: We could avoid some redundant checks here. For newtypes wrapping
         // scalars, we do the same check on every "level" (e.g., first we check
         // MyNewtype and then the scalar in there).
-        match op.layout.abi {
+        match val.layout.abi {
             Abi::Uninhabited => {
-                let ty = op.layout.ty;
+                let ty = val.layout.ty;
                 throw_validation_failure!(self.path, UninhabitedVal { ty });
             }
             Abi::Scalar(scalar_layout) => {
                 if !scalar_layout.is_uninit_valid() {
                     // There is something to check here.
-                    let scalar = self.read_scalar(op, ExpectedKind::InitScalar)?;
+                    let scalar = self.read_scalar(val, ExpectedKind::InitScalar)?;
                     self.visit_scalar(scalar, scalar_layout)?;
                 }
             }
@@ -1010,7 +1314,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
                 // the other must be init.
                 if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
                     let (a, b) =
-                        self.read_immediate(op, ExpectedKind::InitScalar)?.to_scalar_pair();
+                        self.read_immediate(val, ExpectedKind::InitScalar)?.to_scalar_pair();
                     self.visit_scalar(a, a_layout)?;
                     self.visit_scalar(b, b_layout)?;
                 }
@@ -1031,19 +1335,34 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
 
 impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     fn validate_operand_internal(
-        &self,
-        op: &OpTy<'tcx, M::Provenance>,
+        &mut self,
+        val: &PlaceTy<'tcx, M::Provenance>,
         path: Vec<PathElem>,
         ref_tracking: Option<&mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>>,
         ctfe_mode: Option<CtfeValidationMode>,
+        reset_provenance_and_padding: bool,
     ) -> InterpResult<'tcx> {
-        trace!("validate_operand_internal: {:?}, {:?}", *op, op.layout.ty);
-
-        // Construct a visitor
-        let mut visitor = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx: self };
+        trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty);
 
-        // Run it.
-        match self.run_for_validation(|| visitor.visit_value(op)) {
+        // Run the visitor.
+        match self.run_for_validation(|ecx| {
+            let reset_padding = reset_provenance_and_padding && {
+                // Check if `val` is actually stored in memory. If not, padding is not even
+                // represented and we need not reset it.
+                ecx.place_to_op(val)?.as_mplace_or_imm().is_left()
+            };
+            let mut v = ValidityVisitor {
+                path,
+                ref_tracking,
+                ctfe_mode,
+                ecx,
+                reset_provenance_and_padding,
+                data_bytes: reset_padding.then_some(RangeSet(Vec::new())),
+            };
+            v.visit_value(val)?;
+            v.reset_padding(val)?;
+            InterpResult::Ok(())
+        }) {
             Ok(()) => Ok(()),
             // Pass through validation failures and "invalid program" issues.
             Err(err)
@@ -1079,13 +1398,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     /// - no `UnsafeCell` or non-ZST `&mut`.
     #[inline(always)]
     pub(crate) fn const_validate_operand(
-        &self,
-        op: &OpTy<'tcx, M::Provenance>,
+        &mut self,
+        val: &PlaceTy<'tcx, M::Provenance>,
         path: Vec<PathElem>,
         ref_tracking: &mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>,
         ctfe_mode: CtfeValidationMode,
     ) -> InterpResult<'tcx> {
-        self.validate_operand_internal(op, path, Some(ref_tracking), Some(ctfe_mode))
+        self.validate_operand_internal(
+            val,
+            path,
+            Some(ref_tracking),
+            Some(ctfe_mode),
+            /*reset_provenance*/ false,
+        )
     }
 
     /// This function checks the data at `op` to be runtime-valid.
@@ -1093,21 +1418,41 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     /// It will error if the bits at the destination do not match the ones described by the layout.
     #[inline(always)]
     pub fn validate_operand(
-        &self,
-        op: &OpTy<'tcx, M::Provenance>,
+        &mut self,
+        val: &PlaceTy<'tcx, M::Provenance>,
         recursive: bool,
+        reset_provenance_and_padding: bool,
     ) -> InterpResult<'tcx> {
         // Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's
         // still correct to not use `ctfe_mode`: that mode is for validation of the final constant
         // value, it rules out things like `UnsafeCell` in awkward places.
         if !recursive {
-            return self.validate_operand_internal(op, vec![], None, None);
+            return self.validate_operand_internal(
+                val,
+                vec![],
+                None,
+                None,
+                reset_provenance_and_padding,
+            );
         }
         // Do a recursive check.
         let mut ref_tracking = RefTracking::empty();
-        self.validate_operand_internal(op, vec![], Some(&mut ref_tracking), None)?;
+        self.validate_operand_internal(
+            val,
+            vec![],
+            Some(&mut ref_tracking),
+            None,
+            reset_provenance_and_padding,
+        )?;
         while let Some((mplace, path)) = ref_tracking.todo.pop() {
-            self.validate_operand_internal(&mplace.into(), path, Some(&mut ref_tracking), None)?;
+            // Things behind reference do *not* have the provenance reset.
+            self.validate_operand_internal(
+                &mplace.into(),
+                path,
+                Some(&mut ref_tracking),
+                None,
+                /*reset_provenance_and_padding*/ false,
+            )?;
         }
         Ok(())
     }
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index b02f12e3c7f..d8af67bd0e7 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -5,6 +5,7 @@ use std::num::NonZero;
 
 use rustc_index::IndexVec;
 use rustc_middle::mir::interpret::InterpResult;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::{FieldIdx, FieldsShape, VariantIdx, Variants};
 use tracing::trace;
@@ -82,6 +83,7 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
         self.visit_value(new_val)
     }
 
+    /// Traversal logic; should not be overloaded.
     fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx> {
         let ty = v.layout().ty;
         trace!("walk_value: type: {ty}");
@@ -104,6 +106,17 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
                 // DynStar types. Very different from a dyn type (but strangely part of the
                 // same variant in `TyKind`): These are pairs where the 2nd component is the
                 // vtable, and the first component is the data (which must be ptr-sized).
+
+                // First make sure the vtable can be read at its type.
+                // The type of this vtable is fake, it claims to be a reference to some actual memory but that isn't true.
+                // So we transmute it to a raw pointer.
+                let raw_ptr_ty = Ty::new_mut_ptr(*self.ecx().tcx, self.ecx().tcx.types.unit);
+                let raw_ptr_ty = self.ecx().layout_of(raw_ptr_ty)?;
+                let vtable_field =
+                    self.ecx().project_field(v, 1)?.transmute(raw_ptr_ty, self.ecx())?;
+                self.visit_field(v, 1, &vtable_field)?;
+
+                // Then unpack the first field, and continue.
                 let data = self.ecx().unpack_dyn_star(v, data)?;
                 return self.visit_field(v, 0, &data);
             }
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index cbd1fdeea2a..611a8e1a884 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -4,7 +4,7 @@ use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
 use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
 
 use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
-use crate::interpret::{InterpCx, MemoryKind, OpTy};
+use crate::interpret::{InterpCx, MemoryKind};
 
 /// Determines if this type permits "raw" initialization by just transmuting some memory into an
 /// instance of `T`.
@@ -32,15 +32,15 @@ pub fn check_validity_requirement<'tcx>(
 
     let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
     if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
-        might_permit_raw_init_strict(layout, &layout_cx, kind)
+        check_validity_requirement_strict(layout, &layout_cx, kind)
     } else {
-        might_permit_raw_init_lax(layout, &layout_cx, kind)
+        check_validity_requirement_lax(layout, &layout_cx, kind)
     }
 }
 
-/// Implements the 'strict' version of the `might_permit_raw_init` checks; see that function for
-/// details.
-fn might_permit_raw_init_strict<'tcx>(
+/// Implements the 'strict' version of the [`check_validity_requirement`] checks; see that function
+/// for details.
+fn check_validity_requirement_strict<'tcx>(
     ty: TyAndLayout<'tcx>,
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     kind: ValidityRequirement,
@@ -61,18 +61,24 @@ fn might_permit_raw_init_strict<'tcx>(
         .expect("failed to write bytes for zero valid check");
     }
 
-    let ot: OpTy<'_, _> = allocated.into();
-
     // Assume that if it failed, it's a validation failure.
     // This does *not* actually check that references are dereferenceable, but since all types that
     // require dereferenceability also require non-null, we don't actually get any false negatives
     // due to this.
-    Ok(cx.validate_operand(&ot, /*recursive*/ false).is_ok())
+    // The value we are validating is temporary and discarded at the end of this function, so
+    // there is no point in reseting provenance and padding.
+    Ok(cx
+        .validate_operand(
+            &allocated.into(),
+            /*recursive*/ false,
+            /*reset_provenance_and_padding*/ false,
+        )
+        .is_ok())
 }
 
-/// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for
-/// details.
-fn might_permit_raw_init_lax<'tcx>(
+/// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that
+/// function for details.
+fn check_validity_requirement_lax<'tcx>(
     this: TyAndLayout<'tcx>,
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     init_kind: ValidityRequirement,
@@ -137,7 +143,7 @@ fn might_permit_raw_init_lax<'tcx>(
         }
         FieldsShape::Arbitrary { offsets, .. } => {
             for idx in 0..offsets.len() {
-                if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind)? {
+                if !check_validity_requirement_lax(this.field(cx, idx), cx, init_kind)? {
                     // We found a field that is unhappy with this kind of initialization.
                     return Ok(false);
                 }
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index c973fcec0e1..74225d646bd 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -222,10 +222,8 @@ impl<'tcx> PrintExtra<'tcx> {
 }
 
 pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
-    if ppm.needs_analysis() {
-        if ex.tcx().analysis(()).is_err() {
-            FatalError.raise();
-        }
+    if ppm.needs_analysis() && ex.tcx().analysis(()).is_err() {
+        FatalError.raise();
     }
 
     let (src, src_name) = get_source(sess);
diff --git a/compiler/rustc_error_codes/src/error_codes/E0074.md b/compiler/rustc_error_codes/src/error_codes/E0074.md
index 785d6de226d..71d89f5eb60 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0074.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0074.md
@@ -11,7 +11,7 @@ This will cause an error:
 #![feature(repr_simd)]
 
 #[repr(simd)]
-struct Bad<T>(T, T, T, T);
+struct Bad<T>([T; 4]);
 ```
 
 This will not:
@@ -20,5 +20,5 @@ This will not:
 #![feature(repr_simd)]
 
 #[repr(simd)]
-struct Good(u32, u32, u32, u32);
+struct Good([u32; 4]);
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0075.md b/compiler/rustc_error_codes/src/error_codes/E0075.md
index 969c1ee7131..b58018eafc3 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0075.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0075.md
@@ -1,6 +1,6 @@
-A `#[simd]` attribute was applied to an empty tuple struct.
+A `#[simd]` attribute was applied to an empty or multi-field struct.
 
-Erroneous code example:
+Erroneous code examples:
 
 ```compile_fail,E0075
 #![feature(repr_simd)]
@@ -9,9 +9,15 @@ Erroneous code example:
 struct Bad; // error!
 ```
 
-The `#[simd]` attribute can only be applied to non empty tuple structs, because
-it doesn't make sense to try to use SIMD operations when there are no values to
-operate on.
+```compile_fail,E0075
+#![feature(repr_simd)]
+
+#[repr(simd)]
+struct Bad([u32; 1], [u32; 1]); // error!
+```
+
+The `#[simd]` attribute can only be applied to a single-field struct, because
+the one field must be the array of values in the vector.
 
 Fixed example:
 
@@ -19,5 +25,5 @@ Fixed example:
 #![feature(repr_simd)]
 
 #[repr(simd)]
-struct Good(u32); // ok!
+struct Good([u32; 2]); // ok!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0076.md b/compiler/rustc_error_codes/src/error_codes/E0076.md
index 1da8caa9506..b1943de63e5 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0076.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0076.md
@@ -1,4 +1,4 @@
-All types in a tuple struct aren't the same when using the `#[simd]`
+The type of the field in a tuple struct isn't an array when using the `#[simd]`
 attribute.
 
 Erroneous code example:
@@ -7,12 +7,12 @@ Erroneous code example:
 #![feature(repr_simd)]
 
 #[repr(simd)]
-struct Bad(u16, u32, u32 u32); // error!
+struct Bad(u16); // error!
 ```
 
 When using the `#[simd]` attribute to automatically use SIMD operations in tuple
-struct, the types in the struct must all be of the same type, or the compiler
-will trigger this error.
+structs, if you want a single-lane vector then the field must be a 1-element
+array, or the compiler will trigger this error.
 
 Fixed example:
 
@@ -20,5 +20,5 @@ Fixed example:
 #![feature(repr_simd)]
 
 #[repr(simd)]
-struct Good(u32, u32, u32, u32); // ok!
+struct Good([u16; 1]); // ok!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0077.md b/compiler/rustc_error_codes/src/error_codes/E0077.md
index 91aa24d1f52..688bfd3e727 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0077.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0077.md
@@ -7,7 +7,7 @@ Erroneous code example:
 #![feature(repr_simd)]
 
 #[repr(simd)]
-struct Bad(String); // error!
+struct Bad([String; 2]); // error!
 ```
 
 When using the `#[simd]` attribute on a tuple struct, the elements in the tuple
@@ -19,5 +19,5 @@ Fixed example:
 #![feature(repr_simd)]
 
 #[repr(simd)]
-struct Good(u32, u32, u32, u32); // ok!
+struct Good([u32; 4]); // ok!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0511.md b/compiler/rustc_error_codes/src/error_codes/E0511.md
index 681f4e611c3..45ff49bdebb 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0511.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0511.md
@@ -23,11 +23,11 @@ The generic type has to be a SIMD type. Example:
 
 #[repr(simd)]
 #[derive(Copy, Clone)]
-struct i32x2(i32, i32);
+struct i32x2([i32; 2]);
 
 extern "rust-intrinsic" {
     fn simd_add<T>(a: T, b: T) -> T;
 }
 
-unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok!
+unsafe { simd_add(i32x2([0, 0]), i32x2([1, 2])); } // ok!
 ```
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 1c39840207c..7a4d8dba179 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -8,11 +8,11 @@ use std::thread::panicking;
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_error_messages::{fluent_value_from_str_list_sep_by_and, FluentValue};
-use rustc_lint_defs::{Applicability, LintExpectationId};
+use rustc_lint_defs::Applicability;
 use rustc_macros::{Decodable, Encodable};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Symbol;
-use rustc_span::{AttrId, Span, DUMMY_SP};
+use rustc_span::{Span, DUMMY_SP};
 use tracing::debug;
 
 use crate::snippet::Style;
@@ -354,26 +354,6 @@ impl DiagInner {
         }
     }
 
-    pub(crate) fn update_unstable_expectation_id(
-        &mut self,
-        unstable_to_stable: &FxIndexMap<AttrId, LintExpectationId>,
-    ) {
-        if let Level::Expect(expectation_id) | Level::ForceWarning(Some(expectation_id)) =
-            &mut self.level
-            && let LintExpectationId::Unstable { attr_id, lint_index } = *expectation_id
-        {
-            // The unstable to stable map only maps the unstable `AttrId` to a stable `HirId` with an attribute index.
-            // The lint index inside the attribute is manually transferred here.
-            let Some(stable_id) = unstable_to_stable.get(&attr_id) else {
-                panic!("{expectation_id:?} must have a matching stable id")
-            };
-
-            let mut stable_id = *stable_id;
-            stable_id.set_lint_index(lint_index);
-            *expectation_id = stable_id;
-        }
-    }
-
     /// Indicates whether this diagnostic should show up in cargo's future breakage report.
     pub(crate) fn has_future_breakage(&self) -> bool {
         matches!(self.is_lint, Some(IsLint { has_future_breakage: true, .. }))
@@ -701,10 +681,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
             " ".repeat(expected_padding),
             expected_label
         ))];
-        msg.extend(expected.0.into_iter());
+        msg.extend(expected.0);
         msg.push(StringPart::normal(format!("`{expected_extra}\n")));
         msg.push(StringPart::normal(format!("{}{} `", " ".repeat(found_padding), found_label)));
-        msg.extend(found.0.into_iter());
+        msg.extend(found.0);
         msg.push(StringPart::normal(format!("`{found_extra}")));
 
         // For now, just attach these as notes.
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 02ead41fc68..13da1721a4a 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -69,7 +69,7 @@ use rustc_macros::{Decodable, Encodable};
 pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
 use rustc_span::source_map::SourceMap;
 pub use rustc_span::ErrorGuaranteed;
-use rustc_span::{AttrId, Loc, Span, DUMMY_SP};
+use rustc_span::{Loc, Span, DUMMY_SP};
 pub use snippet::Style;
 // Used by external projects such as `rust-gpu`.
 // See https://github.com/rust-lang/rust/pull/115393.
@@ -497,28 +497,18 @@ struct DiagCtxtInner {
 
     future_breakage_diagnostics: Vec<DiagInner>,
 
-    /// The [`Self::unstable_expect_diagnostics`] should be empty when this struct is
-    /// dropped. However, it can have values if the compilation is stopped early
-    /// or is only partially executed. To avoid ICEs, like in rust#94953 we only
-    /// check if [`Self::unstable_expect_diagnostics`] is empty, if the expectation ids
-    /// have been converted.
-    check_unstable_expect_diagnostics: bool,
-
-    /// Expected [`DiagInner`][struct@diagnostic::DiagInner]s store a [`LintExpectationId`] as part
-    /// of the lint level. [`LintExpectationId`]s created early during the compilation
-    /// (before `HirId`s have been defined) are not stable and can therefore not be
-    /// stored on disk. This buffer stores these diagnostics until the ID has been
-    /// replaced by a stable [`LintExpectationId`]. The [`DiagInner`][struct@diagnostic::DiagInner]s
-    /// are submitted for storage and added to the list of fulfilled expectations.
-    unstable_expect_diagnostics: Vec<DiagInner>,
-
     /// expected diagnostic will have the level `Expect` which additionally
     /// carries the [`LintExpectationId`] of the expectation that can be
     /// marked as fulfilled. This is a collection of all [`LintExpectationId`]s
     /// that have been marked as fulfilled this way.
     ///
+    /// Emitting expectations after having stolen this field can happen. In particular, an
+    /// `#[expect(warnings)]` can easily make the `UNFULFILLED_LINT_EXPECTATIONS` lint expect
+    /// itself. To avoid needless complexity in this corner case, we tolerate failing to track
+    /// those expectations.
+    ///
     /// [RFC-2383]: https://rust-lang.github.io/rfcs/2383-lint-reasons.html
-    fulfilled_expectations: FxHashSet<LintExpectationId>,
+    fulfilled_expectations: FxIndexSet<LintExpectationId>,
 
     /// The file where the ICE information is stored. This allows delayed_span_bug backtraces to be
     /// stored along side the main panic backtrace.
@@ -605,13 +595,6 @@ impl Drop for DiagCtxtInner {
                 );
             }
         }
-
-        if self.check_unstable_expect_diagnostics {
-            assert!(
-                self.unstable_expect_diagnostics.is_empty(),
-                "all diagnostics with unstable expectations should have been converted",
-            );
-        }
     }
 }
 
@@ -740,8 +723,6 @@ impl DiagCtxt {
             emitted_diagnostics,
             stashed_diagnostics,
             future_breakage_diagnostics,
-            check_unstable_expect_diagnostics,
-            unstable_expect_diagnostics,
             fulfilled_expectations,
             ice_file: _,
         } = inner.deref_mut();
@@ -761,8 +742,6 @@ impl DiagCtxt {
         *emitted_diagnostics = Default::default();
         *stashed_diagnostics = Default::default();
         *future_breakage_diagnostics = Default::default();
-        *check_unstable_expect_diagnostics = false;
-        *unstable_expect_diagnostics = Default::default();
         *fulfilled_expectations = Default::default();
     }
 
@@ -1094,44 +1073,10 @@ impl<'a> DiagCtxtHandle<'a> {
         inner.emitter.emit_unused_externs(lint_level, unused_externs)
     }
 
-    pub fn update_unstable_expectation_id(
-        &self,
-        unstable_to_stable: FxIndexMap<AttrId, LintExpectationId>,
-    ) {
-        let mut inner = self.inner.borrow_mut();
-        let diags = std::mem::take(&mut inner.unstable_expect_diagnostics);
-        inner.check_unstable_expect_diagnostics = true;
-
-        if !diags.is_empty() {
-            inner.suppressed_expected_diag = true;
-            for mut diag in diags.into_iter() {
-                diag.update_unstable_expectation_id(&unstable_to_stable);
-
-                // Here the diagnostic is given back to `emit_diagnostic` where it was first
-                // intercepted. Now it should be processed as usual, since the unstable expectation
-                // id is now stable.
-                inner.emit_diagnostic(diag, self.tainted_with_errors);
-            }
-        }
-
-        inner
-            .stashed_diagnostics
-            .values_mut()
-            .for_each(|(diag, _guar)| diag.update_unstable_expectation_id(&unstable_to_stable));
-        inner
-            .future_breakage_diagnostics
-            .iter_mut()
-            .for_each(|diag| diag.update_unstable_expectation_id(&unstable_to_stable));
-    }
-
     /// This methods steals all [`LintExpectationId`]s that are stored inside
     /// [`DiagCtxtInner`] and indicate that the linked expectation has been fulfilled.
     #[must_use]
-    pub fn steal_fulfilled_expectation_ids(&self) -> FxHashSet<LintExpectationId> {
-        assert!(
-            self.inner.borrow().unstable_expect_diagnostics.is_empty(),
-            "`DiagCtxtInner::unstable_expect_diagnostics` should be empty at this point",
-        );
+    pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet<LintExpectationId> {
         std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations)
     }
 
@@ -1440,8 +1385,6 @@ impl DiagCtxtInner {
             emitted_diagnostics: Default::default(),
             stashed_diagnostics: Default::default(),
             future_breakage_diagnostics: Vec::new(),
-            check_unstable_expect_diagnostics: false,
-            unstable_expect_diagnostics: Vec::new(),
             fulfilled_expectations: Default::default(),
             ice_file: None,
         }
@@ -1471,24 +1414,6 @@ impl DiagCtxtInner {
         mut diagnostic: DiagInner,
         taint: Option<&Cell<Option<ErrorGuaranteed>>>,
     ) -> Option<ErrorGuaranteed> {
-        match diagnostic.level {
-            Expect(expect_id) | ForceWarning(Some(expect_id)) => {
-                // The `LintExpectationId` can be stable or unstable depending on when it was
-                // created. Diagnostics created before the definition of `HirId`s are unstable and
-                // can not yet be stored. Instead, they are buffered until the `LintExpectationId`
-                // is replaced by a stable one by the `LintLevelsBuilder`.
-                if let LintExpectationId::Unstable { .. } = expect_id {
-                    // We don't call TRACK_DIAGNOSTIC because we wait for the
-                    // unstable ID to be updated, whereupon the diagnostic will be
-                    // passed into this method again.
-                    self.unstable_expect_diagnostics.push(diagnostic);
-                    return None;
-                }
-                // Continue through to the `Expect`/`ForceWarning` case below.
-            }
-            _ => {}
-        }
-
         if diagnostic.has_future_breakage() {
             // Future breakages aren't emitted if they're `Level::Allow` or
             // `Level::Expect`, but they still need to be constructed and
@@ -1564,9 +1489,6 @@ impl DiagCtxtInner {
                 return None;
             }
             Expect(expect_id) | ForceWarning(Some(expect_id)) => {
-                if let LintExpectationId::Unstable { .. } = expect_id {
-                    unreachable!(); // this case was handled at the top of this function
-                }
                 self.fulfilled_expectations.insert(expect_id);
                 if let Expect(_) = diagnostic.level {
                     // Nothing emitted here for expected lints.
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 39489a8df1b..2bd78d34736 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -773,18 +773,20 @@ fn extract_symbol_from_pnr<'a>(
     match pnr {
         ParseNtResult::Ident(nt_ident, is_raw) => {
             if let IdentIsRaw::Yes = is_raw {
-                return Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR));
+                Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR))
+            } else {
+                Ok(nt_ident.name)
             }
-            return Ok(nt_ident.name);
         }
         ParseNtResult::Tt(TokenTree::Token(
             Token { kind: TokenKind::Ident(symbol, is_raw), .. },
             _,
         )) => {
             if let IdentIsRaw::Yes = is_raw {
-                return Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR));
+                Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR))
+            } else {
+                Ok(*symbol)
             }
-            return Ok(*symbol);
         }
         ParseNtResult::Tt(TokenTree::Token(
             Token {
@@ -792,15 +794,13 @@ fn extract_symbol_from_pnr<'a>(
                 ..
             },
             _,
-        )) => {
-            return Ok(*symbol);
-        }
+        )) => Ok(*symbol),
         ParseNtResult::Nt(nt)
             if let Nonterminal::NtLiteral(expr) = &**nt
                 && let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) =
                     &expr.kind =>
         {
-            return Ok(*symbol);
+            Ok(*symbol)
         }
         _ => Err(dcx
             .struct_err(
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 57c47d29857..ee03f780e16 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -168,6 +168,19 @@ impl Lifetime {
             (LifetimeSuggestionPosition::Normal, self.ident.span)
         }
     }
+
+    pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) {
+        debug_assert!(new_lifetime.starts_with('\''));
+        let (pos, span) = self.suggestion_position();
+        let code = match pos {
+            LifetimeSuggestionPosition::Normal => format!("{new_lifetime}"),
+            LifetimeSuggestionPosition::Ampersand => format!("{new_lifetime} "),
+            LifetimeSuggestionPosition::ElidedPath => format!("<{new_lifetime}>"),
+            LifetimeSuggestionPosition::ElidedPathArgument => format!("{new_lifetime}, "),
+            LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lifetime}"),
+        };
+        (span, code)
+    }
 }
 
 /// A `Path` is essentially Rust's notion of a name; for instance,
@@ -2914,6 +2927,7 @@ impl<'hir> InlineAsmOperand<'hir> {
 
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct InlineAsm<'hir> {
+    pub asm_macro: ast::AsmMacro,
     pub template: &'hir [InlineAsmTemplatePiece],
     pub template_strs: &'hir [(Symbol, Option<Symbol>, Span)],
     pub operands: &'hir [(InlineAsmOperand<'hir>, Span)],
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index e47c707ee18..1d686878eab 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1064,20 +1064,29 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
             struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
             return;
         }
-        let e = fields[FieldIdx::ZERO].ty(tcx, args);
-        if !fields.iter().all(|f| f.ty(tcx, args) == e) {
-            struct_span_code_err!(tcx.dcx(), sp, E0076, "SIMD vector should be homogeneous")
-                .with_span_label(sp, "SIMD elements must have the same type")
+
+        let array_field = &fields[FieldIdx::ZERO];
+        let array_ty = array_field.ty(tcx, args);
+        let ty::Array(element_ty, len_const) = array_ty.kind() else {
+            struct_span_code_err!(
+                tcx.dcx(),
+                sp,
+                E0076,
+                "SIMD vector's only field must be an array"
+            )
+            .with_span_label(tcx.def_span(array_field.did), "not an array")
+            .emit();
+            return;
+        };
+
+        if let Some(second_field) = fields.get(FieldIdx::from_u32(1)) {
+            struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot have multiple fields")
+                .with_span_label(tcx.def_span(second_field.did), "excess field")
                 .emit();
             return;
         }
 
-        let len = if let ty::Array(_ty, c) = e.kind() {
-            c.try_eval_target_usize(tcx, tcx.param_env(def.did()))
-        } else {
-            Some(fields.len() as u64)
-        };
-        if let Some(len) = len {
+        if let Some(len) = len_const.try_eval_target_usize(tcx, tcx.param_env(def.did())) {
             if len == 0 {
                 struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
                 return;
@@ -1097,16 +1106,9 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
         // These are scalar types which directly match a "machine" type
         // Yes: Integers, floats, "thin" pointers
         // No: char, "fat" pointers, compound types
-        match e.kind() {
-            ty::Param(_) => (), // pass struct<T>(T, T, T, T) through, let monomorphization catch errors
-            ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct(u8, u8, u8, u8) is ok
-            ty::Array(t, _) if matches!(t.kind(), ty::Param(_)) => (), // pass struct<T>([T; N]) through, let monomorphization catch errors
-            ty::Array(t, _clen)
-                if matches!(
-                    t.kind(),
-                    ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _)
-                ) =>
-            { /* struct([f32; 4]) is ok */ }
+        match element_ty.kind() {
+            ty::Param(_) => (), // pass struct<T>([T; 4]) through, let monomorphization catch errors
+            ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct([u8; 4]) is ok
             _ => {
                 struct_span_code_err!(
                     tcx.dcx(),
@@ -1149,42 +1151,40 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
                 "type has conflicting packed and align representation hints"
             )
             .emit();
-        } else {
-            if let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) {
-                let mut err = struct_span_code_err!(
-                    tcx.dcx(),
-                    sp,
-                    E0588,
-                    "packed type cannot transitively contain a `#[repr(align)]` type"
-                );
+        } else if let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) {
+            let mut err = struct_span_code_err!(
+                tcx.dcx(),
+                sp,
+                E0588,
+                "packed type cannot transitively contain a `#[repr(align)]` type"
+            );
 
-                err.span_note(
-                    tcx.def_span(def_spans[0].0),
-                    format!("`{}` has a `#[repr(align)]` attribute", tcx.item_name(def_spans[0].0)),
-                );
+            err.span_note(
+                tcx.def_span(def_spans[0].0),
+                format!("`{}` has a `#[repr(align)]` attribute", tcx.item_name(def_spans[0].0)),
+            );
 
-                if def_spans.len() > 2 {
-                    let mut first = true;
-                    for (adt_def, span) in def_spans.iter().skip(1).rev() {
-                        let ident = tcx.item_name(*adt_def);
-                        err.span_note(
-                            *span,
-                            if first {
-                                format!(
-                                    "`{}` contains a field of type `{}`",
-                                    tcx.type_of(def.did()).instantiate_identity(),
-                                    ident
-                                )
-                            } else {
-                                format!("...which contains a field of type `{ident}`")
-                            },
-                        );
-                        first = false;
-                    }
+            if def_spans.len() > 2 {
+                let mut first = true;
+                for (adt_def, span) in def_spans.iter().skip(1).rev() {
+                    let ident = tcx.item_name(*adt_def);
+                    err.span_note(
+                        *span,
+                        if first {
+                            format!(
+                                "`{}` contains a field of type `{}`",
+                                tcx.type_of(def.did()).instantiate_identity(),
+                                ident
+                            )
+                        } else {
+                            format!("...which contains a field of type `{ident}`")
+                        },
+                    );
+                    first = false;
                 }
-
-                err.emit();
             }
+
+            err.emit();
         }
     }
 }
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 2afed04c5bc..388e02b36e0 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1038,7 +1038,7 @@ fn report_trait_method_mismatch<'tcx>(
         false,
     );
 
-    return diag.emit();
+    diag.emit()
 }
 
 fn check_region_bounds_on_impl_item<'tcx>(
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 6820a44f141..dbdad2eb41d 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -186,17 +186,15 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
 
     if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id())
         && alloc.inner().provenance().ptrs().len() != 0
-    {
-        if attrs
+        && attrs
             .link_section
             .map(|link_section| !link_section.as_str().starts_with(".init_array"))
             .unwrap()
-        {
-            let msg = "statics with a custom `#[link_section]` must be a \
+    {
+        let msg = "statics with a custom `#[link_section]` must be a \
                         simple list of bytes on the wasm target with no \
                         extra levels of indirection such as references";
-            tcx.dcx().span_err(tcx.def_span(id), msg);
-        }
+        tcx.dcx().span_err(tcx.def_span(id), msg);
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 3627faf8dfc..10b3fe380ab 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1602,7 +1602,7 @@ fn check_fn_or_method<'tcx>(
                     function: def_id,
                     // Note that the `param_idx` of the output type is
                     // one greater than the index of the last input type.
-                    param_idx: idx.try_into().unwrap(),
+                    param_idx: idx,
                 }),
                 ty,
             )
@@ -1611,7 +1611,7 @@ fn check_fn_or_method<'tcx>(
     for (idx, ty) in sig.inputs_and_output.iter().enumerate() {
         wfcx.register_wf_obligation(
             arg_span(idx),
-            Some(WellFormedLoc::Param { function: def_id, param_idx: idx.try_into().unwrap() }),
+            Some(WellFormedLoc::Param { function: def_id, param_idx: idx }),
             ty.into(),
         );
     }
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 30fc06829ed..480116a6249 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -274,7 +274,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
                         return false;
                     }
 
-                    return true;
+                    true
                 })
                 .collect::<Vec<_>>();
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index db809e4837d..f2a97d06771 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -53,17 +53,15 @@ fn enforce_trait_manually_implementable(
 ) -> Result<(), ErrorGuaranteed> {
     let impl_header_span = tcx.def_span(impl_def_id);
 
-    if tcx.is_lang_item(trait_def_id, LangItem::Freeze) {
-        if !tcx.features().freeze_impls {
-            feature_err(
-                &tcx.sess,
-                sym::freeze_impls,
-                impl_header_span,
-                "explicit impls for the `Freeze` trait are not permitted",
-            )
-            .with_span_label(impl_header_span, format!("impl of `Freeze` not allowed"))
-            .emit();
-        }
+    if tcx.is_lang_item(trait_def_id, LangItem::Freeze) && !tcx.features().freeze_impls {
+        feature_err(
+            &tcx.sess,
+            sym::freeze_impls,
+            impl_header_span,
+            "explicit impls for the `Freeze` trait are not permitted",
+        )
+        .with_span_label(impl_header_span, format!("impl of `Freeze` not allowed"))
+        .emit();
     }
 
     // Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index fe46eb583f1..b4cbd1f309c 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1191,23 +1191,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                                     (generics.span, "<'a>".to_owned())
                                 };
 
-                            let lifetime_sugg = match lifetime_ref.suggestion_position() {
-                                (hir::LifetimeSuggestionPosition::Normal, span) => {
-                                    (span, "'a".to_owned())
-                                }
-                                (hir::LifetimeSuggestionPosition::Ampersand, span) => {
-                                    (span, "'a ".to_owned())
-                                }
-                                (hir::LifetimeSuggestionPosition::ElidedPath, span) => {
-                                    (span, "<'a>".to_owned())
-                                }
-                                (hir::LifetimeSuggestionPosition::ElidedPathArgument, span) => {
-                                    (span, "'a, ".to_owned())
-                                }
-                                (hir::LifetimeSuggestionPosition::ObjectDefault, span) => {
-                                    (span, "+ 'a".to_owned())
-                                }
-                            };
+                            let lifetime_sugg = lifetime_ref.suggestion("'a");
                             let suggestions = vec![lifetime_sugg, new_param_sugg];
 
                             diag.span_label(
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 7f4a8208faa..2afb29abd68 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -381,24 +381,22 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
         }
 
         mir_opaque_ty.ty
+    } else if let Some(guar) = tables.tainted_by_errors {
+        // Some error in the owner fn prevented us from populating
+        // the `concrete_opaque_types` table.
+        Ty::new_error(tcx, guar)
     } else {
-        if let Some(guar) = tables.tainted_by_errors {
-            // Some error in the owner fn prevented us from populating
-            // the `concrete_opaque_types` table.
-            Ty::new_error(tcx, guar)
+        // Fall back to the RPIT we inferred during HIR typeck
+        if let Some(hir_opaque_ty) = hir_opaque_ty {
+            hir_opaque_ty.ty
         } else {
-            // Fall back to the RPIT we inferred during HIR typeck
-            if let Some(hir_opaque_ty) = hir_opaque_ty {
-                hir_opaque_ty.ty
-            } else {
-                // We failed to resolve the opaque type or it
-                // resolves to itself. We interpret this as the
-                // no values of the hidden type ever being constructed,
-                // so we can just make the hidden type be `!`.
-                // For backwards compatibility reasons, we fall back to
-                // `()` until we the diverging default is changed.
-                Ty::new_diverging_default(tcx)
-            }
+            // We failed to resolve the opaque type or it
+            // resolves to itself. We interpret this as the
+            // no values of the hidden type ever being constructed,
+            // so we can just make the hidden type be `!`.
+            // For backwards compatibility reasons, we fall back to
+            // `()` until we the diverging default is changed.
+            Ty::new_diverging_default(tcx)
         }
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
index da89f5769d1..97402dd1109 100644
--- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
@@ -827,20 +827,18 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
 
             if num_generic_args_supplied_to_trait + num_assoc_fn_excess_args
                 == num_trait_generics_except_self
+                && let Some(span) = self.gen_args.span_ext()
+                && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
             {
-                if let Some(span) = self.gen_args.span_ext()
-                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
-                {
-                    let sugg = vec![
-                        (
-                            self.path_segment.ident.span,
-                            format!("{}::{}", snippet, self.path_segment.ident),
-                        ),
-                        (span.with_lo(self.path_segment.ident.span.hi()), "".to_owned()),
-                    ];
+                let sugg = vec![
+                    (
+                        self.path_segment.ident.span,
+                        format!("{}::{}", snippet, self.path_segment.ident),
+                    ),
+                    (span.with_lo(self.path_segment.ident.span.hi()), "".to_owned()),
+                ];
 
-                    err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
-                }
+                err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
             }
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index ac5bd825b18..7163352e8a4 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -562,13 +562,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                             tcx.const_param_default(param.def_id)
                                 .instantiate(tcx, preceding_args)
                                 .into()
+                        } else if infer_args {
+                            self.lowerer.ct_infer(Some(param), self.span).into()
                         } else {
-                            if infer_args {
-                                self.lowerer.ct_infer(Some(param), self.span).into()
-                            } else {
-                                // We've already errored above about the mismatch.
-                                ty::Const::new_misc_error(tcx).into()
-                            }
+                            // We've already errored above about the mismatch.
+                            ty::Const::new_misc_error(tcx).into()
                         }
                     }
                 }
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index afaa4a1ac6d..bf8ed017cf7 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -389,7 +389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             {
                 // check that the `if` expr without `else` is the fn body's expr
                 if expr.span == sp {
-                    return self.get_fn_decl(hir_id).map(|(_, fn_decl, _)| {
+                    return self.get_fn_decl(hir_id).map(|(_, fn_decl)| {
                         let (ty, span) = match fn_decl.output {
                             hir::FnRetTy::DefaultReturn(span) => ("()".to_string(), span),
                             hir::FnRetTy::Return(ty) => (ty_to_string(&self.tcx, ty), ty.span),
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 1e1e007862e..36892aaf80c 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -732,12 +732,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             }
             _ => return Err(CastError::NonScalar),
         };
-        if let ty::Adt(adt_def, _) = *self.expr_ty.kind() {
-            if adt_def.did().krate != LOCAL_CRATE {
-                if adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive) {
-                    return Err(CastError::ForeignNonExhaustiveAdt);
-                }
-            }
+        if let ty::Adt(adt_def, _) = *self.expr_ty.kind()
+            && adt_def.did().krate != LOCAL_CRATE
+            && adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive)
+        {
+            return Err(CastError::ForeignNonExhaustiveAdt);
         }
         match (t_from, t_cast) {
             // These types have invariants! can't cast into them.
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 5117eef9ed8..f71427e42d4 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -605,7 +605,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Abi::Rust,
         ));
 
-        return Some(ExpectedSig { cause_span, sig });
+        Some(ExpectedSig { cause_span, sig })
     }
 
     fn sig_of_closure(
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index d97c590bd41..3bada1de148 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1860,10 +1860,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         };
 
         // If this is due to an explicit `return`, suggest adding a return type.
-        if let Some((fn_id, fn_decl, can_suggest)) = fcx.get_fn_decl(block_or_return_id)
+        if let Some((fn_id, fn_decl)) = fcx.get_fn_decl(block_or_return_id)
             && !due_to_block
         {
-            fcx.suggest_missing_return_type(&mut err, fn_decl, expected, found, can_suggest, fn_id);
+            fcx.suggest_missing_return_type(&mut err, fn_decl, expected, found, fn_id);
         }
 
         // If this is due to a block, then maybe we forgot a `return`/`break`.
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 0da299f0179..80a71f27a99 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -1042,7 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return true;
             }
         }
-        return false;
+        false
     }
 
     fn explain_self_literal(
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 9bad5633b69..6fd509ed32f 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -774,7 +774,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.ret_coercion_span.set(Some(expr.span));
             }
             let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
-            if let Some((_, fn_decl, _)) = self.get_fn_decl(expr.hir_id) {
+            if let Some((_, fn_decl)) = self.get_fn_decl(expr.hir_id) {
                 coercion.coerce_forced_unit(
                     self,
                     &cause,
@@ -1780,16 +1780,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         // Make sure the programmer specified correct number of fields.
-        if adt_kind == AdtKind::Union {
-            if hir_fields.len() != 1 {
-                struct_span_code_err!(
-                    self.dcx(),
-                    span,
-                    E0784,
-                    "union expressions should have exactly one field",
-                )
-                .emit();
-            }
+        if adt_kind == AdtKind::Union && hir_fields.len() != 1 {
+            struct_span_code_err!(
+                self.dcx(),
+                span,
+                E0784,
+                "union expressions should have exactly one field",
+            )
+            .emit();
         }
 
         // If check_expr_struct_fields hit an error, do not attempt to populate
@@ -2904,21 +2902,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     candidate_fields.iter().map(|path| format!("{unwrap}{path}")),
                     Applicability::MaybeIncorrect,
                 );
-            } else {
-                if let Some(field_name) = find_best_match_for_name(&field_names, field.name, None) {
-                    err.span_suggestion_verbose(
-                        field.span,
-                        "a field with a similar name exists",
-                        format!("{unwrap}{}", field_name),
-                        Applicability::MaybeIncorrect,
-                    );
-                } else if !field_names.is_empty() {
-                    let is = if field_names.len() == 1 { " is" } else { "s are" };
-                    err.note(format!(
-                        "available field{is}: {}",
-                        self.name_series_display(field_names),
-                    ));
-                }
+            } else if let Some(field_name) =
+                find_best_match_for_name(&field_names, field.name, None)
+            {
+                err.span_suggestion_verbose(
+                    field.span,
+                    "a field with a similar name exists",
+                    format!("{unwrap}{}", field_name),
+                    Applicability::MaybeIncorrect,
+                );
+            } else if !field_names.is_empty() {
+                let is = if field_names.len() == 1 { " is" } else { "s are" };
+                err.note(
+                    format!("available field{is}: {}", self.name_series_display(field_names),),
+                );
             }
         }
         err
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 19f7950287f..178dc47aa1f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -30,7 +30,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::DesugaringKind;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::kw;
 use rustc_span::Span;
 use rustc_target::abi::FieldIdx;
 use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
@@ -859,38 +859,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         )
     }
 
-    /// Given a `HirId`, return the `HirId` of the enclosing function, its `FnDecl`, and whether a
-    /// suggestion can be made, `None` otherwise.
+    /// Given a `HirId`, return the `HirId` of the enclosing function and its `FnDecl`.
     pub(crate) fn get_fn_decl(
         &self,
         blk_id: HirId,
-    ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, bool)> {
+    ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>)> {
         // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
         // `while` before reaching it, as block tail returns are not available in them.
         self.tcx.hir().get_fn_id_for_return_block(blk_id).and_then(|item_id| {
             match self.tcx.hir_node(item_id) {
                 Node::Item(&hir::Item {
-                    ident,
-                    kind: hir::ItemKind::Fn(ref sig, ..),
-                    owner_id,
-                    ..
-                }) => {
-                    // This is less than ideal, it will not suggest a return type span on any
-                    // method called `main`, regardless of whether it is actually the entry point,
-                    // but it will still present it as the reason for the expected type.
-                    Some((owner_id.def_id, sig.decl, ident.name != sym::main))
-                }
+                    kind: hir::ItemKind::Fn(ref sig, ..), owner_id, ..
+                }) => Some((owner_id.def_id, sig.decl)),
                 Node::TraitItem(&hir::TraitItem {
                     kind: hir::TraitItemKind::Fn(ref sig, ..),
                     owner_id,
                     ..
-                }) => Some((owner_id.def_id, sig.decl, true)),
-                // FIXME: Suggestable if this is not a trait implementation
+                }) => Some((owner_id.def_id, sig.decl)),
                 Node::ImplItem(&hir::ImplItem {
                     kind: hir::ImplItemKind::Fn(ref sig, ..),
                     owner_id,
                     ..
-                }) => Some((owner_id.def_id, sig.decl, false)),
+                }) => Some((owner_id.def_id, sig.decl)),
                 Node::Expr(&hir::Expr {
                     hir_id,
                     kind: hir::ExprKind::Closure(&hir::Closure { def_id, kind, fn_decl, .. }),
@@ -901,33 +891,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // FIXME(async_closures): Implement this.
                             return None;
                         }
-                        hir::ClosureKind::Closure => Some((def_id, fn_decl, true)),
+                        hir::ClosureKind::Closure => Some((def_id, fn_decl)),
                         hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
                             _,
                             hir::CoroutineSource::Fn,
                         )) => {
-                            let (ident, sig, owner_id) = match self.tcx.parent_hir_node(hir_id) {
+                            let (sig, owner_id) = match self.tcx.parent_hir_node(hir_id) {
                                 Node::Item(&hir::Item {
-                                    ident,
                                     kind: hir::ItemKind::Fn(ref sig, ..),
                                     owner_id,
                                     ..
-                                }) => (ident, sig, owner_id),
+                                }) => (sig, owner_id),
                                 Node::TraitItem(&hir::TraitItem {
-                                    ident,
                                     kind: hir::TraitItemKind::Fn(ref sig, ..),
                                     owner_id,
                                     ..
-                                }) => (ident, sig, owner_id),
+                                }) => (sig, owner_id),
                                 Node::ImplItem(&hir::ImplItem {
-                                    ident,
                                     kind: hir::ImplItemKind::Fn(ref sig, ..),
                                     owner_id,
                                     ..
-                                }) => (ident, sig, owner_id),
+                                }) => (sig, owner_id),
                                 _ => return None,
                             };
-                            Some((owner_id.def_id, sig.decl, ident.name != sym::main))
+                            Some((owner_id.def_id, sig.decl))
                         }
                         _ => None,
                     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
index cb77d3f85d9..358bc389bd1 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
@@ -307,7 +307,7 @@ impl<'tcx> ArgMatrix<'tcx> {
                 permutation.into_iter().map(|x| x.unwrap()).collect();
             return Some(Issue::Permutation(final_permutation));
         }
-        return None;
+        None
     }
 
     // Obviously, detecting exact user intention is impossible, so the goal here is to
@@ -410,6 +410,6 @@ impl<'tcx> ArgMatrix<'tcx> {
         // sort errors with same type by the order they appear in the source
         // so that suggestion will be handled properly, see #112507
         errors.sort();
-        return (errors, matched_inputs);
+        (errors, matched_inputs)
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index bdf84f33216..21b040bd0bc 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1873,7 +1873,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // that highlight errors inline.
                     let mut sp = blk.span;
                     let mut fn_span = None;
-                    if let Some((fn_def_id, decl, _)) = self.get_fn_decl(blk.hir_id) {
+                    if let Some((fn_def_id, decl)) = self.get_fn_decl(blk.hir_id) {
                         let ret_sp = decl.output.span();
                         if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
                             // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
@@ -2565,7 +2565,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     other_generic_param.name.ident() == generic_param.name.ident()
                 },
             ) {
-                idxs_matched.push(other_idx.into());
+                idxs_matched.push(other_idx);
             }
 
             if idxs_matched.is_empty() {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 4454703645e..b71e34864fd 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -79,9 +79,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // `break` type mismatches provide better context for tail `loop` expressions.
             return false;
         }
-        if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
+        if let Some((fn_id, fn_decl)) = self.get_fn_decl(blk_id) {
             pointing_at_return_type =
-                self.suggest_missing_return_type(err, fn_decl, expected, found, can_suggest, fn_id);
+                self.suggest_missing_return_type(err, fn_decl, expected, found, fn_id);
             self.suggest_missing_break_or_return_expr(
                 err, expr, fn_decl, expected, found, blk_id, fn_id,
             );
@@ -813,7 +813,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fn_decl: &hir::FnDecl<'tcx>,
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
-        can_suggest: bool,
         fn_id: LocalDefId,
     ) -> bool {
         // Can't suggest `->` on a block-like coroutine
@@ -826,28 +825,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let found =
             self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found));
         // Only suggest changing the return type for methods that
-        // haven't set a return type at all (and aren't `fn main()` or an impl).
+        // haven't set a return type at all (and aren't `fn main()`, impl or closure).
         match &fn_decl.output {
-            &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() && !can_suggest => {
-                // `fn main()` must return `()`, do not suggest changing return type
-                err.subdiagnostic(errors::ExpectedReturnTypeLabel::Unit { span });
-                return true;
-            }
+            // For closure with default returns, don't suggest adding return type
+            &hir::FnRetTy::DefaultReturn(_) if self.tcx.is_closure_like(fn_id.to_def_id()) => {}
             &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => {
-                if let Some(found) = found.make_suggestable(self.tcx, false, None) {
+                if !self.can_add_return_type(fn_id) {
+                    err.subdiagnostic(errors::ExpectedReturnTypeLabel::Unit { span });
+                } else if let Some(found) = found.make_suggestable(self.tcx, false, None) {
                     err.subdiagnostic(errors::AddReturnTypeSuggestion::Add {
                         span,
                         found: found.to_string(),
                     });
-                    return true;
                 } else if let Some(sugg) = suggest_impl_trait(self, self.param_env, found) {
                     err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: sugg });
-                    return true;
                 } else {
                     // FIXME: if `found` could be `impl Iterator` we should suggest that.
                     err.subdiagnostic(errors::AddReturnTypeSuggestion::MissingHere { span });
-                    return true;
                 }
+
+                return true;
             }
             hir::FnRetTy::Return(hir_ty) => {
                 if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind
@@ -905,6 +902,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         false
     }
 
+    /// Checks whether we can add a return type to a function.
+    /// Assumes given function doesn't have a explicit return type.
+    fn can_add_return_type(&self, fn_id: LocalDefId) -> bool {
+        match self.tcx.hir_node_by_def_id(fn_id) {
+            Node::Item(&hir::Item { ident, .. }) => {
+                // This is less than ideal, it will not suggest a return type span on any
+                // method called `main`, regardless of whether it is actually the entry point,
+                // but it will still present it as the reason for the expected type.
+                ident.name != sym::main
+            }
+            Node::ImplItem(item) => {
+                // If it doesn't impl a trait, we can add a return type
+                let Node::Item(&hir::Item {
+                    kind: hir::ItemKind::Impl(&hir::Impl { of_trait, .. }),
+                    ..
+                }) = self.tcx.parent_hir_node(item.hir_id())
+                else {
+                    unreachable!();
+                };
+
+                of_trait.is_none()
+            }
+            _ => true,
+        }
+    }
+
     fn try_note_caller_chooses_ty_for_ty_param(
         &self,
         diag: &mut Diag<'_>,
@@ -2028,7 +2051,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let span = expr.span.find_oldest_ancestor_in_same_ctxt();
         err.span_suggestion_verbose(span.shrink_to_hi(), msg, sugg, Applicability::HasPlaceholders);
-        return true;
+        true
     }
 
     pub(crate) fn suggest_coercing_result_via_try_operator(
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 4ea22884cf3..2f990de7e31 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -158,14 +158,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
                         ),
                     );
                 }
-            } else {
-                if !self.fcx.tcx.features().unsized_locals {
-                    self.fcx.require_type_is_sized(
-                        var_ty,
-                        p.span,
-                        ObligationCauseCode::VariableType(p.hir_id),
-                    );
-                }
+            } else if !self.fcx.tcx.features().unsized_locals {
+                self.fcx.require_type_is_sized(
+                    var_ty,
+                    p.span,
+                    ObligationCauseCode::VariableType(p.hir_id),
+                );
             }
 
             debug!(
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index caf09c1177f..e2c1eef837f 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -43,7 +43,7 @@ pub use coercion::can_coerce;
 use fn_ctxt::FnCtxt;
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::codes::*;
-use rustc_errors::{struct_span_code_err, Applicability, ErrorGuaranteed};
+use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::Visitor;
@@ -423,6 +423,36 @@ fn report_unexpected_variant_res(
             err.multipart_suggestion_verbose(descr, suggestion, Applicability::MaybeIncorrect);
             err
         }
+        Res::Def(DefKind::Variant, _) if expr.is_none() => {
+            err.span_label(span, format!("not a {expected}"));
+
+            let fields = &tcx.expect_variant_res(res).fields.raw;
+            let span = qpath.span().shrink_to_hi().to(span.shrink_to_hi());
+            let (msg, sugg) = if fields.is_empty() {
+                ("use the struct variant pattern syntax".to_string(), " {}".to_string())
+            } else {
+                let msg = format!(
+                    "the struct variant's field{s} {are} being ignored",
+                    s = pluralize!(fields.len()),
+                    are = pluralize!("is", fields.len())
+                );
+                let fields = fields
+                    .iter()
+                    .map(|field| format!("{}: _", field.name.to_ident_string()))
+                    .collect::<Vec<_>>()
+                    .join(", ");
+                let sugg = format!(" {{ {} }}", fields);
+                (msg, sugg)
+            };
+
+            err.span_suggestion_verbose(
+                qpath.span().shrink_to_hi().to(span.shrink_to_hi()),
+                msg,
+                sugg,
+                Applicability::HasPlaceholders,
+            );
+            err
+        }
         _ => err.with_span_label(span, format!("not a {expected}")),
     }
     .emit()
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 14ad5830111..9ede809ead2 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1252,11 +1252,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             && suggested_bounds.contains(parent)
                         {
                             // We don't suggest `PartialEq` when we already suggest `Eq`.
-                        } else if !suggested_bounds.contains(pred) {
-                            if collect_type_param_suggestions(self_ty, *pred, &p) {
-                                suggested = true;
-                                suggested_bounds.insert(pred);
-                            }
+                        } else if !suggested_bounds.contains(pred)
+                            && collect_type_param_suggestions(self_ty, *pred, &p)
+                        {
+                            suggested = true;
+                            suggested_bounds.insert(pred);
                         }
                         (
                             match parent_pred {
@@ -1267,14 +1267,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                         if !suggested
                                             && !suggested_bounds.contains(pred)
                                             && !suggested_bounds.contains(parent_pred)
-                                        {
-                                            if collect_type_param_suggestions(
+                                            && collect_type_param_suggestions(
                                                 self_ty,
                                                 *parent_pred,
                                                 &p,
-                                            ) {
-                                                suggested_bounds.insert(pred);
-                                            }
+                                            )
+                                        {
+                                            suggested_bounds.insert(pred);
                                         }
                                         format!("`{p}`\nwhich is required by `{parent_p}`")
                                     }
@@ -1317,7 +1316,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
                 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
                 let mut long_ty_file = None;
-                let (primary_message, label) = if unimplemented_traits.len() == 1
+                let (primary_message, label, notes) = if unimplemented_traits.len() == 1
                     && unimplemented_traits_only
                 {
                     unimplemented_traits
@@ -1327,16 +1326,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             if trait_ref.self_ty().references_error() || rcvr_ty.references_error()
                             {
                                 // Avoid crashing.
-                                return (None, None);
+                                return (None, None, Vec::new());
                             }
-                            let OnUnimplementedNote { message, label, .. } = self
+                            let OnUnimplementedNote { message, label, notes, .. } = self
                                 .err_ctxt()
                                 .on_unimplemented_note(trait_ref, &obligation, &mut long_ty_file);
-                            (message, label)
+                            (message, label, notes)
                         })
                         .unwrap()
                 } else {
-                    (None, None)
+                    (None, None, Vec::new())
                 };
                 let primary_message = primary_message.unwrap_or_else(|| {
                     format!(
@@ -1363,6 +1362,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         "the following trait bounds were not satisfied:\n{bound_list}"
                     ));
                 }
+                for note in notes {
+                    err.note(note);
+                }
+
                 suggested_derive = self.suggest_derive(&mut err, unsatisfied_predicates);
 
                 unsatisfied_bounds = true;
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index 88cb82f0f37..cef0b23143d 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -417,12 +417,10 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
 fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol {
     if let Some(value) = item.value_str() {
         value
+    } else if let Some(ident) = item.ident() {
+        tcx.dcx().emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident });
     } else {
-        if let Some(ident) = item.ident() {
-            tcx.dcx().emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident });
-        } else {
-            tcx.dcx().emit_fatal(errors::AssociatedValueExpected { span: item.span() });
-        }
+        tcx.dcx().emit_fatal(errors::AssociatedValueExpected { span: item.span() });
     }
 }
 
diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs
index 503470f896d..34f541a8cc6 100644
--- a/compiler/rustc_index/src/interval.rs
+++ b/compiler/rustc_index/src/interval.rs
@@ -17,7 +17,7 @@ mod tests;
 /// first value of the following element.
 #[derive(Debug, Clone)]
 pub struct IntervalSet<I> {
-    // Start, end
+    // Start, end (both inclusive)
     map: SmallVec<[(u32, u32); 2]>,
     domain: usize,
     _data: PhantomData<I>,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 63a729b13dc..0e767b7fb2e 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1481,7 +1481,7 @@ impl<'tcx> InferCtxt<'tcx> {
         // This hoists the borrow/release out of the loop body.
         let inner = self.inner.try_borrow();
 
-        return move |infer_var: TyOrConstInferVar| match (infer_var, &inner) {
+        move |infer_var: TyOrConstInferVar| match (infer_var, &inner) {
             (TyOrConstInferVar::Ty(ty_var), Ok(inner)) => {
                 use self::type_variable::TypeVariableValue;
 
@@ -1491,7 +1491,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 )
             }
             _ => false,
-        };
+        }
     }
 
     /// `ty_or_const_infer_var_changed` is equivalent to one of these two:
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index f2a511d7a88..fbe64f47741 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -259,11 +259,11 @@ impl<'tcx> InferCtxt<'tcx> {
             structurally_relate_aliases,
             root_vid,
             for_universe,
-            ambient_variance,
             root_term: source_term.into(),
+            ambient_variance,
             in_alias: false,
-            has_unconstrained_ty_var: false,
             cache: Default::default(),
+            has_unconstrained_ty_var: false,
         };
 
         let value_may_be_infer = generalizer.relate(source_term, source_term)?;
@@ -304,14 +304,12 @@ struct Generalizer<'me, 'tcx> {
     /// we reject the relation.
     for_universe: ty::UniverseIndex,
 
-    /// After we generalize this type, we are going to relate it to
-    /// some other type. What will be the variance at this point?
-    ambient_variance: ty::Variance,
-
     /// The root term (const or type) we're generalizing. Used for cycle errors.
     root_term: Term<'tcx>,
 
-    cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
+    /// After we generalize this type, we are going to relate it to
+    /// some other type. What will be the variance at this point?
+    ambient_variance: ty::Variance,
 
     /// This is set once we're generalizing the arguments of an alias.
     ///
@@ -320,6 +318,8 @@ struct Generalizer<'me, 'tcx> {
     /// hold by either normalizing the outer or the inner associated type.
     in_alias: bool,
 
+    cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>,
+
     /// See the field `has_unconstrained_ty_var` in `Generalization`.
     has_unconstrained_ty_var: bool,
 }
@@ -451,7 +451,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
     fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
 
-        if let Some(&result) = self.cache.get(&t) {
+        if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.in_alias)) {
             return Ok(result);
         }
 
@@ -557,7 +557,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
             _ => relate::structurally_relate_tys(self, t, t),
         }?;
 
-        self.cache.insert(t, g);
+        self.cache.insert((t, self.ambient_variance, self.in_alias), g);
         Ok(g)
     }
 
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 50422df8ee6..080f2a1785a 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -808,7 +808,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(mir_opt_level, Some(4));
     tracked!(move_size_limit, Some(4096));
     tracked!(mutable_noalias, false);
-    tracked!(next_solver, NextSolverConfig { coherence: true, globally: true });
+    tracked!(next_solver, Some(NextSolverConfig { coherence: true, globally: false }));
     tracked!(no_generate_arange_section, true);
     tracked!(no_jump_tables, true);
     tracked!(no_link, true);
@@ -847,6 +847,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(share_generics, Some(true));
     tracked!(show_span, Some(String::from("abc")));
     tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
+    tracked!(small_data_threshold, Some(16));
     tracked!(split_lto_unit, Some(true));
     tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));
     tracked!(stack_protector, StackProtector::All);
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 824a1868c55..8b92180e9bd 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -426,19 +426,11 @@ impl MissingDoc {
         article: &'static str,
         desc: &'static str,
     ) {
-        // If we're building a test harness, then warning about
-        // documentation is probably not really relevant right now.
-        if cx.sess().opts.test {
-            return;
-        }
-
         // Only check publicly-visible items, using the result from the privacy pass.
         // It's an option so the crate root can also use this function (it doesn't
         // have a `NodeId`).
-        if def_id != CRATE_DEF_ID {
-            if !cx.effective_visibilities.is_exported(def_id) {
-                return;
-            }
+        if def_id != CRATE_DEF_ID && !cx.effective_visibilities.is_exported(def_id) {
+            return;
         }
 
         let attrs = cx.tcx.hir().attrs(cx.tcx.local_def_id_to_hir_id(def_id));
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index d8afba3d505..2450afbca06 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -1,10 +1,10 @@
-use rustc_data_structures::fx::FxIndexMap;
-use rustc_hir::{HirId, CRATE_OWNER_ID};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::CRATE_OWNER_ID;
 use rustc_middle::lint::LintExpectation;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS;
-use rustc_session::lint::{Level, LintExpectationId};
+use rustc_session::lint::LintExpectationId;
 use rustc_span::Symbol;
 
 use crate::lints::{Expectation, ExpectationNote};
@@ -17,43 +17,12 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp
     let krate = tcx.hir_crate_items(());
 
     let mut expectations = Vec::new();
-    let mut unstable_to_stable_ids = FxIndexMap::default();
 
-    let mut record_stable = |attr_id, hir_id, attr_index| {
-        let expect_id = LintExpectationId::Stable { hir_id, attr_index, lint_index: None };
-        unstable_to_stable_ids.entry(attr_id).or_insert(expect_id);
-    };
-    let mut push_expectations = |owner| {
+    for owner in std::iter::once(CRATE_OWNER_ID).chain(krate.owners()) {
         let lints = tcx.shallow_lint_levels_on(owner);
-        if lints.expectations.is_empty() {
-            return;
-        }
-
         expectations.extend_from_slice(&lints.expectations);
-
-        let attrs = tcx.hir_attrs(owner);
-        for &(local_id, attrs) in attrs.map.iter() {
-            // Some attributes appear multiple times in HIR, to ensure they are correctly taken
-            // into account where they matter. This means we cannot just associate the AttrId to
-            // the first HirId where we see it, but need to check it actually appears in a lint
-            // level.
-            // FIXME(cjgillot): Can this cause an attribute to appear in multiple expectation ids?
-            if !lints.specs.contains_key(&local_id) {
-                continue;
-            }
-            for (attr_index, attr) in attrs.iter().enumerate() {
-                let Some(Level::Expect(_)) = Level::from_attr(attr) else { continue };
-                record_stable(attr.id, HirId { owner, local_id }, attr_index.try_into().unwrap());
-            }
-        }
-    };
-
-    push_expectations(CRATE_OWNER_ID);
-    for owner in krate.owners() {
-        push_expectations(owner);
     }
 
-    tcx.dcx().update_unstable_expectation_id(unstable_to_stable_ids);
     expectations
 }
 
@@ -61,24 +30,43 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option<Symbol>) {
     let lint_expectations = tcx.lint_expectations(());
     let fulfilled_expectations = tcx.dcx().steal_fulfilled_expectation_ids();
 
-    for (id, expectation) in lint_expectations {
-        // This check will always be true, since `lint_expectations` only
-        // holds stable ids
-        if let LintExpectationId::Stable { hir_id, .. } = id {
-            if !fulfilled_expectations.contains(id)
-                && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter))
-            {
-                let rationale = expectation.reason.map(|rationale| ExpectationNote { rationale });
-                let note = expectation.is_unfulfilled_lint_expectations;
-                tcx.emit_node_span_lint(
-                    UNFULFILLED_LINT_EXPECTATIONS,
-                    *hir_id,
-                    expectation.emission_span,
-                    Expectation { rationale, note },
-                );
+    // Turn a `LintExpectationId` into a `(AttrId, lint_index)` pair.
+    let canonicalize_id = |expect_id: &LintExpectationId| {
+        match *expect_id {
+            LintExpectationId::Unstable { attr_id, lint_index: Some(lint_index) } => {
+                (attr_id, lint_index)
+            }
+            LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => {
+                // We are an `eval_always` query, so looking at the attribute's `AttrId` is ok.
+                let attr_id = tcx.hir().attrs(hir_id)[attr_index as usize].id;
+                (attr_id, lint_index)
             }
-        } else {
+            _ => panic!("fulfilled expectations must have a lint index"),
+        }
+    };
+
+    let fulfilled_expectations: FxHashSet<_> =
+        fulfilled_expectations.iter().map(canonicalize_id).collect();
+
+    for (expect_id, expectation) in lint_expectations {
+        // This check will always be true, since `lint_expectations` only holds stable ids
+        let LintExpectationId::Stable { hir_id, .. } = expect_id else {
             unreachable!("at this stage all `LintExpectationId`s are stable");
+        };
+
+        let expect_id = canonicalize_id(expect_id);
+
+        if !fulfilled_expectations.contains(&expect_id)
+            && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter))
+        {
+            let rationale = expectation.reason.map(|rationale| ExpectationNote { rationale });
+            let note = expectation.is_unfulfilled_lint_expectations;
+            tcx.emit_node_span_lint(
+                UNFULFILLED_LINT_EXPECTATIONS,
+                *hir_id,
+                expectation.emission_span,
+                Expectation { rationale, note },
+            );
         }
     }
 }
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index 2793d48dc51..1b25f21ef84 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -133,7 +133,7 @@ fn extract_iterator_next_call<'tcx>(
     {
         Some(recv)
     } else {
-        return None;
+        None
     }
 }
 
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 3d346b9cc5d..8b0a855612c 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -71,7 +71,7 @@ impl<'hir> Iterator for ParentHirIterator<'hir> {
         debug_assert_ne!(parent_id, self.current_id);
 
         self.current_id = parent_id;
-        return Some(parent_id);
+        Some(parent_id)
     }
 }
 
@@ -103,7 +103,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> {
         self.current_id = HirId::make_owner(parent_id.def_id);
 
         let node = self.map.tcx.hir_owner_node(self.current_id.owner);
-        return Some((self.current_id.owner, node));
+        Some((self.current_id.owner, node))
     }
 }
 
@@ -1233,14 +1233,14 @@ pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> Mod
         body_owners,
         ..
     } = collector;
-    return ModuleItems {
+    ModuleItems {
         submodules: submodules.into_boxed_slice(),
         free_items: items.into_boxed_slice(),
         trait_items: trait_items.into_boxed_slice(),
         impl_items: impl_items.into_boxed_slice(),
         foreign_items: foreign_items.into_boxed_slice(),
         body_owners: body_owners.into_boxed_slice(),
-    };
+    }
 }
 
 pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems {
@@ -1262,14 +1262,14 @@ pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems {
         ..
     } = collector;
 
-    return ModuleItems {
+    ModuleItems {
         submodules: submodules.into_boxed_slice(),
         free_items: items.into_boxed_slice(),
         trait_items: trait_items.into_boxed_slice(),
         impl_items: impl_items.into_boxed_slice(),
         foreign_items: foreign_items.into_boxed_slice(),
         body_owners: body_owners.into_boxed_slice(),
-    };
+    }
 }
 
 struct ItemCollector<'tcx> {
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 3b8861378e0..86dca27f04f 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -444,10 +444,11 @@ impl<'tcx> TyCtxt<'tcx> {
                 // the `-Z force-unstable-if-unmarked` flag present (we're
                 // compiling a compiler crate), then let this missing feature
                 // annotation slide.
-                if feature == sym::rustc_private && issue == NonZero::new(27812) {
-                    if self.sess.opts.unstable_opts.force_unstable_if_unmarked {
-                        return EvalResult::Allow;
-                    }
+                if feature == sym::rustc_private
+                    && issue == NonZero::new(27812)
+                    && self.sess.opts.unstable_opts.force_unstable_if_unmarked
+                {
+                    return EvalResult::Allow;
                 }
 
                 if matches!(allow_unstable, AllowUnstable::Yes) {
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 5fb8af576ae..4c5da188860 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -448,22 +448,20 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
                 bad: uninit_range,
             }))
         })?;
-        if !Prov::OFFSET_IS_ADDR {
-            if !self.provenance.range_empty(range, cx) {
-                // Find the provenance.
-                let (offset, _prov) = self
-                    .provenance
-                    .range_get_ptrs(range, cx)
-                    .first()
-                    .copied()
-                    .expect("there must be provenance somewhere here");
-                let start = offset.max(range.start); // the pointer might begin before `range`!
-                let end = (offset + cx.pointer_size()).min(range.end()); // the pointer might end after `range`!
-                return Err(AllocError::ReadPointerAsInt(Some(BadBytesAccess {
-                    access: range,
-                    bad: AllocRange::from(start..end),
-                })));
-            }
+        if !Prov::OFFSET_IS_ADDR && !self.provenance.range_empty(range, cx) {
+            // Find the provenance.
+            let (offset, _prov) = self
+                .provenance
+                .range_get_ptrs(range, cx)
+                .first()
+                .copied()
+                .expect("there must be provenance somewhere here");
+            let start = offset.max(range.start); // the pointer might begin before `range`!
+            let end = (offset + cx.pointer_size()).min(range.end()); // the pointer might end after `range`!
+            return Err(AllocError::ReadPointerAsInt(Some(BadBytesAccess {
+                access: range,
+                bad: AllocRange::from(start..end),
+            })));
         }
         Ok(self.get_bytes_unchecked(range))
     }
@@ -641,6 +639,12 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
     pub fn write_uninit(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult {
         self.mark_init(range, false);
         self.provenance.clear(range, cx)?;
+        Ok(())
+    }
+
+    /// Remove all provenance in the given memory range.
+    pub fn clear_provenance(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult {
+        self.provenance.clear(range, cx)?;
         return Ok(());
     }
 
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 84c17b39a62..989f03d3d13 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -307,6 +307,13 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
         }
     }
 
+    pub fn clear_provenance(&mut self) -> InterpResult<'tcx> {
+        if matches!(self, Scalar::Ptr(..)) {
+            *self = self.to_scalar_int()?.into();
+        }
+        Ok(())
+    }
+
     #[inline(always)]
     pub fn to_scalar_int(self) -> InterpResult<'tcx, ScalarInt> {
         self.try_to_scalar_int().map_err(|_| err_unsup!(ReadPointerAsInt(None)).into())
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 081a23b6ff3..26addb1e357 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1166,10 +1166,9 @@ impl<'tcx> LocalDecl<'tcx> {
     /// Returns `true` if this is a DerefTemp
     pub fn is_deref_temp(&self) -> bool {
         match self.local_info() {
-            LocalInfo::DerefTemp => return true,
-            _ => (),
+            LocalInfo::DerefTemp => true,
+            _ => false,
         }
-        return false;
     }
 
     /// Returns `true` is the local is from a compiler desugaring, e.g.,
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index a98e6943d68..d66d0be1009 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -208,12 +208,10 @@ fn dump_path<'tcx>(
 
     let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number {
         String::new()
+    } else if pass_num {
+        format!(".{:03}-{:03}", body.phase.phase_index(), body.pass_count)
     } else {
-        if pass_num {
-            format!(".{:03}-{:03}", body.phase.phase_index(), body.pass_count)
-        } else {
-            ".-------".to_string()
-        }
+        ".-------".to_string()
     };
 
     let crate_name = tcx.crate_name(source.def_id().krate);
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 362ff8e988d..a5952c65692 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -396,7 +396,7 @@ impl<'tcx> Const<'tcx> {
                         Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
                     }
                     Ok(Err(bad_ty)) => Err(Either::Left(bad_ty)),
-                    Err(err) => Err(Either::Right(err.into())),
+                    Err(err) => Err(Either::Right(err)),
                 }
             }
             ConstKind::Value(ty, val) => Ok((ty, val)),
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 5334e767766..5ec7e80ee45 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -181,6 +181,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         }
     }
 
+    fn evaluation_is_concurrent(&self) -> bool {
+        self.sess.threads() > 1
+    }
+
     fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, t: T) -> T {
         self.expand_abstract_consts(t)
     }
@@ -2003,7 +2007,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 ));
             }
         }
-        return None;
+        None
     }
 
     /// Checks if the bound region is in Impl Item.
@@ -2602,33 +2606,31 @@ impl<'tcx> TyCtxt<'tcx> {
     /// With `cfg(debug_assertions)`, assert that args are compatible with their generics,
     /// and print out the args if not.
     pub fn debug_assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) {
-        if cfg!(debug_assertions) {
-            if !self.check_args_compatible(def_id, args) {
-                if let DefKind::AssocTy = self.def_kind(def_id)
-                    && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id))
-                {
-                    bug!(
-                        "args not compatible with generics for {}: args={:#?}, generics={:#?}",
-                        self.def_path_str(def_id),
-                        args,
-                        // Make `[Self, GAT_ARGS...]` (this could be simplified)
-                        self.mk_args_from_iter(
-                            [self.types.self_param.into()].into_iter().chain(
-                                self.generics_of(def_id)
-                                    .own_args(ty::GenericArgs::identity_for_item(self, def_id))
-                                    .iter()
-                                    .copied()
-                            )
+        if cfg!(debug_assertions) && !self.check_args_compatible(def_id, args) {
+            if let DefKind::AssocTy = self.def_kind(def_id)
+                && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id))
+            {
+                bug!(
+                    "args not compatible with generics for {}: args={:#?}, generics={:#?}",
+                    self.def_path_str(def_id),
+                    args,
+                    // Make `[Self, GAT_ARGS...]` (this could be simplified)
+                    self.mk_args_from_iter(
+                        [self.types.self_param.into()].into_iter().chain(
+                            self.generics_of(def_id)
+                                .own_args(ty::GenericArgs::identity_for_item(self, def_id))
+                                .iter()
+                                .copied()
                         )
-                    );
-                } else {
-                    bug!(
-                        "args not compatible with generics for {}: args={:#?}, generics={:#?}",
-                        self.def_path_str(def_id),
-                        args,
-                        ty::GenericArgs::identity_for_item(self, def_id)
-                    );
-                }
+                    )
+                );
+            } else {
+                bug!(
+                    "args not compatible with generics for {}: args={:#?}, generics={:#?}",
+                    self.def_path_str(def_id),
+                    args,
+                    ty::GenericArgs::identity_for_item(self, def_id)
+                );
             }
         }
     }
@@ -3128,11 +3130,11 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn next_trait_solver_globally(self) -> bool {
-        self.sess.opts.unstable_opts.next_solver.globally
+        self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally)
     }
 
     pub fn next_trait_solver_in_coherence(self) -> bool {
-        self.sess.opts.unstable_opts.next_solver.coherence
+        self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.coherence)
     }
 
     pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 8cec8eac189..254a0119920 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1183,10 +1183,10 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
         //
         // This is not part of `codegen_fn_attrs` as it can differ between crates
         // and therefore cannot be computed in core.
-        if tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Abort {
-            if tcx.is_lang_item(did, LangItem::DropInPlace) {
-                return false;
-            }
+        if tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Abort
+            && tcx.is_lang_item(did, LangItem::DropInPlace)
+        {
+            return false;
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index f1ff90831b0..988516d100f 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1526,7 +1526,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
 
                 let precedence = |binop: rustc_middle::mir::BinOp| {
                     use rustc_ast::util::parser::AssocOp;
-                    AssocOp::from_ast_binop(binop.to_hir_binop().into()).precedence()
+                    AssocOp::from_ast_binop(binop.to_hir_binop()).precedence()
                 };
                 let op_precedence = precedence(op);
                 let formatted_op = op.to_hir_binop().as_str();
@@ -3361,10 +3361,8 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
                     // name.
                     //
                     // Any stable ordering would be fine here though.
-                    if *v.get() != symbol {
-                        if v.get().as_str() > symbol.as_str() {
-                            v.insert(symbol);
-                        }
+                    if *v.get() != symbol && v.get().as_str() > symbol.as_str() {
+                        v.insert(symbol);
                     }
                 }
                 Vacant(v) => {
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index a2a96105777..44956d5b0a6 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -431,7 +431,7 @@ impl BoundRegionKind {
 
     pub fn get_id(&self) -> Option<DefId> {
         match *self {
-            BoundRegionKind::BrNamed(id, _) => return Some(id),
+            BoundRegionKind::BrNamed(id, _) => Some(id),
             _ => None,
         }
     }
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 1f4f2c62d70..44309697ba9 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1091,29 +1091,21 @@ impl<'tcx> Ty<'tcx> {
     }
 
     pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
-        match self.kind() {
-            Adt(def, args) => {
-                assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type");
-                let variant = def.non_enum_variant();
-                let f0_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args);
-
-                match f0_ty.kind() {
-                    // If the first field is an array, we assume it is the only field and its
-                    // elements are the SIMD components.
-                    Array(f0_elem_ty, f0_len) => {
-                        // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112
-                        // The way we evaluate the `N` in `[T; N]` here only works since we use
-                        // `simd_size_and_type` post-monomorphization. It will probably start to ICE
-                        // if we use it in generic code. See the `simd-array-trait` ui test.
-                        (f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty)
-                    }
-                    // Otherwise, the fields of this Adt are the SIMD components (and we assume they
-                    // all have the same type).
-                    _ => (variant.fields.len() as u64, f0_ty),
-                }
-            }
-            _ => bug!("`simd_size_and_type` called on invalid type"),
-        }
+        let Adt(def, args) = self.kind() else {
+            bug!("`simd_size_and_type` called on invalid type")
+        };
+        assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type");
+        let variant = def.non_enum_variant();
+        assert_eq!(variant.fields.len(), 1);
+        let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args);
+        let Array(f0_elem_ty, f0_len) = field_ty.kind() else {
+            bug!("Simd type has non-array field type {field_ty:?}")
+        };
+        // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112
+        // The way we evaluate the `N` in `[T; N]` here only works since we use
+        // `simd_size_and_type` post-monomorphization. It will probably start to ICE
+        // if we use it in generic code. See the `simd-array-trait` ui test.
+        (f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty)
     }
 
     #[inline]
@@ -1136,6 +1128,7 @@ impl<'tcx> Ty<'tcx> {
     }
 
     /// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer).
+    /// `Box` is *not* considered a pointer here!
     #[inline]
     pub fn is_any_ptr(self) -> bool {
         self.is_ref() || self.is_unsafe_ptr() || self.is_fn_ptr()
diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs
index 3aa6e708476..6019a93e787 100644
--- a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs
+++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs
@@ -268,10 +268,9 @@ impl Builder<'_, '_> {
     pub(crate) fn mcdc_decrement_depth_if_enabled(&mut self) {
         if let Some(coverage_info) = self.coverage_info.as_mut()
             && let Some(mcdc_info) = coverage_info.mcdc_info.as_mut()
+            && mcdc_info.state.decision_ctx_stack.pop().is_none()
         {
-            if mcdc_info.state.decision_ctx_stack.pop().is_none() {
-                bug!("Unexpected empty decision stack");
-            }
+            bug!("Unexpected empty decision stack");
         };
     }
 }
diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs
index 646aefa0882..1f186c8f99a 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse.rs
@@ -82,13 +82,11 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
     fn statement_as_expr(&self, stmt_id: StmtId) -> PResult<ExprId> {
         match &self.thir[stmt_id].kind {
             StmtKind::Expr { expr, .. } => Ok(*expr),
-            kind @ StmtKind::Let { pattern, .. } => {
-                return Err(ParseError {
-                    span: pattern.span,
-                    item_description: format!("{kind:?}"),
-                    expected: "expression".to_string(),
-                });
-            }
+            kind @ StmtKind::Let { pattern, .. } => Err(ParseError {
+                span: pattern.span,
+                item_description: format!("{kind:?}"),
+                expected: "expression".to_string(),
+            }),
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs
index 18a0746f54f..24c955c0c78 100644
--- a/compiler/rustc_mir_transform/src/add_call_guards.rs
+++ b/compiler/rustc_mir_transform/src/add_call_guards.rs
@@ -32,12 +32,6 @@ pub(super) use self::AddCallGuards::*;
 
 impl<'tcx> crate::MirPass<'tcx> for AddCallGuards {
     fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        self.add_call_guards(body);
-    }
-}
-
-impl AddCallGuards {
-    pub(super) fn add_call_guards(&self, body: &mut Body<'_>) {
         let mut pred_count: IndexVec<_, _> =
             body.basic_blocks.predecessors().iter().map(|ps| ps.len()).collect();
         pred_count[START_BLOCK] += 1;
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index 47572d8d3b2..74df5f7479e 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -40,35 +40,34 @@ pub(super) struct AddMovesForPackedDrops;
 impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span);
-        add_moves_for_packed_drops(tcx, body);
-    }
-}
-
-fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let patch = add_moves_for_packed_drops_patch(tcx, body);
-    patch.apply(body);
-}
 
-fn add_moves_for_packed_drops_patch<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> MirPatch<'tcx> {
-    let def_id = body.source.def_id();
-    let mut patch = MirPatch::new(body);
-    let param_env = tcx.param_env(def_id);
+        let def_id = body.source.def_id();
+        let mut patch = MirPatch::new(body);
+        let param_env = tcx.param_env(def_id);
 
-    for (bb, data) in body.basic_blocks.iter_enumerated() {
-        let loc = Location { block: bb, statement_index: data.statements.len() };
-        let terminator = data.terminator();
+        for (bb, data) in body.basic_blocks.iter_enumerated() {
+            let loc = Location { block: bb, statement_index: data.statements.len() };
+            let terminator = data.terminator();
 
-        match terminator.kind {
-            TerminatorKind::Drop { place, .. }
-                if util::is_disaligned(tcx, body, param_env, place) =>
-            {
-                add_move_for_packed_drop(tcx, body, &mut patch, terminator, loc, data.is_cleanup);
+            match terminator.kind {
+                TerminatorKind::Drop { place, .. }
+                    if util::is_disaligned(tcx, body, param_env, place) =>
+                {
+                    add_move_for_packed_drop(
+                        tcx,
+                        body,
+                        &mut patch,
+                        terminator,
+                        loc,
+                        data.is_cleanup,
+                    );
+                }
+                _ => {}
             }
-            _ => {}
         }
-    }
 
-    patch
+        patch.apply(body);
+    }
 }
 
 fn add_move_for_packed_drop<'tcx>(
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index 794e85fbfed..8ad364ed055 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -60,7 +60,9 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag {
         let basic_blocks = body.basic_blocks.as_mut();
         let local_decls = &body.local_decls;
         let needs_retag = |place: &Place<'tcx>| {
-            !place.is_indirect_first_projection() // we're not really interested in stores to "outside" locations, they are hard to keep track of anyway
+            // We're not really interested in stores to "outside" locations, they are hard to keep
+            // track of anyway.
+            !place.is_indirect_first_projection()
                 && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
                 && !local_decls[place.local].is_deref_temp()
         };
@@ -129,9 +131,9 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag {
                     StatementKind::Assign(box (ref place, ref rvalue)) => {
                         let add_retag = match rvalue {
                             // Ptr-creating operations already do their own internal retagging, no
-                            // need to also add a retag statement.
-                            // *Except* if we are deref'ing a Box, because those get desugared to directly working
-                            // with the inner raw pointer! That's relevant for `RawPtr` as Miri otherwise makes it
+                            // need to also add a retag statement. *Except* if we are deref'ing a
+                            // Box, because those get desugared to directly working with the inner
+                            // raw pointer! That's relevant for `RawPtr` as Miri otherwise makes it
                             // a NOP when the original pointer is already raw.
                             Rvalue::RawPtr(_mutbl, place) => {
                                 // Using `is_box_global` here is a bit sketchy: if this code is
diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
index ab6bf18b30c..e585e338613 100644
--- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
+++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
@@ -51,18 +51,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> {
 // // gets transformed to
 // let temp: rval_ty = rval;
 // let place: place_ty = temp as place_ty;
-fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let patch = MirPatch::new(body);
-    let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls };
-
-    for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
-        checker.visit_basic_block_data(bb, data);
-    }
-    checker.patcher.apply(body);
-}
-
 impl<'tcx> crate::MirPass<'tcx> for Subtyper {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        subtype_finder(tcx, body);
+        let patch = MirPatch::new(body);
+        let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls };
+
+        for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
+            checker.visit_basic_block_data(bb, data);
+        }
+        checker.patcher.apply(body);
     }
 }
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index 234ed8206f5..9c3cbbe1fc9 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -95,19 +95,19 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
             // Check for assignment to fields of a constant
             // Assigning directly to a constant (e.g. `FOO = true;`) is a hard error,
             // so emitting a lint would be redundant.
-            if !lhs.projection.is_empty() {
-                if let Some(def_id) = self.is_const_item_without_destructor(lhs.local)
-                    && let Some((lint_root, span, item)) =
-                        self.should_lint_const_item_usage(lhs, def_id, loc)
-                {
-                    self.tcx.emit_node_span_lint(
-                        CONST_ITEM_MUTATION,
-                        lint_root,
-                        span,
-                        errors::ConstMutate::Modify { konst: item },
-                    );
-                }
+            if !lhs.projection.is_empty()
+                && let Some(def_id) = self.is_const_item_without_destructor(lhs.local)
+                && let Some((lint_root, span, item)) =
+                    self.should_lint_const_item_usage(lhs, def_id, loc)
+            {
+                self.tcx.emit_node_span_lint(
+                    CONST_ITEM_MUTATION,
+                    lint_root,
+                    span,
+                    errors::ConstMutate::Modify { konst: item },
+                );
             }
+
             // We are looking for MIR of the form:
             //
             // ```
@@ -123,6 +123,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
         self.super_statement(stmt, loc);
         self.target_local = None;
     }
+
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, loc: Location) {
         if let Rvalue::Ref(_, BorrowKind::Mut { .. }, place) = rvalue {
             let local = place.local;
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index dc4ee58ea83..b3db5669121 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -27,37 +27,34 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp {
     #[instrument(level = "trace", skip(self, tcx, body))]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!(def_id = ?body.source.def_id());
-        propagate_ssa(tcx, body);
-    }
-}
 
-fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
-    let ssa = SsaLocals::new(tcx, body, param_env);
+        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+        let ssa = SsaLocals::new(tcx, body, param_env);
 
-    let fully_moved = fully_moved_locals(&ssa, body);
-    debug!(?fully_moved);
+        let fully_moved = fully_moved_locals(&ssa, body);
+        debug!(?fully_moved);
 
-    let mut storage_to_remove = BitSet::new_empty(fully_moved.domain_size());
-    for (local, &head) in ssa.copy_classes().iter_enumerated() {
-        if local != head {
-            storage_to_remove.insert(head);
+        let mut storage_to_remove = BitSet::new_empty(fully_moved.domain_size());
+        for (local, &head) in ssa.copy_classes().iter_enumerated() {
+            if local != head {
+                storage_to_remove.insert(head);
+            }
         }
-    }
 
-    let any_replacement = ssa.copy_classes().iter_enumerated().any(|(l, &h)| l != h);
+        let any_replacement = ssa.copy_classes().iter_enumerated().any(|(l, &h)| l != h);
 
-    Replacer {
-        tcx,
-        copy_classes: ssa.copy_classes(),
-        fully_moved,
-        borrowed_locals: ssa.borrowed_locals(),
-        storage_to_remove,
-    }
-    .visit_body_preserves_cfg(body);
+        Replacer {
+            tcx,
+            copy_classes: ssa.copy_classes(),
+            fully_moved,
+            borrowed_locals: ssa.borrowed_locals(),
+            storage_to_remove,
+        }
+        .visit_body_preserves_cfg(body);
 
-    if any_replacement {
-        crate::simplify::remove_unused_definitions(body);
+        if any_replacement {
+            crate::simplify::remove_unused_definitions(body);
+        }
     }
 }
 
@@ -140,7 +137,8 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
 
     fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) {
         if let Operand::Move(place) = *operand
-            // A move out of a projection of a copy is equivalent to a copy of the original projection.
+            // A move out of a projection of a copy is equivalent to a copy of the original
+            // projection.
             && !place.is_indirect_first_projection()
             && !self.fully_moved.contains(place.local)
         {
diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs
index ea1c0d2df45..1c240366afa 100644
--- a/compiler/rustc_mir_transform/src/coverage/counters.rs
+++ b/compiler/rustc_mir_transform/src/coverage/counters.rs
@@ -74,12 +74,11 @@ pub(super) struct CoverageCounters {
 }
 
 impl CoverageCounters {
-    /// Makes [`BcbCounter`] `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or
-    /// indirectly associated with coverage spans, and accumulates additional `Expression`s
-    /// representing intermediate values.
+    /// Ensures that each BCB node needing a counter has one, by creating physical
+    /// counters or counter expressions for nodes and edges as required.
     pub(super) fn make_bcb_counters(
         basic_coverage_blocks: &CoverageGraph,
-        bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool,
+        bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool,
     ) -> Self {
         let num_bcbs = basic_coverage_blocks.num_nodes();
 
@@ -91,8 +90,7 @@ impl CoverageCounters {
             expressions_memo: FxHashMap::default(),
         };
 
-        MakeBcbCounters::new(&mut this, basic_coverage_blocks)
-            .make_bcb_counters(bcb_has_coverage_spans);
+        MakeBcbCounters::new(&mut this, basic_coverage_blocks).make_bcb_counters(bcb_needs_counter);
 
         this
     }
@@ -241,10 +239,7 @@ impl CoverageCounters {
     }
 }
 
-/// Traverse the `CoverageGraph` and add either a `Counter` or `Expression` to every BCB, to be
-/// injected with coverage spans. `Expressions` have no runtime overhead, so if a viable expression
-/// (adding or subtracting two other counters or expressions) can compute the same result as an
-/// embedded counter, an `Expression` should be used.
+/// Helper struct that allows counter creation to inspect the BCB graph.
 struct MakeBcbCounters<'a> {
     coverage_counters: &'a mut CoverageCounters,
     basic_coverage_blocks: &'a CoverageGraph,
@@ -258,36 +253,21 @@ impl<'a> MakeBcbCounters<'a> {
         Self { coverage_counters, basic_coverage_blocks }
     }
 
-    /// If two `BasicCoverageBlock`s branch from another `BasicCoverageBlock`, one of the branches
-    /// can be counted by `Expression` by subtracting the other branch from the branching
-    /// block. Otherwise, the `BasicCoverageBlock` executed the least should have the `Counter`.
-    /// One way to predict which branch executes the least is by considering loops. A loop is exited
-    /// at a branch, so the branch that jumps to a `BasicCoverageBlock` outside the loop is almost
-    /// always executed less than the branch that does not exit the loop.
-    fn make_bcb_counters(&mut self, bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool) {
+    fn make_bcb_counters(&mut self, bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool) {
         debug!("make_bcb_counters(): adding a counter or expression to each BasicCoverageBlock");
 
-        // Walk the `CoverageGraph`. For each `BasicCoverageBlock` node with an associated
-        // coverage span, add a counter. If the `BasicCoverageBlock` branches, add a counter or
-        // expression to each branch `BasicCoverageBlock` (if the branch BCB has only one incoming
-        // edge) or edge from the branching BCB to the branch BCB (if the branch BCB has multiple
-        // incoming edges).
+        // Traverse the coverage graph, ensuring that every node that needs a
+        // coverage counter has one.
         //
-        // The `TraverseCoverageGraphWithLoops` traversal ensures that, when a loop is encountered,
-        // all `BasicCoverageBlock` nodes in the loop are visited before visiting any node outside
-        // the loop. The `traversal` state includes a `context_stack`, providing a way to know if
-        // the current BCB is in one or more nested loops or not.
+        // The traversal tries to ensure that, when a loop is encountered, all
+        // nodes within the loop are visited before visiting any nodes outside
+        // the loop. It also keeps track of which loop(s) the traversal is
+        // currently inside.
         let mut traversal = TraverseCoverageGraphWithLoops::new(self.basic_coverage_blocks);
         while let Some(bcb) = traversal.next() {
-            if bcb_has_coverage_spans(bcb) {
-                debug!("{:?} has at least one coverage span. Get or make its counter", bcb);
-                self.make_node_and_branch_counters(&traversal, bcb);
-            } else {
-                debug!(
-                    "{:?} does not have any coverage spans. A counter will only be added if \
-                    and when a covered BCB has an expression dependency.",
-                    bcb,
-                );
+            let _span = debug_span!("traversal", ?bcb).entered();
+            if bcb_needs_counter(bcb) {
+                self.make_node_counter_and_out_edge_counters(&traversal, bcb);
             }
         }
 
@@ -298,73 +278,66 @@ impl<'a> MakeBcbCounters<'a> {
         );
     }
 
-    fn make_node_and_branch_counters(
+    /// Make sure the given node has a node counter, and then make sure each of
+    /// its out-edges has an edge counter (if appropriate).
+    #[instrument(level = "debug", skip(self, traversal))]
+    fn make_node_counter_and_out_edge_counters(
         &mut self,
         traversal: &TraverseCoverageGraphWithLoops<'_>,
         from_bcb: BasicCoverageBlock,
     ) {
         // First, ensure that this node has a counter of some kind.
-        // We might also use its term later to compute one of the branch counters.
-        let from_bcb_operand = self.get_or_make_counter_operand(from_bcb);
+        // We might also use that counter to compute one of the out-edge counters.
+        let node_counter = self.get_or_make_node_counter(from_bcb);
 
-        let branch_target_bcbs = self.basic_coverage_blocks.successors[from_bcb].as_slice();
+        let successors = self.basic_coverage_blocks.successors[from_bcb].as_slice();
 
         // If this node doesn't have multiple out-edges, or all of its out-edges
         // already have counters, then we don't need to create edge counters.
-        let needs_branch_counters = branch_target_bcbs.len() > 1
-            && branch_target_bcbs
-                .iter()
-                .any(|&to_bcb| self.branch_has_no_counter(from_bcb, to_bcb));
-        if !needs_branch_counters {
+        let needs_out_edge_counters = successors.len() > 1
+            && successors.iter().any(|&to_bcb| self.edge_has_no_counter(from_bcb, to_bcb));
+        if !needs_out_edge_counters {
             return;
         }
 
-        debug!(
-            "{from_bcb:?} has some branch(es) without counters:\n  {}",
-            branch_target_bcbs
-                .iter()
-                .map(|&to_bcb| {
-                    format!("{from_bcb:?}->{to_bcb:?}: {:?}", self.branch_counter(from_bcb, to_bcb))
-                })
-                .collect::<Vec<_>>()
-                .join("\n  "),
-        );
+        if tracing::enabled!(tracing::Level::DEBUG) {
+            let _span =
+                debug_span!("node has some out-edges without counters", ?from_bcb).entered();
+            for &to_bcb in successors {
+                debug!(?to_bcb, counter=?self.edge_counter(from_bcb, to_bcb));
+            }
+        }
 
-        // Of the branch edges that don't have counters yet, one can be given an expression
-        // (computed from the other edges) instead of a dedicated counter.
-        let expression_to_bcb = self.choose_preferred_expression_branch(traversal, from_bcb);
+        // Of the out-edges that don't have counters yet, one can be given an expression
+        // (computed from the other out-edges) instead of a dedicated counter.
+        let expression_to_bcb = self.choose_out_edge_for_expression(traversal, from_bcb);
 
-        // For each branch arm other than the one that was chosen to get an expression,
+        // For each out-edge other than the one that was chosen to get an expression,
         // ensure that it has a counter (existing counter/expression or a new counter),
-        // and accumulate the corresponding terms into a single sum term.
-        let sum_of_all_other_branches: BcbCounter = {
-            let _span = debug_span!("sum_of_all_other_branches", ?expression_to_bcb).entered();
-            branch_target_bcbs
+        // and accumulate the corresponding counters into a single sum expression.
+        let sum_of_all_other_out_edges: BcbCounter = {
+            let _span = debug_span!("sum_of_all_other_out_edges", ?expression_to_bcb).entered();
+            successors
                 .iter()
                 .copied()
-                // Skip the chosen branch, since we'll calculate it from the other branches.
+                // Skip the chosen edge, since we'll calculate its count from this sum.
                 .filter(|&to_bcb| to_bcb != expression_to_bcb)
                 .fold(None, |accum, to_bcb| {
                     let _span = debug_span!("to_bcb", ?accum, ?to_bcb).entered();
-                    let branch_counter = self.get_or_make_edge_counter_operand(from_bcb, to_bcb);
-                    Some(self.coverage_counters.make_sum_expression(accum, branch_counter))
+                    let edge_counter = self.get_or_make_edge_counter(from_bcb, to_bcb);
+                    Some(self.coverage_counters.make_sum_expression(accum, edge_counter))
                 })
-                .expect("there must be at least one other branch")
+                .expect("there must be at least one other out-edge")
         };
 
-        // For the branch that was chosen to get an expression, create that expression
-        // by taking the count of the node we're branching from, and subtracting the
-        // sum of all the other branches.
-        debug!(
-            "Making an expression for the selected expression_branch: \
-            {expression_to_bcb:?} (expression_branch predecessors: {:?})",
-            self.bcb_predecessors(expression_to_bcb),
-        );
+        // Now create an expression for the chosen edge, by taking the counter
+        // for its source node and subtracting the sum of its sibling out-edges.
         let expression = self.coverage_counters.make_expression(
-            from_bcb_operand,
+            node_counter,
             Op::Subtract,
-            sum_of_all_other_branches,
+            sum_of_all_other_out_edges,
         );
+
         debug!("{expression_to_bcb:?} gets an expression: {expression:?}");
         if self.basic_coverage_blocks.bcb_has_multiple_in_edges(expression_to_bcb) {
             self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression);
@@ -374,7 +347,7 @@ impl<'a> MakeBcbCounters<'a> {
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
+    fn get_or_make_node_counter(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
         // If the BCB already has a counter, return it.
         if let Some(counter_kind) = self.coverage_counters.bcb_counters[bcb] {
             debug!("{bcb:?} already has a counter: {counter_kind:?}");
@@ -411,7 +384,7 @@ impl<'a> MakeBcbCounters<'a> {
                 .copied()
                 .fold(None, |accum, from_bcb| {
                     let _span = debug_span!("from_bcb", ?accum, ?from_bcb).entered();
-                    let edge_counter = self.get_or_make_edge_counter_operand(from_bcb, bcb);
+                    let edge_counter = self.get_or_make_edge_counter(from_bcb, bcb);
                     Some(self.coverage_counters.make_sum_expression(accum, edge_counter))
                 })
                 .expect("there must be at least one in-edge")
@@ -422,7 +395,7 @@ impl<'a> MakeBcbCounters<'a> {
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn get_or_make_edge_counter_operand(
+    fn get_or_make_edge_counter(
         &mut self,
         from_bcb: BasicCoverageBlock,
         to_bcb: BasicCoverageBlock,
@@ -431,13 +404,13 @@ impl<'a> MakeBcbCounters<'a> {
         // a node counter instead, since it will have the same value.
         if !self.basic_coverage_blocks.bcb_has_multiple_in_edges(to_bcb) {
             assert_eq!([from_bcb].as_slice(), self.basic_coverage_blocks.predecessors[to_bcb]);
-            return self.get_or_make_counter_operand(to_bcb);
+            return self.get_or_make_node_counter(to_bcb);
         }
 
         // If the source BCB has only one successor (assumed to be the given target), an edge
         // counter is unnecessary. Just get or make a counter for the source BCB.
         if self.bcb_successors(from_bcb).len() == 1 {
-            return self.get_or_make_counter_operand(from_bcb);
+            return self.get_or_make_node_counter(from_bcb);
         }
 
         // If the edge already has a counter, return it.
@@ -455,82 +428,79 @@ impl<'a> MakeBcbCounters<'a> {
         self.coverage_counters.set_bcb_edge_counter(from_bcb, to_bcb, counter_kind)
     }
 
-    /// Select a branch for the expression, either the recommended `reloop_branch`, or if none was
-    /// found, select any branch.
-    fn choose_preferred_expression_branch(
+    /// Choose one of the out-edges of `from_bcb` to receive an expression
+    /// instead of a physical counter, and returns that edge's target node.
+    ///
+    /// - Precondition: The node must have at least one out-edge without a counter.
+    /// - Postcondition: The selected edge does not have an edge counter.
+    fn choose_out_edge_for_expression(
         &self,
         traversal: &TraverseCoverageGraphWithLoops<'_>,
         from_bcb: BasicCoverageBlock,
     ) -> BasicCoverageBlock {
-        let good_reloop_branch = self.find_good_reloop_branch(traversal, from_bcb);
-        if let Some(reloop_target) = good_reloop_branch {
-            assert!(self.branch_has_no_counter(from_bcb, reloop_target));
+        if let Some(reloop_target) = self.find_good_reloop_edge(traversal, from_bcb) {
+            assert!(self.edge_has_no_counter(from_bcb, reloop_target));
             debug!("Selecting reloop target {reloop_target:?} to get an expression");
-            reloop_target
-        } else {
-            let &branch_without_counter = self
-                .bcb_successors(from_bcb)
-                .iter()
-                .find(|&&to_bcb| self.branch_has_no_counter(from_bcb, to_bcb))
-                .expect(
-                    "needs_branch_counters was `true` so there should be at least one \
-                    branch",
-                );
-            debug!(
-                "Selecting any branch={:?} that still needs a counter, to get the \
-                `Expression` because there was no `reloop_branch`, or it already had a \
-                counter",
-                branch_without_counter
-            );
-            branch_without_counter
+            return reloop_target;
         }
+
+        // We couldn't identify a "good" edge, so just choose any edge that
+        // doesn't already have a counter.
+        let arbitrary_target = self
+            .bcb_successors(from_bcb)
+            .iter()
+            .copied()
+            .find(|&to_bcb| self.edge_has_no_counter(from_bcb, to_bcb))
+            .expect("precondition: at least one out-edge without a counter");
+        debug!(?arbitrary_target, "selecting arbitrary out-edge to get an expression");
+        arbitrary_target
     }
 
-    /// Tries to find a branch that leads back to the top of a loop, and that
-    /// doesn't already have a counter. Such branches are good candidates to
+    /// Tries to find an edge that leads back to the top of a loop, and that
+    /// doesn't already have a counter. Such edges are good candidates to
     /// be given an expression (instead of a physical counter), because they
-    /// will tend to be executed more times than a loop-exit branch.
-    fn find_good_reloop_branch(
+    /// will tend to be executed more times than a loop-exit edge.
+    fn find_good_reloop_edge(
         &self,
         traversal: &TraverseCoverageGraphWithLoops<'_>,
         from_bcb: BasicCoverageBlock,
     ) -> Option<BasicCoverageBlock> {
-        let branch_target_bcbs = self.bcb_successors(from_bcb);
+        let successors = self.bcb_successors(from_bcb);
 
         // Consider each loop on the current traversal context stack, top-down.
         for reloop_bcbs in traversal.reloop_bcbs_per_loop() {
-            let mut all_branches_exit_this_loop = true;
+            let mut all_edges_exit_this_loop = true;
 
-            // Try to find a branch that doesn't exit this loop and doesn't
+            // Try to find an out-edge that doesn't exit this loop and doesn't
             // already have a counter.
-            for &branch_target_bcb in branch_target_bcbs {
-                // A branch is a reloop branch if it dominates any BCB that has
-                // an edge back to the loop header. (Other branches are exits.)
-                let is_reloop_branch = reloop_bcbs.iter().any(|&reloop_bcb| {
-                    self.basic_coverage_blocks.dominates(branch_target_bcb, reloop_bcb)
+            for &target_bcb in successors {
+                // An edge is a reloop edge if its target dominates any BCB that has
+                // an edge back to the loop header. (Otherwise it's an exit edge.)
+                let is_reloop_edge = reloop_bcbs.iter().any(|&reloop_bcb| {
+                    self.basic_coverage_blocks.dominates(target_bcb, reloop_bcb)
                 });
 
-                if is_reloop_branch {
-                    all_branches_exit_this_loop = false;
-                    if self.branch_has_no_counter(from_bcb, branch_target_bcb) {
-                        // We found a good branch to be given an expression.
-                        return Some(branch_target_bcb);
+                if is_reloop_edge {
+                    all_edges_exit_this_loop = false;
+                    if self.edge_has_no_counter(from_bcb, target_bcb) {
+                        // We found a good out-edge to be given an expression.
+                        return Some(target_bcb);
                     }
-                    // Keep looking for another reloop branch without a counter.
+                    // Keep looking for another reloop edge without a counter.
                 } else {
-                    // This branch exits the loop.
+                    // This edge exits the loop.
                 }
             }
 
-            if !all_branches_exit_this_loop {
-                // We found one or more reloop branches, but all of them already
-                // have counters. Let the caller choose one of the exit branches.
-                debug!("All reloop branches had counters; skip checking the other loops");
+            if !all_edges_exit_this_loop {
+                // We found one or more reloop edges, but all of them already
+                // have counters. Let the caller choose one of the other edges.
+                debug!("All reloop edges had counters; skipping the other loops");
                 return None;
             }
 
-            // All of the branches exit this loop, so keep looking for a good
-            // reloop branch for one of the outer loops.
+            // All of the out-edges exit this loop, so keep looking for a good
+            // reloop edge for one of the outer loops.
         }
 
         None
@@ -547,15 +517,15 @@ impl<'a> MakeBcbCounters<'a> {
     }
 
     #[inline]
-    fn branch_has_no_counter(
+    fn edge_has_no_counter(
         &self,
         from_bcb: BasicCoverageBlock,
         to_bcb: BasicCoverageBlock,
     ) -> bool {
-        self.branch_counter(from_bcb, to_bcb).is_none()
+        self.edge_counter(from_bcb, to_bcb).is_none()
     }
 
-    fn branch_counter(
+    fn edge_counter(
         &self,
         from_bcb: BasicCoverageBlock,
         to_bcb: BasicCoverageBlock,
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 042f589768a..f78fc7931f9 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -279,7 +279,8 @@ fn inject_mcdc_statements<'tcx>(
     basic_coverage_blocks: &CoverageGraph,
     extracted_mappings: &ExtractedMappings,
 ) {
-    // Inject test vector update first because `inject_statement` always insert new statement at head.
+    // Inject test vector update first because `inject_statement` always insert new statement at
+    // head.
     for &mappings::MCDCDecision {
         span: _,
         ref end_bcbs,
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 79f12be4bc3..7ac019ce812 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -647,7 +647,8 @@ fn try_write_constant<'tcx>(
         ty::FnDef(..) => {}
 
         // Those are scalars, must be handled above.
-        ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => throw_machine_stop_str!("primitive type with provenance"),
+        ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char =>
+            throw_machine_stop_str!("primitive type with provenance"),
 
         ty::Tuple(elem_tys) => {
             for (i, elem) in elem_tys.iter().enumerate() {
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index e870a71b05a..c0cb0e641ac 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -42,9 +42,9 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
             }
             PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) => {
                 // Whether mutating though a `&raw const` is allowed is still undecided, so we
-                // disable any sketchy `readonly` optimizations for now.
-                // But we only need to do this if the pointer would point into the argument.
-                // IOW: for indirect places, like `&raw (*local).field`, this surely cannot mutate `local`.
+                // disable any sketchy `readonly` optimizations for now. But we only need to do
+                // this if the pointer would point into the argument. IOW: for indirect places,
+                // like `&raw (*local).field`, this surely cannot mutate `local`.
                 !place.is_indirect()
             }
             PlaceContext::NonMutatingUse(..) | PlaceContext::NonUse(..) => {
@@ -168,17 +168,16 @@ pub(super) fn deduced_param_attrs<'tcx>(
     // Codegen won't use this information for anything if all the function parameters are passed
     // directly. Detect that and bail, for compilation speed.
     let fn_ty = tcx.type_of(def_id).instantiate_identity();
-    if matches!(fn_ty.kind(), ty::FnDef(..)) {
-        if fn_ty
+    if matches!(fn_ty.kind(), ty::FnDef(..))
+        && fn_ty
             .fn_sig(tcx)
             .inputs()
             .skip_binder()
             .iter()
             .cloned()
             .all(type_will_always_be_passed_directly)
-        {
-            return &[];
-        }
+    {
+        return &[];
     }
 
     // Don't deduce any attributes for functions that have no MIR.
diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
index c8179d513c7..ad204e76d0d 100644
--- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
+++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
@@ -69,8 +69,8 @@ fn find_duplicates(body: &Body<'_>) -> FxHashMap<BasicBlock, BasicBlock> {
     // For example, if bb1, bb2 and bb3 are duplicates, we will first insert bb3 in same_hashes.
     // Then we will see that bb2 is a duplicate of bb3,
     // and insert bb2 with the replacement bb3 in the duplicates list.
-    // When we see bb1, we see that it is a duplicate of bb3, and therefore insert it in the duplicates list
-    // with replacement bb3.
+    // When we see bb1, we see that it is a duplicate of bb3, and therefore insert it in the
+    // duplicates list with replacement bb3.
     // When the duplicates are removed, we will end up with only bb3.
     for (bb, bbd) in body.basic_blocks.iter_enumerated().rev().filter(|(_, bbd)| !bbd.is_cleanup) {
         // Basic blocks can get really big, so to avoid checking for duplicates in basic blocks
@@ -105,7 +105,8 @@ struct BasicBlockHashable<'tcx, 'a> {
 impl Hash for BasicBlockHashable<'_, '_> {
     fn hash<H: Hasher>(&self, state: &mut H) {
         hash_statements(state, self.basic_block_data.statements.iter());
-        // Note that since we only hash the kind, we lose span information if we deduplicate the blocks
+        // Note that since we only hash the kind, we lose span information if we deduplicate the
+        // blocks.
         self.basic_block_data.terminator().kind.hash(state);
     }
 }
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 175097e30ee..f123658580d 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -242,7 +242,7 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
             }
             round_count += 1;
 
-            apply_merges(body, tcx, &merges, &merged_locals);
+            apply_merges(body, tcx, merges, merged_locals);
         }
 
         trace!(round_count);
@@ -281,20 +281,20 @@ struct Candidates {
 fn apply_merges<'tcx>(
     body: &mut Body<'tcx>,
     tcx: TyCtxt<'tcx>,
-    merges: &FxIndexMap<Local, Local>,
-    merged_locals: &BitSet<Local>,
+    merges: FxIndexMap<Local, Local>,
+    merged_locals: BitSet<Local>,
 ) {
     let mut merger = Merger { tcx, merges, merged_locals };
     merger.visit_body_preserves_cfg(body);
 }
 
-struct Merger<'a, 'tcx> {
+struct Merger<'tcx> {
     tcx: TyCtxt<'tcx>,
-    merges: &'a FxIndexMap<Local, Local>,
-    merged_locals: &'a BitSet<Local>,
+    merges: FxIndexMap<Local, Local>,
+    merged_locals: BitSet<Local>,
 }
 
-impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> {
+impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
index 3884321df2a..704ed508b22 100644
--- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
+++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
@@ -261,8 +261,8 @@ fn evaluate_candidate<'tcx>(
         // };
         // ```
         //
-        // Hoisting the `discriminant(Q)` out of the `A` arm causes us to compute the discriminant of an
-        // invalid value, which is UB.
+        // Hoisting the `discriminant(Q)` out of the `A` arm causes us to compute the discriminant
+        // of an invalid value, which is UB.
         // In order to fix this, **we would either need to show that the discriminant computation of
         // `place` is computed in all branches**.
         // FIXME(#95162) For the moment, we adopt a conservative approach and
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index cb729792dc5..42d13fa3613 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -20,8 +20,8 @@ use tracing::{debug, instrument};
 use crate::deref_separator::deref_finder;
 
 /// During MIR building, Drop terminators are inserted in every place where a drop may occur.
-/// However, in this phase, the presence of these terminators does not guarantee that a destructor will run,
-/// as the target of the drop may be uninitialized.
+/// However, in this phase, the presence of these terminators does not guarantee that a destructor
+/// will run, as the target of the drop may be uninitialized.
 /// In general, the compiler cannot determine at compile time whether a destructor will run or not.
 ///
 /// At a high level, this pass refines Drop to only run the destructor if the
@@ -30,10 +30,10 @@ use crate::deref_separator::deref_finder;
 /// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or
 /// "drop shim" for the type of the dropped place.
 ///
-/// This pass relies on dropped places having an associated move path, which is then used to determine
-/// the initialization status of the place and its descendants.
-/// It's worth noting that a MIR containing a Drop without an associated move path is probably ill formed,
-/// as it would allow running a destructor on a place behind a reference:
+/// This pass relies on dropped places having an associated move path, which is then used to
+/// determine the initialization status of the place and its descendants.
+/// It's worth noting that a MIR containing a Drop without an associated move path is probably ill
+/// formed, as it would allow running a destructor on a place behind a reference:
 ///
 /// ```text
 /// fn drop_term<T>(t: &mut T) {
@@ -377,8 +377,8 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
                         );
                     }
                     // A drop and replace behind a pointer/array/whatever.
-                    // The borrow checker requires that these locations are initialized before the assignment,
-                    // so we just leave an unconditional drop.
+                    // The borrow checker requires that these locations are initialized before the
+                    // assignment, so we just leave an unconditional drop.
                     assert!(!data.is_cleanup);
                 }
             }
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 81875e3d012..8490b7e2358 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -60,8 +60,9 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
         let fn_def_id = match ty.kind() {
             ty::FnPtr(..) => None,
             &ty::FnDef(def_id, _) => {
-                // Rust calls cannot themselves create foreign unwinds (even if they use a non-Rust ABI).
-                // So the leak of the foreign unwind into Rust can only be elsewhere, not here.
+                // Rust calls cannot themselves create foreign unwinds (even if they use a non-Rust
+                // ABI). So the leak of the foreign unwind into Rust can only be elsewhere, not
+                // here.
                 if !tcx.is_foreign_item(def_id) {
                     continue;
                 }
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 0efaa172e0c..eb09a7d3b21 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -92,8 +92,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
                             {
                                 let mut span = self.nth_arg_span(args, arg_num);
                                 if span.from_expansion() {
-                                    // The operand's ctxt wouldn't display the lint since it's inside a macro so
-                                    // we have to use the callsite's ctxt.
+                                    // The operand's ctxt wouldn't display the lint since it's
+                                    // inside a macro so we have to use the callsite's ctxt.
                                     let callsite_ctxt = span.source_callsite().ctxt();
                                     span = span.with_ctxt(callsite_ctxt);
                                 }
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index e5d2b13efd8..598bf61483d 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -119,53 +119,50 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
     #[instrument(level = "trace", skip(self, tcx, body))]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!(def_id = ?body.source.def_id());
-        propagate_ssa(tcx, body);
-    }
-}
 
-fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
-    let ssa = SsaLocals::new(tcx, body, param_env);
-    // Clone dominators as we need them while mutating the body.
-    let dominators = body.basic_blocks.dominators().clone();
-
-    let mut state = VnState::new(tcx, body, param_env, &ssa, &dominators, &body.local_decls);
-    ssa.for_each_assignment_mut(
-        body.basic_blocks.as_mut_preserves_cfg(),
-        |local, value, location| {
-            let value = match value {
-                // We do not know anything of this assigned value.
-                AssignedValue::Arg | AssignedValue::Terminator => None,
-                // Try to get some insight.
-                AssignedValue::Rvalue(rvalue) => {
-                    let value = state.simplify_rvalue(rvalue, location);
-                    // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark `local` as
-                    // reusable if we have an exact type match.
-                    if state.local_decls[local].ty != rvalue.ty(state.local_decls, tcx) {
-                        return;
+        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+        let ssa = SsaLocals::new(tcx, body, param_env);
+        // Clone dominators because we need them while mutating the body.
+        let dominators = body.basic_blocks.dominators().clone();
+
+        let mut state = VnState::new(tcx, body, param_env, &ssa, dominators, &body.local_decls);
+        ssa.for_each_assignment_mut(
+            body.basic_blocks.as_mut_preserves_cfg(),
+            |local, value, location| {
+                let value = match value {
+                    // We do not know anything of this assigned value.
+                    AssignedValue::Arg | AssignedValue::Terminator => None,
+                    // Try to get some insight.
+                    AssignedValue::Rvalue(rvalue) => {
+                        let value = state.simplify_rvalue(rvalue, location);
+                        // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark
+                        // `local` as reusable if we have an exact type match.
+                        if state.local_decls[local].ty != rvalue.ty(state.local_decls, tcx) {
+                            return;
+                        }
+                        value
                     }
-                    value
-                }
-            };
-            // `next_opaque` is `Some`, so `new_opaque` must return `Some`.
-            let value = value.or_else(|| state.new_opaque()).unwrap();
-            state.assign(local, value);
-        },
-    );
-
-    // Stop creating opaques during replacement as it is useless.
-    state.next_opaque = None;
-
-    let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec();
-    for bb in reverse_postorder {
-        let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb];
-        state.visit_basic_block_data(bb, data);
-    }
+                };
+                // `next_opaque` is `Some`, so `new_opaque` must return `Some`.
+                let value = value.or_else(|| state.new_opaque()).unwrap();
+                state.assign(local, value);
+            },
+        );
+
+        // Stop creating opaques during replacement as it is useless.
+        state.next_opaque = None;
 
-    // For each local that is reused (`y` above), we remove its storage statements do avoid any
-    // difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage
-    // statements.
-    StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body);
+        let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec();
+        for bb in reverse_postorder {
+            let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb];
+            state.visit_basic_block_data(bb, data);
+        }
+
+        // For each local that is reused (`y` above), we remove its storage statements do avoid any
+        // difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage
+        // statements.
+        StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body);
+    }
 }
 
 newtype_index! {
@@ -261,7 +258,7 @@ struct VnState<'body, 'tcx> {
     /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop.
     feature_unsized_locals: bool,
     ssa: &'body SsaLocals,
-    dominators: &'body Dominators<BasicBlock>,
+    dominators: Dominators<BasicBlock>,
     reused_locals: BitSet<Local>,
 }
 
@@ -271,7 +268,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         body: &Body<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         ssa: &'body SsaLocals,
-        dominators: &'body Dominators<BasicBlock>,
+        dominators: Dominators<BasicBlock>,
         local_decls: &'body LocalDecls<'tcx>,
     ) -> Self {
         // Compute a rough estimate of the number of values in the body from the number of
@@ -480,7 +477,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 let pointer = self.evaluated[local].as_ref()?;
                 let mut mplace = self.ecx.deref_pointer(pointer).ok()?;
                 for proj in place.projection.iter().skip(1) {
-                    // We have no call stack to associate a local with a value, so we cannot interpret indexing.
+                    // We have no call stack to associate a local with a value, so we cannot
+                    // interpret indexing.
                     if matches!(proj, ProjectionElem::Index(_)) {
                         return None;
                     }
@@ -1382,7 +1380,8 @@ fn op_to_prop_const<'tcx>(
         return Some(ConstValue::ZeroSized);
     }
 
-    // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to avoid.
+    // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to
+    // avoid.
     if !matches!(op.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
         return None;
     }
@@ -1491,7 +1490,7 @@ impl<'tcx> VnState<'_, 'tcx> {
         let other = self.rev_locals.get(index)?;
         other
             .iter()
-            .find(|&&other| self.ssa.assignment_dominates(self.dominators, other, loc))
+            .find(|&&other| self.ssa.assignment_dominates(&self.dominators, other, loc))
             .copied()
     }
 }
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 03ef808efec..870cb180ce1 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -568,7 +568,8 @@ impl<'tcx> Inliner<'tcx> {
                 // if the no-attribute function ends up with the same instruction set anyway.
                 return Err("Cannot move inline-asm across instruction sets");
             } else if let TerminatorKind::TailCall { .. } = term.kind {
-                // FIXME(explicit_tail_calls): figure out how exactly functions containing tail calls can be inlined (and if they even should)
+                // FIXME(explicit_tail_calls): figure out how exactly functions containing tail
+                // calls can be inlined (and if they even should)
                 return Err("can't inline functions with tail calls");
             } else {
                 work_list.extend(term.successors())
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index a9591bf3984..0b344f29b07 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -18,19 +18,13 @@ pub(super) enum InstSimplify {
     AfterSimplifyCfg,
 }
 
-impl InstSimplify {
+impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
     fn name(&self) -> &'static str {
         match self {
             InstSimplify::BeforeInline => "InstSimplify-before-inline",
             InstSimplify::AfterSimplifyCfg => "InstSimplify-after-simplifycfg",
         }
     }
-}
-
-impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
-    fn name(&self) -> &'static str {
-        self.name()
-    }
 
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
         sess.mir_opt_level() > 0
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index e950c2cb72a..d48df59ada8 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -78,18 +78,16 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
         }
 
         let param_env = tcx.param_env_reveal_all_normalized(def_id);
-        let map = Map::new(tcx, body, Some(MAX_PLACES));
-        let loop_headers = loop_headers(body);
 
-        let arena = DroplessArena::default();
+        let arena = &DroplessArena::default();
         let mut finder = TOFinder {
             tcx,
             param_env,
             ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
             body,
-            arena: &arena,
-            map: &map,
-            loop_headers: &loop_headers,
+            arena,
+            map: Map::new(tcx, body, Some(MAX_PLACES)),
+            loop_headers: loop_headers(body),
             opportunities: Vec::new(),
         };
 
@@ -105,7 +103,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
 
         // Verify that we do not thread through a loop header.
         for to in opportunities.iter() {
-            assert!(to.chain.iter().all(|&block| !loop_headers.contains(block)));
+            assert!(to.chain.iter().all(|&block| !finder.loop_headers.contains(block)));
         }
         OpportunitySet::new(body, opportunities).apply(body);
     }
@@ -124,8 +122,8 @@ struct TOFinder<'tcx, 'a> {
     param_env: ty::ParamEnv<'tcx>,
     ecx: InterpCx<'tcx, DummyMachine>,
     body: &'a Body<'tcx>,
-    map: &'a Map<'tcx>,
-    loop_headers: &'a BitSet<BasicBlock>,
+    map: Map<'tcx>,
+    loop_headers: BitSet<BasicBlock>,
     /// We use an arena to avoid cloning the slices when cloning `state`.
     arena: &'a DroplessArena,
     opportunities: Vec<ThreadingOpportunity>,
@@ -223,7 +221,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
             }))
         };
         let conds = ConditionSet(conds);
-        state.insert_value_idx(discr, conds, self.map);
+        state.insert_value_idx(discr, conds, &self.map);
 
         self.find_opportunity(bb, state, cost, 0);
     }
@@ -264,7 +262,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
             //   _1 = 5 // Whatever happens here, it won't change the result of a `SwitchInt`.
             //   _1 = 6
             if let Some((lhs, tail)) = self.mutated_statement(stmt) {
-                state.flood_with_tail_elem(lhs.as_ref(), tail, self.map, ConditionSet::BOTTOM);
+                state.flood_with_tail_elem(lhs.as_ref(), tail, &self.map, ConditionSet::BOTTOM);
             }
         }
 
@@ -370,7 +368,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
             self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target })
         };
 
-        if let Some(conditions) = state.try_get_idx(lhs, self.map)
+        if let Some(conditions) = state.try_get_idx(lhs, &self.map)
             && let Immediate::Scalar(Scalar::Int(int)) = *rhs
         {
             conditions.iter_matches(int).for_each(register_opportunity);
@@ -406,7 +404,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
                 }
             },
             &mut |place, op| {
-                if let Some(conditions) = state.try_get_idx(place, self.map)
+                if let Some(conditions) = state.try_get_idx(place, &self.map)
                     && let Ok(imm) = self.ecx.read_immediate_raw(op)
                     && let Some(imm) = imm.right()
                     && let Immediate::Scalar(Scalar::Int(int)) = *imm
@@ -441,7 +439,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
             // Transfer the conditions on the copied rhs.
             Operand::Move(rhs) | Operand::Copy(rhs) => {
                 let Some(rhs) = self.map.find(rhs.as_ref()) else { return };
-                state.insert_place_idx(rhs, lhs, self.map);
+                state.insert_place_idx(rhs, lhs, &self.map);
             }
         }
     }
@@ -461,7 +459,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
             Rvalue::CopyForDeref(rhs) => self.process_operand(bb, lhs, &Operand::Copy(*rhs), state),
             Rvalue::Discriminant(rhs) => {
                 let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return };
-                state.insert_place_idx(rhs, lhs, self.map);
+                state.insert_place_idx(rhs, lhs, &self.map);
             }
             // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
             Rvalue::Aggregate(box ref kind, ref operands) => {
@@ -492,10 +490,10 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
             }
             // Transfer the conditions on the copy rhs, after inversing polarity.
             Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => {
-                let Some(conditions) = state.try_get_idx(lhs, self.map) else { return };
+                let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return };
                 let Some(place) = self.map.find(place.as_ref()) else { return };
                 let conds = conditions.map(self.arena, Condition::inv);
-                state.insert_value_idx(place, conds, self.map);
+                state.insert_value_idx(place, conds, &self.map);
             }
             // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`.
             // Create a condition on `rhs ?= B`.
@@ -504,7 +502,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
                 box (Operand::Move(place) | Operand::Copy(place), Operand::Constant(value))
                 | box (Operand::Constant(value), Operand::Move(place) | Operand::Copy(place)),
             ) => {
-                let Some(conditions) = state.try_get_idx(lhs, self.map) else { return };
+                let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return };
                 let Some(place) = self.map.find(place.as_ref()) else { return };
                 let equals = match op {
                     BinOp::Eq => ScalarInt::TRUE,
@@ -528,7 +526,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
                     polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne },
                     ..c
                 });
-                state.insert_value_idx(place, conds, self.map);
+                state.insert_value_idx(place, conds, &self.map);
             }
 
             _ => {}
@@ -583,7 +581,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
             StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(
                 Operand::Copy(place) | Operand::Move(place),
             )) => {
-                let Some(conditions) = state.try_get(place.as_ref(), self.map) else { return };
+                let Some(conditions) = state.try_get(place.as_ref(), &self.map) else { return };
                 conditions.iter_matches(ScalarInt::TRUE).for_each(register_opportunity);
             }
             StatementKind::Assign(box (lhs_place, rhs)) => {
@@ -631,7 +629,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
         // We can recurse through this terminator.
         let mut state = state();
         if let Some(place_to_flood) = place_to_flood {
-            state.flood_with(place_to_flood.as_ref(), self.map, ConditionSet::BOTTOM);
+            state.flood_with(place_to_flood.as_ref(), &self.map, ConditionSet::BOTTOM);
         }
         self.find_opportunity(bb, state, cost.clone(), depth + 1);
     }
@@ -650,7 +648,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
         let Some(discr) = discr.place() else { return };
         let discr_ty = discr.ty(self.body, self.tcx).ty;
         let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else { return };
-        let Some(conditions) = state.try_get(discr.as_ref(), self.map) else { return };
+        let Some(conditions) = state.try_get(discr.as_ref(), &self.map) else { return };
 
         if let Some((value, _)) = targets.iter().find(|&(_, target)| target == target_bb) {
             let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { return };
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index e964310c542..f123f39bf42 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -1,8 +1,6 @@
-//! A lint that checks for known panics like
-//! overflows, division by zero,
-//! out-of-bound access etc.
-//! Uses const propagation to determine the
-//! values of operands during checks.
+//! A lint that checks for known panics like overflows, division by zero,
+//! out-of-bound access etc. Uses const propagation to determine the values of
+//! operands during checks.
 
 use std::fmt::Debug;
 
@@ -380,19 +378,19 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         if let (Some(l), Some(r)) = (l, r)
             && l.layout.ty.is_integral()
             && op.is_overflowing()
-        {
-            if self.use_ecx(|this| {
+            && self.use_ecx(|this| {
                 let (_res, overflow) = this.ecx.binary_op(op, &l, &r)?.to_scalar_pair();
                 overflow.to_bool()
-            })? {
-                self.report_assert_as_lint(
-                    location,
-                    AssertLintKind::ArithmeticOverflow,
-                    AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()),
-                );
-                return None;
-            }
+            })?
+        {
+            self.report_assert_as_lint(
+                location,
+                AssertLintKind::ArithmeticOverflow,
+                AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()),
+            );
+            return None;
         }
+
         Some(())
     }
 
@@ -562,7 +560,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
                 let val = self.use_ecx(|this| this.ecx.binary_op(bin_op, &left, &right))?;
                 if matches!(val.layout.abi, Abi::ScalarPair(..)) {
-                    // FIXME `Value` should properly support pairs in `Immediate`... but currently it does not.
+                    // FIXME `Value` should properly support pairs in `Immediate`... but currently
+                    // it does not.
                     let (val, overflow) = val.to_pair(&self.ecx);
                     Value::Aggregate {
                         variant: VariantIdx::ZERO,
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index f61cf236f77..3e263aa4067 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -16,8 +16,7 @@ use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants};
 ///   Large([u32; 1024]),
 /// }
 /// ```
-/// Instead of emitting moves of the large variant,
-/// Perform a memcpy instead.
+/// Instead of emitting moves of the large variant, perform a memcpy instead.
 /// Based off of [this HackMD](https://hackmd.io/@ft4bxUsFT5CEUBmRKYHr7w/rJM8BBPzD).
 ///
 /// In summary, what this does is at runtime determine which enum variant is active,
@@ -34,10 +33,173 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
         // https://github.com/rust-lang/rust/pull/85158#issuecomment-1101836457
         sess.opts.unstable_opts.unsound_mir_opts || sess.mir_opt_level() >= 3
     }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // NOTE: This pass may produce different MIR based on the alignment of the target
         // platform, but it will still be valid.
-        self.optim(tcx, body);
+
+        let mut alloc_cache = FxHashMap::default();
+        let body_did = body.source.def_id();
+        let param_env = tcx.param_env_reveal_all_normalized(body_did);
+
+        let blocks = body.basic_blocks.as_mut();
+        let local_decls = &mut body.local_decls;
+
+        for bb in blocks {
+            bb.expand_statements(|st| {
+                let StatementKind::Assign(box (
+                    lhs,
+                    Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
+                )) = &st.kind
+                else {
+                    return None;
+                };
+
+                let ty = lhs.ty(local_decls, tcx).ty;
+
+                let (adt_def, num_variants, alloc_id) =
+                    self.candidate(tcx, param_env, ty, &mut alloc_cache)?;
+
+                let source_info = st.source_info;
+                let span = source_info.span;
+
+                let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64);
+                let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span));
+                let store_live =
+                    Statement { source_info, kind: StatementKind::StorageLive(size_array_local) };
+
+                let place = Place::from(size_array_local);
+                let constant_vals = ConstOperand {
+                    span,
+                    user_ty: None,
+                    const_: Const::Val(
+                        ConstValue::Indirect { alloc_id, offset: Size::ZERO },
+                        tmp_ty,
+                    ),
+                };
+                let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals)));
+                let const_assign =
+                    Statement { source_info, kind: StatementKind::Assign(Box::new((place, rval))) };
+
+                let discr_place = Place::from(
+                    local_decls.push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)),
+                );
+                let store_discr = Statement {
+                    source_info,
+                    kind: StatementKind::Assign(Box::new((
+                        discr_place,
+                        Rvalue::Discriminant(*rhs),
+                    ))),
+                };
+
+                let discr_cast_place =
+                    Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span)));
+                let cast_discr = Statement {
+                    source_info,
+                    kind: StatementKind::Assign(Box::new((
+                        discr_cast_place,
+                        Rvalue::Cast(
+                            CastKind::IntToInt,
+                            Operand::Copy(discr_place),
+                            tcx.types.usize,
+                        ),
+                    ))),
+                };
+
+                let size_place =
+                    Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span)));
+                let store_size = Statement {
+                    source_info,
+                    kind: StatementKind::Assign(Box::new((
+                        size_place,
+                        Rvalue::Use(Operand::Copy(Place {
+                            local: size_array_local,
+                            projection: tcx
+                                .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]),
+                        })),
+                    ))),
+                };
+
+                let dst =
+                    Place::from(local_decls.push(LocalDecl::new(Ty::new_mut_ptr(tcx, ty), span)));
+                let dst_ptr = Statement {
+                    source_info,
+                    kind: StatementKind::Assign(Box::new((
+                        dst,
+                        Rvalue::RawPtr(Mutability::Mut, *lhs),
+                    ))),
+                };
+
+                let dst_cast_ty = Ty::new_mut_ptr(tcx, tcx.types.u8);
+                let dst_cast_place =
+                    Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span)));
+                let dst_cast = Statement {
+                    source_info,
+                    kind: StatementKind::Assign(Box::new((
+                        dst_cast_place,
+                        Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty),
+                    ))),
+                };
+
+                let src =
+                    Place::from(local_decls.push(LocalDecl::new(Ty::new_imm_ptr(tcx, ty), span)));
+                let src_ptr = Statement {
+                    source_info,
+                    kind: StatementKind::Assign(Box::new((
+                        src,
+                        Rvalue::RawPtr(Mutability::Not, *rhs),
+                    ))),
+                };
+
+                let src_cast_ty = Ty::new_imm_ptr(tcx, tcx.types.u8);
+                let src_cast_place =
+                    Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span)));
+                let src_cast = Statement {
+                    source_info,
+                    kind: StatementKind::Assign(Box::new((
+                        src_cast_place,
+                        Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty),
+                    ))),
+                };
+
+                let deinit_old =
+                    Statement { source_info, kind: StatementKind::Deinit(Box::new(dst)) };
+
+                let copy_bytes = Statement {
+                    source_info,
+                    kind: StatementKind::Intrinsic(Box::new(
+                        NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
+                            src: Operand::Copy(src_cast_place),
+                            dst: Operand::Copy(dst_cast_place),
+                            count: Operand::Copy(size_place),
+                        }),
+                    )),
+                };
+
+                let store_dead =
+                    Statement { source_info, kind: StatementKind::StorageDead(size_array_local) };
+
+                let iter = [
+                    store_live,
+                    const_assign,
+                    store_discr,
+                    cast_discr,
+                    store_size,
+                    dst_ptr,
+                    dst_cast,
+                    src_ptr,
+                    src_cast,
+                    deinit_old,
+                    copy_bytes,
+                    store_dead,
+                ]
+                .into_iter();
+
+                st.make_nop();
+
+                Some(iter)
+            });
+        }
     }
 }
 
@@ -82,6 +244,8 @@ impl EnumSizeOpt {
         let ptr_sized_int = data_layout.ptr_sized_integer();
         let target_bytes = ptr_sized_int.size().bytes() as usize;
         let mut data = vec![0; target_bytes * num_discrs];
+
+        // We use a macro because `$bytes` can be u32 or u64.
         macro_rules! encode_store {
             ($curr_idx: expr, $endian: expr, $bytes: expr) => {
                 let bytes = match $endian {
@@ -116,184 +280,4 @@ impl EnumSizeOpt {
         let alloc = tcx.reserve_and_set_memory_alloc(tcx.mk_const_alloc(alloc));
         Some((*adt_def, num_discrs, *alloc_cache.entry(ty).or_insert(alloc)))
     }
-    fn optim<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        let mut alloc_cache = FxHashMap::default();
-        let body_did = body.source.def_id();
-        let param_env = tcx.param_env_reveal_all_normalized(body_did);
-
-        let blocks = body.basic_blocks.as_mut();
-        let local_decls = &mut body.local_decls;
-
-        for bb in blocks {
-            bb.expand_statements(|st| {
-                if let StatementKind::Assign(box (
-                    lhs,
-                    Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
-                )) = &st.kind
-                {
-                    let ty = lhs.ty(local_decls, tcx).ty;
-
-                    let source_info = st.source_info;
-                    let span = source_info.span;
-
-                    let (adt_def, num_variants, alloc_id) =
-                        self.candidate(tcx, param_env, ty, &mut alloc_cache)?;
-
-                    let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64);
-
-                    let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span));
-                    let store_live = Statement {
-                        source_info,
-                        kind: StatementKind::StorageLive(size_array_local),
-                    };
-
-                    let place = Place::from(size_array_local);
-                    let constant_vals = ConstOperand {
-                        span,
-                        user_ty: None,
-                        const_: Const::Val(
-                            ConstValue::Indirect { alloc_id, offset: Size::ZERO },
-                            tmp_ty,
-                        ),
-                    };
-                    let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals)));
-
-                    let const_assign = Statement {
-                        source_info,
-                        kind: StatementKind::Assign(Box::new((place, rval))),
-                    };
-
-                    let discr_place = Place::from(
-                        local_decls
-                            .push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)),
-                    );
-
-                    let store_discr = Statement {
-                        source_info,
-                        kind: StatementKind::Assign(Box::new((
-                            discr_place,
-                            Rvalue::Discriminant(*rhs),
-                        ))),
-                    };
-
-                    let discr_cast_place =
-                        Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span)));
-
-                    let cast_discr = Statement {
-                        source_info,
-                        kind: StatementKind::Assign(Box::new((
-                            discr_cast_place,
-                            Rvalue::Cast(
-                                CastKind::IntToInt,
-                                Operand::Copy(discr_place),
-                                tcx.types.usize,
-                            ),
-                        ))),
-                    };
-
-                    let size_place =
-                        Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span)));
-
-                    let store_size = Statement {
-                        source_info,
-                        kind: StatementKind::Assign(Box::new((
-                            size_place,
-                            Rvalue::Use(Operand::Copy(Place {
-                                local: size_array_local,
-                                projection: tcx
-                                    .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]),
-                            })),
-                        ))),
-                    };
-
-                    let dst = Place::from(
-                        local_decls.push(LocalDecl::new(Ty::new_mut_ptr(tcx, ty), span)),
-                    );
-
-                    let dst_ptr = Statement {
-                        source_info,
-                        kind: StatementKind::Assign(Box::new((
-                            dst,
-                            Rvalue::RawPtr(Mutability::Mut, *lhs),
-                        ))),
-                    };
-
-                    let dst_cast_ty = Ty::new_mut_ptr(tcx, tcx.types.u8);
-                    let dst_cast_place =
-                        Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span)));
-
-                    let dst_cast = Statement {
-                        source_info,
-                        kind: StatementKind::Assign(Box::new((
-                            dst_cast_place,
-                            Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty),
-                        ))),
-                    };
-
-                    let src = Place::from(
-                        local_decls.push(LocalDecl::new(Ty::new_imm_ptr(tcx, ty), span)),
-                    );
-
-                    let src_ptr = Statement {
-                        source_info,
-                        kind: StatementKind::Assign(Box::new((
-                            src,
-                            Rvalue::RawPtr(Mutability::Not, *rhs),
-                        ))),
-                    };
-
-                    let src_cast_ty = Ty::new_imm_ptr(tcx, tcx.types.u8);
-                    let src_cast_place =
-                        Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span)));
-
-                    let src_cast = Statement {
-                        source_info,
-                        kind: StatementKind::Assign(Box::new((
-                            src_cast_place,
-                            Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty),
-                        ))),
-                    };
-
-                    let deinit_old =
-                        Statement { source_info, kind: StatementKind::Deinit(Box::new(dst)) };
-
-                    let copy_bytes = Statement {
-                        source_info,
-                        kind: StatementKind::Intrinsic(Box::new(
-                            NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
-                                src: Operand::Copy(src_cast_place),
-                                dst: Operand::Copy(dst_cast_place),
-                                count: Operand::Copy(size_place),
-                            }),
-                        )),
-                    };
-
-                    let store_dead = Statement {
-                        source_info,
-                        kind: StatementKind::StorageDead(size_array_local),
-                    };
-                    let iter = [
-                        store_live,
-                        const_assign,
-                        store_discr,
-                        cast_discr,
-                        store_size,
-                        dst_ptr,
-                        dst_cast,
-                        src_ptr,
-                        src_cast,
-                        deinit_old,
-                        copy_bytes,
-                        store_dead,
-                    ]
-                    .into_iter();
-
-                    st.make_nop();
-                    Some(iter)
-                } else {
-                    None
-                }
-            });
-        }
-    }
 }
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 0bbbf047f63..84d07d38330 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -87,6 +87,7 @@ mod match_branches;
 mod mentioned_items;
 mod multiple_return_terminators;
 mod nrvo;
+mod post_drop_elaboration;
 mod prettify;
 mod promote_consts;
 mod ref_prop;
@@ -168,8 +169,9 @@ fn remap_mir_for_const_eval_select<'tcx>(
                 let (method, place): (fn(Place<'tcx>) -> Operand<'tcx>, Place<'tcx>) =
                     match tupled_args.node {
                         Operand::Constant(_) => {
-                            // there is no good way of extracting a tuple arg from a constant (const generic stuff)
-                            // so we just create a temporary and deconstruct that.
+                            // There is no good way of extracting a tuple arg from a constant
+                            // (const generic stuff) so we just create a temporary and deconstruct
+                            // that.
                             let local = body.local_decls.push(LocalDecl::new(ty, fn_span));
                             bb.statements.push(Statement {
                                 source_info: SourceInfo::outermost(fn_span),
@@ -222,14 +224,14 @@ fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
 /// MIR associated with them.
 fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
     // All body-owners have MIR associated with them.
-    let mut set: FxIndexSet<_> = tcx.hir().body_owners().collect();
+    let set: FxIndexSet<_> = tcx.hir().body_owners().collect();
 
     // Additionally, tuple struct/variant constructors have MIR, but
     // they don't have a BodyId, so we need to build them separately.
-    struct GatherCtors<'a> {
-        set: &'a mut FxIndexSet<LocalDefId>,
+    struct GatherCtors {
+        set: FxIndexSet<LocalDefId>,
     }
-    impl<'tcx> Visitor<'tcx> for GatherCtors<'_> {
+    impl<'tcx> Visitor<'tcx> for GatherCtors {
         fn visit_variant_data(&mut self, v: &'tcx hir::VariantData<'tcx>) {
             if let hir::VariantData::Tuple(_, _, def_id) = *v {
                 self.set.insert(def_id);
@@ -237,9 +239,11 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
             intravisit::walk_struct_def(self, v)
         }
     }
-    tcx.hir().visit_all_item_likes_in_crate(&mut GatherCtors { set: &mut set });
 
-    set
+    let mut gather_ctors = GatherCtors { set };
+    tcx.hir().visit_all_item_likes_in_crate(&mut gather_ctors);
+
+    gather_ctors.set
 }
 
 fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
@@ -477,10 +481,13 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
         pm::run_passes(
             tcx,
             body,
-            &[&remove_uninit_drops::RemoveUninitDrops, &simplify::SimplifyCfg::RemoveFalseEdges],
+            &[
+                &remove_uninit_drops::RemoveUninitDrops,
+                &simplify::SimplifyCfg::RemoveFalseEdges,
+                &Lint(post_drop_elaboration::CheckLiveDrops),
+            ],
             None,
         );
-        check_consts::post_drop_elaboration::check_live_drops(tcx, body); // FIXME: make this a MIR lint
     }
 
     debug!("runtime_mir_lowering({:?})", did);
@@ -509,10 +516,12 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 /// Returns the sequence of passes that lowers analysis to runtime MIR.
 fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let passes: &[&dyn MirPass<'tcx>] = &[
-        // These next passes must be executed together
+        // These next passes must be executed together.
         &add_call_guards::CriticalCallEdges,
-        &reveal_all::RevealAll, // has to be done before drop elaboration, since we need to drop opaque types, too.
-        &add_subtyping_projections::Subtyper, // calling this after reveal_all ensures that we don't deal with opaque types
+        // Must be done before drop elaboration because we need to drop opaque types, too.
+        &reveal_all::RevealAll,
+        // Calling this after reveal_all ensures that we don't deal with opaque types.
+        &add_subtyping_projections::Subtyper,
         &elaborate_drops::ElaborateDrops,
         // This will remove extraneous landing pads which are no longer
         // necessary as well as forcing any call in a non-unwinding
@@ -521,8 +530,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // AddMovesForPackedDrops needs to run after drop
         // elaboration.
         &add_moves_for_packed_drops::AddMovesForPackedDrops,
-        // `AddRetag` needs to run after `ElaborateDrops` but before `ElaborateBoxDerefs`. Otherwise it should run fairly late,
-        // but before optimizations begin.
+        // `AddRetag` needs to run after `ElaborateDrops` but before `ElaborateBoxDerefs`.
+        // Otherwise it should run fairly late, but before optimizations begin.
         &add_retag::AddRetag,
         &elaborate_box_derefs::ElaborateBoxDerefs,
         &coroutine::StateTransform,
@@ -563,13 +572,15 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             // Before inlining: trim down MIR with passes to reduce inlining work.
 
             // Has to be done before inlining, otherwise actual call will be almost always inlined.
-            // Also simple, so can just do first
+            // Also simple, so can just do first.
             &lower_slice_len::LowerSliceLenCalls,
-            // Perform instsimplify before inline to eliminate some trivial calls (like clone shims).
+            // Perform instsimplify before inline to eliminate some trivial calls (like clone
+            // shims).
             &instsimplify::InstSimplify::BeforeInline,
             // Perform inlining, which may add a lot of code.
             &inline::Inline,
-            // Code from other crates may have storage markers, so this needs to happen after inlining.
+            // Code from other crates may have storage markers, so this needs to happen after
+            // inlining.
             &remove_storage_markers::RemoveStorageMarkers,
             // Inlining and instantiation may introduce ZST and useless drops.
             &remove_zsts::RemoveZsts,
@@ -586,7 +597,8 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &match_branches::MatchBranchSimplification,
             // inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
             &multiple_return_terminators::MultipleReturnTerminators,
-            // After simplifycfg, it allows us to discover new opportunities for peephole optimizations.
+            // After simplifycfg, it allows us to discover new opportunities for peephole
+            // optimizations.
             &instsimplify::InstSimplify::AfterSimplifyCfg,
             &simplify::SimplifyLocals::BeforeConstProp,
             &dead_store_elimination::DeadStoreElimination::Initial,
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index ca59d4d12ac..420661f29c8 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -13,22 +13,18 @@ impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls {
     }
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        lower_slice_len_calls(tcx, body)
-    }
-}
-
-fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let language_items = tcx.lang_items();
-    let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else {
-        // there is no lang item to compare to :)
-        return;
-    };
+        let language_items = tcx.lang_items();
+        let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else {
+            // there is no lang item to compare to :)
+            return;
+        };
 
-    // The one successor remains unchanged, so no need to invalidate
-    let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
-    for block in basic_blocks {
-        // lower `<[_]>::len` calls
-        lower_slice_len_call(block, slice_len_fn_item_def_id);
+        // The one successor remains unchanged, so no need to invalidate
+        let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
+        for block in basic_blocks {
+            // lower `<[_]>::len` calls
+            lower_slice_len_call(block, slice_len_fn_item_def_id);
+        }
     }
 }
 
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 2a2616b20a6..0f981425cfd 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -57,8 +57,9 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
 }
 
 trait SimplifyMatch<'tcx> {
-    /// Simplifies a match statement, returning true if the simplification succeeds, false otherwise.
-    /// Generic code is written here, and we generally don't need a custom implementation.
+    /// Simplifies a match statement, returning true if the simplification succeeds, false
+    /// otherwise. Generic code is written here, and we generally don't need a custom
+    /// implementation.
     fn simplify(
         &mut self,
         tcx: TyCtxt<'tcx>,
@@ -240,7 +241,8 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
                         // Same value in both blocks. Use statement as is.
                         patch.add_statement(parent_end, f.kind.clone());
                     } else {
-                        // Different value between blocks. Make value conditional on switch condition.
+                        // Different value between blocks. Make value conditional on switch
+                        // condition.
                         let size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size;
                         let const_cmp = Operand::const_from_scalar(
                             tcx,
@@ -394,14 +396,16 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
             return None;
         }
 
-        // We first compare the two branches, and then the other branches need to fulfill the same conditions.
+        // We first compare the two branches, and then the other branches need to fulfill the same
+        // conditions.
         let mut expected_transform_kinds = Vec::new();
         for (f, s) in iter::zip(first_stmts, second_stmts) {
             let compare_type = match (&f.kind, &s.kind) {
                 // If two statements are exactly the same, we can optimize.
                 (f_s, s_s) if f_s == s_s => ExpectedTransformKind::Same(f_s),
 
-                // If two statements are assignments with the match values to the same place, we can optimize.
+                // If two statements are assignments with the match values to the same place, we
+                // can optimize.
                 (
                     StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))),
                     StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs
index 7f9d0a5b698..f24de609e6b 100644
--- a/compiler/rustc_mir_transform/src/mentioned_items.rs
+++ b/compiler/rustc_mir_transform/src/mentioned_items.rs
@@ -10,7 +10,7 @@ pub(super) struct MentionedItems;
 struct MentionedItemsVisitor<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     body: &'a mir::Body<'tcx>,
-    mentioned_items: &'a mut Vec<Spanned<MentionedItem<'tcx>>>,
+    mentioned_items: Vec<Spanned<MentionedItem<'tcx>>>,
 }
 
 impl<'tcx> crate::MirPass<'tcx> for MentionedItems {
@@ -23,9 +23,9 @@ impl<'tcx> crate::MirPass<'tcx> for MentionedItems {
     }
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
-        let mut mentioned_items = Vec::new();
-        MentionedItemsVisitor { tcx, body, mentioned_items: &mut mentioned_items }.visit_body(body);
-        body.set_mentioned_items(mentioned_items);
+        let mut visitor = MentionedItemsVisitor { tcx, body, mentioned_items: Vec::new() };
+        visitor.visit_body(body);
+        body.set_mentioned_items(visitor.mentioned_items);
     }
 }
 
@@ -82,7 +82,9 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
                     source_ty.builtin_deref(true).map(|t| t.kind()),
                     target_ty.builtin_deref(true).map(|t| t.kind()),
                 ) {
-                    (Some(ty::Array(..)), Some(ty::Str | ty::Slice(..))) => false, // &str/&[T] unsizing
+                    // &str/&[T] unsizing
+                    (Some(ty::Array(..)), Some(ty::Str | ty::Slice(..))) => false,
+
                     _ => true,
                 };
                 if may_involve_vtable {
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index 60ece5e7db9..29f8b4f6e4d 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -42,7 +42,7 @@ fn to_profiler_name(type_name: &'static str) -> &'static str {
 
 // const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }`
 const fn c_name(name: &'static str) -> &'static str {
-    // FIXME Simplify the implementation once more `str` methods get const-stable.
+    // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable.
     // and inline into call site
     let bytes = name.as_bytes();
     let mut i = bytes.len();
@@ -61,7 +61,7 @@ const fn c_name(name: &'static str) -> &'static str {
 /// loop that goes over each available MIR and applies `run_pass`.
 pub(super) trait MirPass<'tcx> {
     fn name(&self) -> &'static str {
-        // FIXME Simplify the implementation once more `str` methods get const-stable.
+        // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable.
         // See copypaste in `MirLint`
         const {
             let name = std::any::type_name::<Self>();
@@ -89,7 +89,7 @@ pub(super) trait MirPass<'tcx> {
 /// disabled (via the `Lint` adapter).
 pub(super) trait MirLint<'tcx> {
     fn name(&self) -> &'static str {
-        // FIXME Simplify the implementation once more `str` methods get const-stable.
+        // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable.
         // See copypaste in `MirPass`
         const {
             let name = std::any::type_name::<Self>();
diff --git a/compiler/rustc_mir_transform/src/post_drop_elaboration.rs b/compiler/rustc_mir_transform/src/post_drop_elaboration.rs
new file mode 100644
index 00000000000..75721d46076
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/post_drop_elaboration.rs
@@ -0,0 +1,13 @@
+use rustc_const_eval::check_consts;
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+
+use crate::MirLint;
+
+pub(super) struct CheckLiveDrops;
+
+impl<'tcx> MirLint<'tcx> for CheckLiveDrops {
+    fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
+        check_consts::post_drop_elaboration::check_live_drops(tcx, body);
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs
index ef011d230c2..937c207776b 100644
--- a/compiler/rustc_mir_transform/src/prettify.rs
+++ b/compiler/rustc_mir_transform/src/prettify.rs
@@ -63,7 +63,7 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderLocals {
             finder.visit_basic_block_data(bb, bbd);
         }
 
-        // track everything in case there are some locals that we never saw,
+        // Track everything in case there are some locals that we never saw,
         // such as in non-block things like debug info or in non-uses.
         for local in body.local_decls.indices() {
             finder.track(local);
@@ -87,7 +87,7 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderLocals {
 
 fn permute<I: rustc_index::Idx + Ord, T>(data: &mut IndexVec<I, T>, map: &IndexSlice<I, I>) {
     // FIXME: It would be nice to have a less-awkward way to apply permutations,
-    // but I don't know one that exists.  `sort_by_cached_key` has logic for it
+    // but I don't know one that exists. `sort_by_cached_key` has logic for it
     // internally, but not in a way that we're allowed to use here.
     let mut enumerated: Vec<_> = std::mem::take(data).into_iter_enumerated().collect();
     enumerated.sort_by_key(|p| map[p.0]);
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index 65309f63d59..59df99f858d 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -1,16 +1,14 @@
 //! A pass that promotes borrows of constant rvalues.
 //!
-//! The rvalues considered constant are trees of temps,
-//! each with exactly one initialization, and holding
-//! a constant value with no interior mutability.
-//! They are placed into a new MIR constant body in
-//! `promoted` and the borrow rvalue is replaced with
-//! a `Literal::Promoted` using the index into `promoted`
-//! of that constant MIR.
+//! The rvalues considered constant are trees of temps, each with exactly one
+//! initialization, and holding a constant value with no interior mutability.
+//! They are placed into a new MIR constant body in `promoted` and the borrow
+//! rvalue is replaced with a `Literal::Promoted` using the index into
+//! `promoted` of that constant MIR.
 //!
-//! This pass assumes that every use is dominated by an
-//! initialization and can otherwise silence errors, if
-//! move analysis runs after promotion on broken MIR.
+//! This pass assumes that every use is dominated by an initialization and can
+//! otherwise silence errors, if move analysis runs after promotion on broken
+//! MIR.
 
 use std::assert_matches::assert_matches;
 use std::cell::Cell;
@@ -38,6 +36,7 @@ use tracing::{debug, instrument};
 /// newly created `Constant`.
 #[derive(Default)]
 pub(super) struct PromoteTemps<'tcx> {
+    // Must use `Cell` because `run_pass` takes `&self`, not `&mut self`.
     pub promoted_fragments: Cell<IndexVec<Promoted, Body<'tcx>>>,
 }
 
@@ -386,7 +385,8 @@ impl<'tcx> Validator<'_, 'tcx> {
     fn validate_ref(&mut self, kind: BorrowKind, place: &Place<'tcx>) -> Result<(), Unpromotable> {
         match kind {
             // Reject these borrow types just to be safe.
-            // FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase.
+            // FIXME(RalfJung): could we allow them? Should we? No point in it until we have a
+            // usecase.
             BorrowKind::Fake(_) | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
                 return Err(Unpromotable);
             }
@@ -468,7 +468,8 @@ impl<'tcx> Validator<'_, 'tcx> {
                 let lhs_ty = lhs.ty(self.body, self.tcx);
 
                 if let ty::RawPtr(_, _) | ty::FnPtr(..) = lhs_ty.kind() {
-                    // Raw and fn pointer operations are not allowed inside consts and thus not promotable.
+                    // Raw and fn pointer operations are not allowed inside consts and thus not
+                    // promotable.
                     assert_matches!(
                         op,
                         BinOp::Eq
@@ -498,7 +499,8 @@ impl<'tcx> Validator<'_, 'tcx> {
                                 Some(x) if x != 0 => {}        // okay
                                 _ => return Err(Unpromotable), // value not known or 0 -- not okay
                             }
-                            // Furthermore, for signed division, we also have to exclude `int::MIN / -1`.
+                            // Furthermore, for signed division, we also have to exclude `int::MIN /
+                            // -1`.
                             if lhs_ty.is_signed() {
                                 match rhs_val.map(|x| x.to_int(sz)) {
                                     Some(-1) | None => {
@@ -512,8 +514,11 @@ impl<'tcx> Validator<'_, 'tcx> {
                                         };
                                         let lhs_min = sz.signed_int_min();
                                         match lhs_val.map(|x| x.to_int(sz)) {
-                                            Some(x) if x != lhs_min => {}  // okay
-                                            _ => return Err(Unpromotable), // value not known or int::MIN -- not okay
+                                            // okay
+                                            Some(x) if x != lhs_min => {}
+
+                                            // value not known or int::MIN -- not okay
+                                            _ => return Err(Unpromotable),
                                         }
                                     }
                                     _ => {}
@@ -815,8 +820,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 TerminatorKind::Call {
                     mut func, mut args, call_source: desugar, fn_span, ..
                 } => {
-                    // This promoted involves a function call, so it may fail to evaluate.
-                    // Let's make sure it is added to `required_consts` so that failure cannot get lost.
+                    // This promoted involves a function call, so it may fail to evaluate. Let's
+                    // make sure it is added to `required_consts` so that failure cannot get lost.
                     self.add_to_required = true;
 
                     self.visit_operand(&mut func, loc);
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index 25b98786c66..4c3a99b79d4 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -253,11 +253,8 @@ fn compute_replacement<'tcx>(
 
     debug!(?targets);
 
-    let mut finder = ReplacementFinder {
-        targets: &mut targets,
-        can_perform_opt,
-        allowed_replacements: FxHashSet::default(),
-    };
+    let mut finder =
+        ReplacementFinder { targets, can_perform_opt, allowed_replacements: FxHashSet::default() };
     let reachable_blocks = traversal::reachable_as_bitset(body);
     for (bb, bbdata) in body.basic_blocks.iter_enumerated() {
         // Only visit reachable blocks as we rely on dataflow.
@@ -269,19 +266,19 @@ fn compute_replacement<'tcx>(
     let allowed_replacements = finder.allowed_replacements;
     return Replacer {
         tcx,
-        targets,
+        targets: finder.targets,
         storage_to_remove,
         allowed_replacements,
         any_replacement: false,
     };
 
-    struct ReplacementFinder<'a, 'tcx, F> {
-        targets: &'a mut IndexVec<Local, Value<'tcx>>,
+    struct ReplacementFinder<'tcx, F> {
+        targets: IndexVec<Local, Value<'tcx>>,
         can_perform_opt: F,
         allowed_replacements: FxHashSet<(Local, Location)>,
     }
 
-    impl<'tcx, F> Visitor<'tcx> for ReplacementFinder<'_, 'tcx, F>
+    impl<'tcx, F> Visitor<'tcx> for ReplacementFinder<'tcx, F>
     where
         F: FnMut(Place<'tcx>, Location) -> bool,
     {
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index 37197c3f573..55394e93a5c 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -18,7 +18,61 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
     fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let def_id = body.source.def_id();
         debug!(?def_id);
-        self.remove_nop_landing_pads(body)
+
+        // Skip the pass if there are no blocks with a resume terminator.
+        let has_resume = body
+            .basic_blocks
+            .iter_enumerated()
+            .any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::UnwindResume));
+        if !has_resume {
+            debug!("remove_noop_landing_pads: no resume block in MIR");
+            return;
+        }
+
+        // make sure there's a resume block without any statements
+        let resume_block = {
+            let mut patch = MirPatch::new(body);
+            let resume_block = patch.resume_block();
+            patch.apply(body);
+            resume_block
+        };
+        debug!("remove_noop_landing_pads: resume block is {:?}", resume_block);
+
+        let mut jumps_folded = 0;
+        let mut landing_pads_removed = 0;
+        let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks.len());
+
+        // This is a post-order traversal, so that if A post-dominates B
+        // then A will be visited before B.
+        let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect();
+        for bb in postorder {
+            debug!("  processing {:?}", bb);
+            if let Some(unwind) = body[bb].terminator_mut().unwind_mut() {
+                if let UnwindAction::Cleanup(unwind_bb) = *unwind {
+                    if nop_landing_pads.contains(unwind_bb) {
+                        debug!("    removing noop landing pad");
+                        landing_pads_removed += 1;
+                        *unwind = UnwindAction::Continue;
+                    }
+                }
+            }
+
+            for target in body[bb].terminator_mut().successors_mut() {
+                if *target != resume_block && nop_landing_pads.contains(*target) {
+                    debug!("    folding noop jump to {:?} to resume block", target);
+                    *target = resume_block;
+                    jumps_folded += 1;
+                }
+            }
+
+            let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads);
+            if is_nop_landing_pad {
+                nop_landing_pads.insert(bb);
+            }
+            debug!("    is_nop_landing_pad({:?}) = {}", bb, is_nop_landing_pad);
+        }
+
+        debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed);
     }
 }
 
@@ -82,61 +136,4 @@ impl RemoveNoopLandingPads {
             | TerminatorKind::InlineAsm { .. } => false,
         }
     }
-
-    fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
-        // Skip the pass if there are no blocks with a resume terminator.
-        let has_resume = body
-            .basic_blocks
-            .iter_enumerated()
-            .any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::UnwindResume));
-        if !has_resume {
-            debug!("remove_noop_landing_pads: no resume block in MIR");
-            return;
-        }
-
-        // make sure there's a resume block without any statements
-        let resume_block = {
-            let mut patch = MirPatch::new(body);
-            let resume_block = patch.resume_block();
-            patch.apply(body);
-            resume_block
-        };
-        debug!("remove_noop_landing_pads: resume block is {:?}", resume_block);
-
-        let mut jumps_folded = 0;
-        let mut landing_pads_removed = 0;
-        let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks.len());
-
-        // This is a post-order traversal, so that if A post-dominates B
-        // then A will be visited before B.
-        let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect();
-        for bb in postorder {
-            debug!("  processing {:?}", bb);
-            if let Some(unwind) = body[bb].terminator_mut().unwind_mut() {
-                if let UnwindAction::Cleanup(unwind_bb) = *unwind {
-                    if nop_landing_pads.contains(unwind_bb) {
-                        debug!("    removing noop landing pad");
-                        landing_pads_removed += 1;
-                        *unwind = UnwindAction::Continue;
-                    }
-                }
-            }
-
-            for target in body[bb].terminator_mut().successors_mut() {
-                if *target != resume_block && nop_landing_pads.contains(*target) {
-                    debug!("    folding noop jump to {:?} to resume block", target);
-                    *target = resume_block;
-                    jumps_folded += 1;
-                }
-            }
-
-            let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads);
-            if is_nop_landing_pad {
-                nop_landing_pads.insert(bb);
-            }
-            debug!("    is_nop_landing_pad({:?}) = {}", bb, is_nop_landing_pad);
-        }
-
-        debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed);
-    }
 }
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index c58f492655a..d80a4edecdf 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -106,8 +106,9 @@ fn is_needs_drop_and_init<'tcx>(
             // If its projection *is* present in `MoveData`, then the field may have been moved
             // from separate from its parent. Recurse.
             adt.variants().iter_enumerated().any(|(vid, variant)| {
-                // Enums have multiple variants, which are discriminated with a `Downcast` projection.
-                // Structs have a single variant, and don't use a `Downcast` projection.
+                // Enums have multiple variants, which are discriminated with a `Downcast`
+                // projection. Structs have a single variant, and don't use a `Downcast`
+                // projection.
                 let mpi = if adt.is_enum() {
                     let downcast =
                         move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid));
diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index ebcf5b5d27b..99d1cd6f63e 100644
--- a/compiler/rustc_mir_transform/src/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
@@ -1,26 +1,21 @@
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::{traversal, Body, ConstOperand, Location};
 
-pub(super) struct RequiredConstsVisitor<'a, 'tcx> {
-    required_consts: &'a mut Vec<ConstOperand<'tcx>>,
+pub(super) struct RequiredConstsVisitor<'tcx> {
+    required_consts: Vec<ConstOperand<'tcx>>,
 }
 
-impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
-    fn new(required_consts: &'a mut Vec<ConstOperand<'tcx>>) -> Self {
-        RequiredConstsVisitor { required_consts }
-    }
-
+impl<'tcx> RequiredConstsVisitor<'tcx> {
     pub(super) fn compute_required_consts(body: &mut Body<'tcx>) {
-        let mut required_consts = Vec::new();
-        let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts);
+        let mut visitor = RequiredConstsVisitor { required_consts: Vec::new() };
         for (bb, bb_data) in traversal::reverse_postorder(&body) {
-            required_consts_visitor.visit_basic_block_data(bb, bb_data);
+            visitor.visit_basic_block_data(bb, bb_data);
         }
-        body.set_required_consts(required_consts);
+        body.set_required_consts(visitor.required_consts);
     }
 }
 
-impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
+impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'tcx> {
     fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, _: Location) {
         if constant.const_.is_required_const() {
             self.required_consts.push(*constant);
diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs
index 3db962bd94a..f3b2f78b31c 100644
--- a/compiler/rustc_mir_transform/src/reveal_all.rs
+++ b/compiler/rustc_mir_transform/src/reveal_all.rs
@@ -35,9 +35,9 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
         if place.projection.iter().all(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) {
             return;
         }
-        // `OpaqueCast` projections are only needed if there are opaque types on which projections are performed.
-        // After the `RevealAll` pass, all opaque types are replaced with their hidden types, so we don't need these
-        // projections anymore.
+        // `OpaqueCast` projections are only needed if there are opaque types on which projections
+        // are performed. After the `RevealAll` pass, all opaque types are replaced with their
+        // hidden types, so we don't need these projections anymore.
         place.projection = self.tcx.mk_place_elems(
             &place
                 .projection
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index cf8ef580b27..f1bd803d835 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -404,8 +404,7 @@ fn build_thread_local_shim<'tcx>(
     let span = tcx.def_span(def_id);
     let source_info = SourceInfo::outermost(span);
 
-    let mut blocks = IndexVec::with_capacity(1);
-    blocks.push(BasicBlockData {
+    let blocks = IndexVec::from_raw(vec![BasicBlockData {
         statements: vec![Statement {
             source_info,
             kind: StatementKind::Assign(Box::new((
@@ -415,7 +414,7 @@ fn build_thread_local_shim<'tcx>(
         }],
         terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }),
         is_cleanup: false,
-    });
+    }]);
 
     new_body(
         MirSource::from_instance(instance),
@@ -1003,7 +1002,8 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t
     let locals = local_decls_for_sig(&sig, span);
 
     let source_info = SourceInfo::outermost(span);
-    // FIXME: use `expose_provenance` once we figure out whether function pointers have meaningful provenance.
+    // FIXME: use `expose_provenance` once we figure out whether function pointers have meaningful
+    // provenance.
     let rvalue = Rvalue::Cast(
         CastKind::FnPtrToPtr,
         Operand::Move(Place::from(Local::new(1))),
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index cb8e1dfda98..7ed43547e11 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -381,23 +381,33 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("running SimplifyLocals on {:?}", body.source);
-        simplify_locals(body, tcx);
-    }
-}
 
-pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
-    // First, we're going to get a count of *actual* uses for every `Local`.
-    let mut used_locals = UsedLocals::new(body);
+        // First, we're going to get a count of *actual* uses for every `Local`.
+        let mut used_locals = UsedLocals::new(body);
 
-    // Next, we're going to remove any `Local` with zero actual uses. When we remove those
-    // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals`
-    // count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from
-    // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a
-    // fixedpoint where there are no more unused locals.
-    remove_unused_definitions_helper(&mut used_locals, body);
+        // Next, we're going to remove any `Local` with zero actual uses. When we remove those
+        // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals`
+        // count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from
+        // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a
+        // fixedpoint where there are no more unused locals.
+        remove_unused_definitions_helper(&mut used_locals, body);
+
+        // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the
+        // `Local`s.
+        let map = make_local_map(&mut body.local_decls, &used_locals);
+
+        // Only bother running the `LocalUpdater` if we actually found locals to remove.
+        if map.iter().any(Option::is_none) {
+            // Update references to all vars and tmps now
+            let mut updater = LocalUpdater { map, tcx };
+            updater.visit_body_preserves_cfg(body);
+
+            body.local_decls.shrink_to_fit();
+        }
+    }
 }
 
-fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
+pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
     // First, we're going to get a count of *actual* uses for every `Local`.
     let mut used_locals = UsedLocals::new(body);
 
@@ -407,18 +417,6 @@ fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
     // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a
     // fixedpoint where there are no more unused locals.
     remove_unused_definitions_helper(&mut used_locals, body);
-
-    // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s.
-    let map = make_local_map(&mut body.local_decls, &used_locals);
-
-    // Only bother running the `LocalUpdater` if we actually found locals to remove.
-    if map.iter().any(Option::is_none) {
-        // Update references to all vars and tmps now
-        let mut updater = LocalUpdater { map, tcx };
-        updater.visit_body_preserves_cfg(body);
-
-        body.local_decls.shrink_to_fit();
-    }
 }
 
 /// Construct the mapping while swapping out unused stuff out from the `vec`.
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index 644bcb58d56..e8d8335b136 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -73,12 +73,13 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
                 _ => unreachable!(),
             }
 
-            // delete comparison statement if it the value being switched on was moved, which means it can not be user later on
+            // delete comparison statement if it the value being switched on was moved, which means
+            // it can not be user later on
             if opt.can_remove_bin_op_stmt {
                 bb.statements[opt.bin_op_stmt_idx].make_nop();
             } else {
-                // if the integer being compared to a const integral is being moved into the comparison,
-                // e.g `_2 = Eq(move _3, const 'x');`
+                // if the integer being compared to a const integral is being moved into the
+                // comparison, e.g `_2 = Eq(move _3, const 'x');`
                 // we want to avoid making a double move later on in the switchInt on _3.
                 // So to avoid `switchInt(move _3) -> ['x': bb2, otherwise: bb1];`,
                 // we convert the move in the comparison statement to a copy.
@@ -102,12 +103,15 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
 
             // remove StorageDead (if it exists) being used in the assign of the comparison
             for (stmt_idx, stmt) in bb.statements.iter().enumerate() {
-                if !matches!(stmt.kind, StatementKind::StorageDead(local) if local == opt.to_switch_on.local)
-                {
+                if !matches!(
+                    stmt.kind,
+                    StatementKind::StorageDead(local) if local == opt.to_switch_on.local
+                ) {
                     continue;
                 }
                 storage_deads_to_remove.push((stmt_idx, opt.bb_idx));
-                // if we have StorageDeads to remove then make sure to insert them at the top of each target
+                // if we have StorageDeads to remove then make sure to insert them at the top of
+                // each target
                 for bb_idx in new_targets.all_targets() {
                     storage_deads_to_insert.push((
                         *bb_idx,
@@ -207,7 +211,8 @@ fn find_branch_value_info<'tcx>(
         (Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on))
         | (Copy(to_switch_on) | Move(to_switch_on), Constant(branch_value)) => {
             let branch_value_ty = branch_value.const_.ty();
-            // we only want to apply this optimization if we are matching on integrals (and chars), as it is not possible to switch on floats
+            // we only want to apply this optimization if we are matching on integrals (and chars),
+            // as it is not possible to switch on floats
             if !branch_value_ty.is_integral() && !branch_value_ty.is_char() {
                 return None;
             };
@@ -222,7 +227,8 @@ fn find_branch_value_info<'tcx>(
 struct OptimizationInfo<'tcx> {
     /// Basic block to apply the optimization
     bb_idx: BasicBlock,
-    /// Statement index of Eq/Ne assignment that can be removed. None if the assignment can not be removed - i.e the statement is used later on
+    /// Statement index of Eq/Ne assignment that can be removed. None if the assignment can not be
+    /// removed - i.e the statement is used later on
     bin_op_stmt_idx: usize,
     /// Can remove Eq/Ne assignment
     can_remove_bin_op_stmt: bool,
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 6957394ed10..5612e779d6b 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -156,9 +156,9 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching {
                 };
                 true
             }
-            // If and only if there is a variant that does not have a branch set,
-            // change the current of otherwise as the variant branch and set otherwise to unreachable.
-            // It transforms following code
+            // If and only if there is a variant that does not have a branch set, change the
+            // current of otherwise as the variant branch and set otherwise to unreachable. It
+            // transforms following code
             // ```rust
             // match c {
             //     Ordering::Less => 1,
diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index c60cbae2142..f3dafd13824 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -26,7 +26,8 @@ impl crate::MirPass<'_> for UnreachablePropagation {
             let terminator = bb_data.terminator();
             let is_unreachable = match &terminator.kind {
                 TerminatorKind::Unreachable => true,
-                // This will unconditionally run into an unreachable and is therefore unreachable as well.
+                // This will unconditionally run into an unreachable and is therefore unreachable
+                // as well.
                 TerminatorKind::Goto { target } if unreachable_blocks.contains(target) => {
                     patch.patch_terminator(bb, TerminatorKind::Unreachable);
                     true
@@ -85,8 +86,9 @@ fn remove_successors_from_switch<'tcx>(
     //     }
     // }
     //
-    // This generates a `switchInt() -> [0: 0, 1: 1, otherwise: unreachable]`, which allows us or LLVM to
-    // turn it into just `x` later. Without the unreachable, such a transformation would be illegal.
+    // This generates a `switchInt() -> [0: 0, 1: 1, otherwise: unreachable]`, which allows us or
+    // LLVM to turn it into just `x` later. Without the unreachable, such a transformation would be
+    // illegal.
     //
     // In order to preserve this information, we record reachable and unreachable targets as
     // `Assume` statements in MIR.
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 18865c73f75..3b84755dded 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -388,10 +388,11 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                     }
                     self.check_unwind_edge(location, unwind);
 
-                    // The code generation assumes that there are no critical call edges. The assumption
-                    // is used to simplify inserting code that should be executed along the return edge
-                    // from the call. FIXME(tmiasko): Since this is a strictly code generation concern,
-                    // the code generation should be responsible for handling it.
+                    // The code generation assumes that there are no critical call edges. The
+                    // assumption is used to simplify inserting code that should be executed along
+                    // the return edge from the call. FIXME(tmiasko): Since this is a strictly code
+                    // generation concern, the code generation should be responsible for handling
+                    // it.
                     if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Optimized)
                         && self.is_critical_call_edge(target, unwind)
                     {
@@ -404,8 +405,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                         );
                     }
 
-                    // The call destination place and Operand::Move place used as an argument might be
-                    // passed by a reference to the callee. Consequently they cannot be packed.
+                    // The call destination place and Operand::Move place used as an argument might
+                    // be passed by a reference to the callee. Consequently they cannot be packed.
                     if is_within_packed(self.tcx, &self.body.local_decls, destination).is_some() {
                         // This is bad! The callee will expect the memory to be aligned.
                         self.fail(
@@ -953,9 +954,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 }
                 AggregateKind::RawPtr(pointee_ty, mutability) => {
                     if !matches!(self.mir_phase, MirPhase::Runtime(_)) {
-                        // It would probably be fine to support this in earlier phases,
-                        // but at the time of writing it's only ever introduced from intrinsic lowering,
-                        // so earlier things just `bug!` on it.
+                        // It would probably be fine to support this in earlier phases, but at the
+                        // time of writing it's only ever introduced from intrinsic lowering, so
+                        // earlier things just `bug!` on it.
                         self.fail(location, "RawPtr should be in runtime MIR only");
                     }
 
@@ -1109,10 +1110,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     }
                     UnOp::PtrMetadata => {
                         if !matches!(self.mir_phase, MirPhase::Runtime(_)) {
-                            // It would probably be fine to support this in earlier phases,
-                            // but at the time of writing it's only ever introduced from intrinsic lowering
-                            // or other runtime-phase optimization passes,
-                            // so earlier things can just `bug!` on it.
+                            // It would probably be fine to support this in earlier phases, but at
+                            // the time of writing it's only ever introduced from intrinsic
+                            // lowering or other runtime-phase optimization passes, so earlier
+                            // things can just `bug!` on it.
                             self.fail(location, "PtrMetadata should be in runtime MIR only");
                         }
 
@@ -1506,7 +1507,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 }
 
                 if let TerminatorKind::TailCall { .. } = terminator.kind {
-                    // FIXME(explicit_tail_calls): implement tail-call specific checks here (such as signature matching, forbidding closures, etc)
+                    // FIXME(explicit_tail_calls): implement tail-call specific checks here (such
+                    // as signature matching, forbidding closures, etc)
                 }
             }
             TerminatorKind::Assert { cond, .. } => {
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 093697a290c..c3f22896200 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1193,7 +1193,7 @@ fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) ->
             return Some(new.def_id);
         }
     }
-    return None;
+    None
 }
 
 /// Scans the MIR in order to find function calls, closures, and drop-glue.
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 0d295b8f280..2d9dbdbaec2 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -504,10 +504,8 @@ fn compute_inlined_overlap<'tcx>(cgu1: &CodegenUnit<'tcx>, cgu2: &CodegenUnit<'t
 
     let mut overlap = 0;
     for (item, data) in src_cgu.items().iter() {
-        if data.inlined {
-            if dst_cgu.items().contains_key(item) {
-                overlap += data.size_estimate;
-            }
+        if data.inlined && dst_cgu.items().contains_key(item) {
+            overlap += data.size_estimate;
         }
     }
     overlap
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 394518daa42..196ddeb2443 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -185,10 +185,8 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
                 for var in var_infos.iter_mut() {
                     // We simply put all regions from the input into the highest
                     // compressed universe, so we only deal with them at the end.
-                    if !var.is_region() {
-                        if is_existential == var.is_existential() {
-                            update_uv(var, orig_uv, is_existential)
-                        }
+                    if !var.is_region() && is_existential == var.is_existential() {
+                        update_uv(var, orig_uv, is_existential)
                     }
                 }
             }
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 683d8dab3b2..73d9b5e8a4e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -883,7 +883,6 @@ where
             .into_iter()
             .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
                 elaborate::supertrait_def_ids(self.cx(), principal_def_id)
-                    .into_iter()
                     .filter(|def_id| self.cx().trait_is_auto(*def_id))
             }))
             .collect();
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index e7a7105803f..c83d8bf4021 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -299,7 +299,7 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
             }
             return diff_errs;
         }
-        return errs;
+        errs
     }
 
     fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'psess> {
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 205cca830b2..6a241be0a15 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -383,7 +383,7 @@ impl<'a> Parser<'a> {
             self.capture_state
                 .parser_replacements
                 .drain(parser_replacements_start..parser_replacements_end)
-                .chain(inner_attr_parser_replacements.into_iter())
+                .chain(inner_attr_parser_replacements)
                 .map(|(parser_range, data)| {
                     (NodeRange::new(parser_range, collect_pos.start_pos), data)
                 })
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index f6f66821df7..bee73c58cb7 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -2553,7 +2553,7 @@ impl<'a> Parser<'a> {
                 err.delay_as_bug();
             }
         }
-        return Ok(false); // Don't continue.
+        Ok(false) // Don't continue.
     }
 
     /// Attempt to parse a generic const argument that has not been enclosed in braces.
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index ecc4cd96faf..2d6edad2977 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2554,13 +2554,12 @@ impl<'a> Parser<'a> {
             let maybe_fatarrow = self.token.clone();
             let block = if self.check(&token::OpenDelim(Delimiter::Brace)) {
                 self.parse_block()?
+            } else if let Some(block) = recover_block_from_condition(self) {
+                block
             } else {
-                if let Some(block) = recover_block_from_condition(self) {
-                    block
-                } else {
-                    self.error_on_extra_if(&cond)?;
-                    // Parse block, which will always fail, but we can add a nice note to the error
-                    self.parse_block().map_err(|mut err| {
+                self.error_on_extra_if(&cond)?;
+                // Parse block, which will always fail, but we can add a nice note to the error
+                self.parse_block().map_err(|mut err| {
                         if self.prev_token == token::Semi
                             && self.token == token::AndAnd
                             && let maybe_let = self.look_ahead(1, |t| t.clone())
@@ -2592,7 +2591,6 @@ impl<'a> Parser<'a> {
                         }
                         err
                     })?
-                }
             };
             self.error_on_if_block_attrs(lo, false, block.span, attrs);
             block
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index c6a5e1908f7..104678e081c 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -457,7 +457,7 @@ impl<'a> Parser<'a> {
 
     fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemInfo>> {
         // To be expanded
-        return Ok(None);
+        Ok(None)
     }
 
     /// Parses an item macro, e.g., `item!();`.
@@ -1588,7 +1588,7 @@ impl<'a> Parser<'a> {
                             (thin_vec![], Recovered::Yes(guar))
                         }
                     };
-                VariantData::Struct { fields, recovered: recovered.into() }
+                VariantData::Struct { fields, recovered }
             } else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) {
                 let body = match this.parse_tuple_struct_body() {
                     Ok(body) => body,
@@ -1672,7 +1672,7 @@ impl<'a> Parser<'a> {
                     class_name.span,
                     generics.where_clause.has_where_token,
                 )?;
-                VariantData::Struct { fields, recovered: recovered.into() }
+                VariantData::Struct { fields, recovered }
             }
         // No `where` so: `struct Foo<T>;`
         } else if self.eat(&token::Semi) {
@@ -1684,7 +1684,7 @@ impl<'a> Parser<'a> {
                 class_name.span,
                 generics.where_clause.has_where_token,
             )?;
-            VariantData::Struct { fields, recovered: recovered.into() }
+            VariantData::Struct { fields, recovered }
         // Tuple-style struct definition with optional where-clause.
         } else if self.token == token::OpenDelim(Delimiter::Parenthesis) {
             let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
@@ -1713,14 +1713,14 @@ impl<'a> Parser<'a> {
                 class_name.span,
                 generics.where_clause.has_where_token,
             )?;
-            VariantData::Struct { fields, recovered: recovered.into() }
+            VariantData::Struct { fields, recovered }
         } else if self.token == token::OpenDelim(Delimiter::Brace) {
             let (fields, recovered) = self.parse_record_struct_body(
                 "union",
                 class_name.span,
                 generics.where_clause.has_where_token,
             )?;
-            VariantData::Struct { fields, recovered: recovered.into() }
+            VariantData::Struct { fields, recovered }
         } else {
             let token_str = super::token_descr(&self.token);
             let msg = format!("expected `where` or `{{` after union name, found {token_str}");
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 3ee6e742d1b..9d9265d5318 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1359,13 +1359,11 @@ impl<'a> Parser<'a> {
     fn parse_attr_args(&mut self) -> PResult<'a, AttrArgs> {
         Ok(if let Some(args) = self.parse_delim_args_inner() {
             AttrArgs::Delimited(args)
+        } else if self.eat(&token::Eq) {
+            let eq_span = self.prev_token.span;
+            AttrArgs::Eq(eq_span, AttrArgsEq::Ast(self.parse_expr_force_collect()?))
         } else {
-            if self.eat(&token::Eq) {
-                let eq_span = self.prev_token.span;
-                AttrArgs::Eq(eq_span, AttrArgsEq::Ast(self.parse_expr_force_collect()?))
-            } else {
-                AttrArgs::Empty
-            }
+            AttrArgs::Empty
         })
     }
 
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index cbd35ffdfa9..daced411b8f 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1336,21 +1336,19 @@ impl<'a> Parser<'a> {
                         vec![(first_etc_span, String::new())],
                         Applicability::MachineApplicable,
                     );
-                } else {
-                    if let Some(last_non_comma_dotdot_span) = last_non_comma_dotdot_span {
-                        // We have `.., x`.
-                        err.multipart_suggestion(
-                            "move the `..` to the end of the field list",
-                            vec![
-                                (first_etc_span, String::new()),
-                                (
-                                    self.token.span.to(last_non_comma_dotdot_span.shrink_to_hi()),
-                                    format!("{} .. }}", if ate_comma { "" } else { "," }),
-                                ),
-                            ],
-                            Applicability::MachineApplicable,
-                        );
-                    }
+                } else if let Some(last_non_comma_dotdot_span) = last_non_comma_dotdot_span {
+                    // We have `.., x`.
+                    err.multipart_suggestion(
+                        "move the `..` to the end of the field list",
+                        vec![
+                            (first_etc_span, String::new()),
+                            (
+                                self.token.span.to(last_non_comma_dotdot_span.shrink_to_hi()),
+                                format!("{} .. }}", if ate_comma { "" } else { "," }),
+                            ),
+                        ],
+                        Applicability::MachineApplicable,
+                    );
                 }
             }
             err.emit();
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 8ee40ecd77e..42039c621d6 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -671,12 +671,12 @@ impl<'a> Parser<'a> {
                     err.emit();
                     continue;
                 }
-                if !self.token.kind.should_end_const_arg() {
-                    if self.handle_ambiguous_unbraced_const_arg(&mut args)? {
-                        // We've managed to (partially) recover, so continue trying to parse
-                        // arguments.
-                        continue;
-                    }
+                if !self.token.kind.should_end_const_arg()
+                    && self.handle_ambiguous_unbraced_const_arg(&mut args)?
+                {
+                    // We've managed to (partially) recover, so continue trying to parse
+                    // arguments.
+                    continue;
                 }
                 break;
             }
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index fce41bd90be..f2121c3243a 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -192,13 +192,11 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr:
                 );
             }
         }
-    } else {
-        if let Safety::Unsafe(unsafe_span) = attr_item.unsafety {
-            psess.dcx().emit_err(errors::InvalidAttrUnsafe {
-                span: unsafe_span,
-                name: attr_item.path.clone(),
-            });
-        }
+    } else if let Safety::Unsafe(unsafe_span) = attr_item.unsafety {
+        psess.dcx().emit_err(errors::InvalidAttrUnsafe {
+            span: unsafe_span,
+            name: attr_item.path.clone(),
+        });
     }
 }
 
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index e7f208d5ad5..5369f54afb9 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -484,6 +484,9 @@ passes_must_not_suspend =
 passes_must_use_no_effect =
     `#[must_use]` has no effect when applied to {$article} {$target}
 
+passes_naked_asm_outside_naked_fn =
+    the `naked_asm!` macro can only be used in functions marked with `#[naked]`
+
 passes_naked_functions_asm_block =
     naked functions must contain a single asm block
     .label_multiple_asm = multiple asm blocks are unsupported in naked functions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index e41f89a3c9d..ee892c17376 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1905,10 +1905,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             || (int_reprs == 1
                 && is_c
                 && item.is_some_and(|item| {
-                    if let ItemLike::Item(item) = item {
-                        return is_c_like_enum(item);
-                    }
-                    return false;
+                    if let ItemLike::Item(item) = item { is_c_like_enum(item) } else { false }
                 }))
         {
             self.tcx.emit_node_span_lint(
@@ -2172,17 +2169,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     attr.span,
                     errors::MacroExport::TooManyItems,
                 );
-            } else {
-                if meta_item_list[0].name_or_empty() != sym::local_inner_macros {
-                    self.tcx.emit_node_span_lint(
-                        INVALID_MACRO_EXPORT_ARGUMENTS,
-                        hir_id,
-                        meta_item_list[0].span(),
-                        errors::MacroExport::UnknownItem {
-                            name: meta_item_list[0].name_or_empty(),
-                        },
-                    );
-                }
+            } else if meta_item_list[0].name_or_empty() != sym::local_inner_macros {
+                self.tcx.emit_node_span_lint(
+                    INVALID_MACRO_EXPORT_ARGUMENTS,
+                    hir_id,
+                    meta_item_list[0].span(),
+                    errors::MacroExport::UnknownItem { name: meta_item_list[0].name_or_empty() },
+                );
             }
         } else {
             // special case when `#[macro_export]` is applied to a macro 2.0
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 7f1e906ffd7..ef534c645a4 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -394,7 +394,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             }
         }
 
-        return false;
+        false
     }
 
     fn visit_node(&mut self, node: Node<'tcx>) {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index f5d982e1a5c..a985ecb019a 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1222,6 +1222,13 @@ pub(crate) struct NakedFunctionIncompatibleAttribute {
 }
 
 #[derive(Diagnostic)]
+#[diag(passes_naked_asm_outside_naked_fn)]
+pub(crate) struct NakedAsmOutsideNakedFn {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(passes_attr_only_in_functions)]
 pub(crate) struct AttrOnlyInFunctions {
     #[primary_span]
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index db3eaea68b5..959b7ad147b 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1500,15 +1500,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
                             );
                         }
                     }
-                } else {
-                    if let Some(name) = self.should_warn(var) {
-                        self.ir.tcx.emit_node_span_lint(
-                            lint::builtin::UNUSED_VARIABLES,
-                            var_hir_id,
-                            vec![span],
-                            errors::UnusedVarMaybeCaptureRef { name },
-                        );
-                    }
+                } else if let Some(name) = self.should_warn(var) {
+                    self.ir.tcx.emit_node_span_lint(
+                        lint::builtin::UNUSED_VARIABLES,
+                        var_hir_id,
+                        vec![span],
+                        errors::UnusedVarMaybeCaptureRef { name },
+                    );
                 }
             }
         }
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index b72ce239c4a..ab6385dd7d7 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -6,6 +6,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{LocalDefId, LocalModDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{ExprKind, HirIdSet, InlineAsmOperand, StmtKind};
+use rustc_middle::hir::nested_filter::OnlyBodies;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
@@ -14,8 +15,9 @@ use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
 use crate::errors::{
-    NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, NakedFunctionsMustUseNoreturn,
-    NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, UndefinedNakedFunctionAbi,
+    NakedAsmOutsideNakedFn, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions,
+    NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed,
+    UndefinedNakedFunctionAbi,
 };
 
 pub(crate) fn provide(providers: &mut Providers) {
@@ -29,11 +31,6 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
             continue;
         }
 
-        let naked = tcx.has_attr(def_id, sym::naked);
-        if !naked {
-            continue;
-        }
-
         let (fn_header, body_id) = match tcx.hir_node_by_def_id(def_id) {
             hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })
             | hir::Node::TraitItem(hir::TraitItem {
@@ -48,10 +45,17 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
         };
 
         let body = tcx.hir().body(body_id);
-        check_abi(tcx, def_id, fn_header.abi);
-        check_no_patterns(tcx, body.params);
-        check_no_parameters_use(tcx, body);
-        check_asm(tcx, def_id, body);
+
+        if tcx.has_attr(def_id, sym::naked) {
+            check_abi(tcx, def_id, fn_header.abi);
+            check_no_patterns(tcx, body.params);
+            check_no_parameters_use(tcx, body);
+            check_asm(tcx, def_id, body);
+        } else {
+            // `naked_asm!` is not allowed outside of functions marked as `#[naked]`
+            let mut visitor = CheckNakedAsmInNakedFn { tcx };
+            visitor.visit_body(body);
+        }
     }
 }
 
@@ -276,3 +280,25 @@ impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> {
         self.check_expr(expr, expr.span);
     }
 }
+
+struct CheckNakedAsmInNakedFn<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> Visitor<'tcx> for CheckNakedAsmInNakedFn<'tcx> {
+    type NestedFilter = OnlyBodies;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.tcx.hir()
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
+        if let ExprKind::InlineAsm(inline_asm) = expr.kind {
+            if let rustc_ast::AsmMacro::NakedAsm = inline_asm.asm_macro {
+                self.tcx.dcx().emit_err(NakedAsmOutsideNakedFn { span: expr.span });
+            }
+        }
+
+        hir::intravisit::walk_expr(self, expr);
+    }
+}
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index ba4c300ea61..e2c9067c0b9 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -174,16 +174,14 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
 
         // If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI,
         // check if the function/method is const or the parent impl block is const
-        if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig) {
-            if fn_sig.header.abi != Abi::RustIntrinsic && !fn_sig.header.is_const() {
-                if !self.in_trait_impl
-                    || (self.in_trait_impl && !self.tcx.is_const_fn_raw(def_id.to_def_id()))
-                {
-                    self.tcx
-                        .dcx()
-                        .emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span });
-                }
-            }
+        if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig)
+            && fn_sig.header.abi != Abi::RustIntrinsic
+            && !fn_sig.header.is_const()
+            && (!self.in_trait_impl || !self.tcx.is_const_fn_raw(def_id.to_def_id()))
+        {
+            self.tcx
+                .dcx()
+                .emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span });
         }
 
         // `impl const Trait for Type` items forward their const stability to their
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index 6535afcc398..814559a66c5 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -951,7 +951,11 @@ impl<Cx: PatCx> PlaceInfo<Cx> {
             self.is_scrutinee && matches!(ctors_for_ty, ConstructorSet::NoConstructors);
         // Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if
         // it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`).
-        let empty_arms_are_unreachable = self.validity.is_known_valid();
+        // We don't want to warn empty patterns as unreachable by default just yet. We will in a
+        // later version of rust or under a different lint name, see
+        // https://github.com/rust-lang/rust/pull/129103.
+        let empty_arms_are_unreachable = self.validity.is_known_valid()
+            && (is_toplevel_exception || cx.is_exhaustive_patterns_feature_on());
         // Whether empty patterns can be omitted for exhaustiveness. We ignore place validity in the
         // toplevel exception and `exhaustive_patterns` cases for backwards compatibility.
         let can_omit_empty_arms = self.validity.is_known_valid()
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index f349713f22d..3b69ecee357 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1233,64 +1233,63 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     && ns == namespace
                     && in_module != parent_scope.module
                     && !ident.span.normalize_to_macros_2_0().from_expansion()
+                    && filter_fn(res)
                 {
-                    if filter_fn(res) {
-                        // create the path
-                        let mut segms = if lookup_ident.span.at_least_rust_2018() {
-                            // crate-local absolute paths start with `crate::` in edition 2018
-                            // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
-                            crate_path.clone()
-                        } else {
-                            ThinVec::new()
-                        };
-                        segms.append(&mut path_segments.clone());
+                    // create the path
+                    let mut segms = if lookup_ident.span.at_least_rust_2018() {
+                        // crate-local absolute paths start with `crate::` in edition 2018
+                        // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
+                        crate_path.clone()
+                    } else {
+                        ThinVec::new()
+                    };
+                    segms.append(&mut path_segments.clone());
 
-                        segms.push(ast::PathSegment::from_ident(ident));
-                        let path = Path { span: name_binding.span, segments: segms, tokens: None };
+                    segms.push(ast::PathSegment::from_ident(ident));
+                    let path = Path { span: name_binding.span, segments: segms, tokens: None };
 
-                        if child_accessible {
-                            // Remove invisible match if exists
-                            if let Some(idx) = candidates
-                                .iter()
-                                .position(|v: &ImportSuggestion| v.did == did && !v.accessible)
-                            {
-                                candidates.remove(idx);
-                            }
+                    if child_accessible {
+                        // Remove invisible match if exists
+                        if let Some(idx) = candidates
+                            .iter()
+                            .position(|v: &ImportSuggestion| v.did == did && !v.accessible)
+                        {
+                            candidates.remove(idx);
                         }
+                    }
 
-                        if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
-                            // See if we're recommending TryFrom, TryInto, or FromIterator and add
-                            // a note about editions
-                            let note = if let Some(did) = did {
-                                let requires_note = !did.is_local()
-                                    && this.tcx.get_attrs(did, sym::rustc_diagnostic_item).any(
-                                        |attr| {
-                                            [sym::TryInto, sym::TryFrom, sym::FromIterator]
-                                                .map(|x| Some(x))
-                                                .contains(&attr.value_str())
-                                        },
-                                    );
-
-                                requires_note.then(|| {
-                                    format!(
-                                        "'{}' is included in the prelude starting in Edition 2021",
-                                        path_names_to_string(&path)
-                                    )
-                                })
-                            } else {
-                                None
-                            };
-
-                            candidates.push(ImportSuggestion {
-                                did,
-                                descr: res.descr(),
-                                path,
-                                accessible: child_accessible,
-                                doc_visible: child_doc_visible,
-                                note,
-                                via_import,
-                            });
-                        }
+                    if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
+                        // See if we're recommending TryFrom, TryInto, or FromIterator and add
+                        // a note about editions
+                        let note = if let Some(did) = did {
+                            let requires_note = !did.is_local()
+                                && this.tcx.get_attrs(did, sym::rustc_diagnostic_item).any(
+                                    |attr| {
+                                        [sym::TryInto, sym::TryFrom, sym::FromIterator]
+                                            .map(|x| Some(x))
+                                            .contains(&attr.value_str())
+                                    },
+                                );
+
+                            requires_note.then(|| {
+                                format!(
+                                    "'{}' is included in the prelude starting in Edition 2021",
+                                    path_names_to_string(&path)
+                                )
+                            })
+                        } else {
+                            None
+                        };
+
+                        candidates.push(ImportSuggestion {
+                            did,
+                            descr: res.descr(),
+                            path,
+                            accessible: child_accessible,
+                            doc_visible: child_doc_visible,
+                            note,
+                            via_import,
+                        });
                     }
                 }
 
@@ -3076,7 +3075,7 @@ fn search_for_any_use_in_items(items: &[P<ast::Item>]) -> Option<Span> {
             }
         }
     }
-    return None;
+    None
 }
 
 fn is_span_suitable_for_use_injection(s: Span) -> bool {
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 1602db2f196..61df051ec1e 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -958,12 +958,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 });
             }
 
-            if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT {
-                if let NameBindingKind::Import { import, .. } = binding.kind
-                    && matches!(import.kind, ImportKind::MacroExport)
-                {
-                    self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
-                }
+            if !restricted_shadowing
+                && binding.expansion != LocalExpnId::ROOT
+                && let NameBindingKind::Import { import, .. } = binding.kind
+                && matches!(import.kind, ImportKind::MacroExport)
+            {
+                self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
             }
 
             self.record_use(ident, binding, used);
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 2edff67f96a..67ee377fd54 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -1260,28 +1260,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         extern_crate_span: self.tcx.source_span(self.local_def_id(extern_crate_id)),
                     },
                 );
+            } else if ns == TypeNS {
+                let err = if crate_private_reexport {
+                    self.dcx()
+                        .create_err(CannotBeReexportedCratePublicNS { span: import.span, ident })
+                } else {
+                    self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident })
+                };
+                err.emit();
             } else {
-                if ns == TypeNS {
-                    let err = if crate_private_reexport {
-                        self.dcx().create_err(CannotBeReexportedCratePublicNS {
-                            span: import.span,
-                            ident,
-                        })
-                    } else {
-                        self.dcx()
-                            .create_err(CannotBeReexportedPrivateNS { span: import.span, ident })
-                    };
-                    err.emit();
+                let mut err = if crate_private_reexport {
+                    self.dcx()
+                        .create_err(CannotBeReexportedCratePublic { span: import.span, ident })
                 } else {
-                    let mut err = if crate_private_reexport {
-                        self.dcx()
-                            .create_err(CannotBeReexportedCratePublic { span: import.span, ident })
-                    } else {
-                        self.dcx()
-                            .create_err(CannotBeReexportedPrivate { span: import.span, ident })
-                    };
+                    self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident })
+                };
 
-                    match binding.kind {
+                match binding.kind {
                         NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id))
                             // exclude decl_macro
                             if self.get_macro_by_def_id(def_id).macro_rules =>
@@ -1297,8 +1292,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             });
                         }
                     }
-                    err.emit();
-                }
+                err.emit();
             }
         }
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 8ebfe328e3e..0aa351cad40 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -4782,16 +4782,14 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 if let Some(res) = res
                     && let Some(def_id) = res.opt_def_id()
                     && !def_id.is_local()
+                    && self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
+                    && matches!(
+                        self.r.tcx.sess.opts.resolve_doc_links,
+                        ResolveDocLinks::ExportedMetadata
+                    )
                 {
-                    if self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
-                        && matches!(
-                            self.r.tcx.sess.opts.resolve_doc_links,
-                            ResolveDocLinks::ExportedMetadata
-                        )
-                    {
-                        // Encoding foreign def ids in proc macro crate metadata will ICE.
-                        return None;
-                    }
+                    // Encoding foreign def ids in proc macro crate metadata will ICE.
+                    return None;
                 }
                 res
             });
@@ -5017,5 +5015,5 @@ fn def_id_matches_path(tcx: TyCtxt<'_>, mut def_id: DefId, expected_path: &[&str
         }
         def_id = parent;
     }
-    return true;
+    true
 }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index fb658407f61..1c584bf8338 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -779,7 +779,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg);
         }
 
-        return (false, candidates);
+        (false, candidates)
     }
 
     fn suggest_trait_and_bounds(
@@ -2255,25 +2255,24 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn let_binding_suggestion(&mut self, err: &mut Diag<'_>, ident_span: Span) -> bool {
         if let Some(Expr { kind: ExprKind::Assign(lhs, ..), .. }) = self.diag_metadata.in_assignment
             && let ast::ExprKind::Path(None, ref path) = lhs.kind
+            && !ident_span.from_expansion()
         {
-            if !ident_span.from_expansion() {
-                let (span, text) = match path.segments.first() {
-                    Some(seg) if let Some(name) = seg.ident.as_str().strip_prefix("let") => {
-                        // a special case for #117894
-                        let name = name.strip_prefix('_').unwrap_or(name);
-                        (ident_span, format!("let {name}"))
-                    }
-                    _ => (ident_span.shrink_to_lo(), "let ".to_string()),
-                };
+            let (span, text) = match path.segments.first() {
+                Some(seg) if let Some(name) = seg.ident.as_str().strip_prefix("let") => {
+                    // a special case for #117894
+                    let name = name.strip_prefix('_').unwrap_or(name);
+                    (ident_span, format!("let {name}"))
+                }
+                _ => (ident_span.shrink_to_lo(), "let ".to_string()),
+            };
 
-                err.span_suggestion_verbose(
-                    span,
-                    "you might have meant to introduce a new binding",
-                    text,
-                    Applicability::MaybeIncorrect,
-                );
-                return true;
-            }
+            err.span_suggestion_verbose(
+                span,
+                "you might have meant to introduce a new binding",
+                text,
+                Applicability::MaybeIncorrect,
+            );
+            return true;
         }
         false
     }
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 976c4acb212..bed3baa30fb 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -270,12 +270,10 @@ fn strip_generics_from_path_segment(segment: Vec<char>) -> Result<String, Malfor
                 // Give a helpful error message instead of completely ignoring the angle brackets.
                 return Err(MalformedGenerics::HasFullyQualifiedSyntax);
             }
+        } else if param_depth == 0 {
+            stripped_segment.push(c);
         } else {
-            if param_depth == 0 {
-                stripped_segment.push(c);
-            } else {
-                latest_generics_chunk.push(c);
-            }
+            latest_generics_chunk.push(c);
         }
     }
 
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index 45057a3530c..a0a0dd058ff 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -207,14 +207,12 @@ fn encode_fnsig<'tcx>(
         if fn_sig.c_variadic {
             s.push('z');
         }
+    } else if fn_sig.c_variadic {
+        s.push('z');
     } else {
-        if fn_sig.c_variadic {
-            s.push('z');
-        } else {
-            // Empty parameter lists, whether declared as () or conventionally as (void), are
-            // encoded with a void parameter specifier "v".
-            s.push('v')
-        }
+        // Empty parameter lists, whether declared as () or conventionally as (void), are
+        // encoded with a void parameter specifier "v".
+        s.push('v')
     }
 
     // Close the "F..E" pair
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index 01c371ee498..a4fbab8477b 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -113,6 +113,8 @@ session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clt
 
 session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
 
+session_target_small_data_threshold_not_supported = `-Z small-data-threshold` is not supported for target {$target_triple} and will be ignored
+
 session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
 
 session_unleashed_feature_help_named = skipping check for `{$gate}` feature
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index f3e3b36111c..908d50a041e 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -842,11 +842,6 @@ pub struct NextSolverConfig {
     /// This is only `true` if `coherence` is also enabled.
     pub globally: bool,
 }
-impl Default for NextSolverConfig {
-    fn default() -> Self {
-        NextSolverConfig { coherence: true, globally: false }
-    }
-}
 
 #[derive(Clone)]
 pub enum Input {
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 15bbd4ff7bf..462e2a97c33 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -183,6 +183,12 @@ pub(crate) struct StackProtectorNotSupportedForTarget<'a> {
 }
 
 #[derive(Diagnostic)]
+#[diag(session_target_small_data_threshold_not_supported)]
+pub(crate) struct SmallDataThresholdNotSupportedForTarget<'a> {
+    pub(crate) target_triple: &'a TargetTriple,
+}
+
+#[derive(Diagnostic)]
 #[diag(session_branch_protection_requires_aarch64)]
 pub(crate) struct BranchProtectionRequiresAArch64;
 
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index d78f4a78de7..e72d4face3c 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -182,7 +182,7 @@ pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
         }
     }
 
-    return sysroot_candidates;
+    sysroot_candidates
 }
 
 /// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none.
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index a57dc80b316..e487a2501e3 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -353,7 +353,7 @@ fn build_options<O: Default>(
             None => early_dcx.early_fatal(format!("unknown {outputname} option: `{key}`")),
         }
     }
-    return op;
+    op
 }
 
 #[allow(non_upper_case_globals)]
@@ -403,7 +403,7 @@ mod desc {
     pub(crate) const parse_unpretty: &str = "`string` or `string=string`";
     pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
     pub(crate) const parse_next_solver_config: &str =
-        "either `globally` (when used without an argument), `coherence` (default) or `no`";
+        "a comma separated list of solver configurations: `globally` (default), and `coherence`";
     pub(crate) const parse_lto: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted";
     pub(crate) const parse_linker_plugin_lto: &str =
@@ -1105,16 +1105,27 @@ mod parse {
         }
     }
 
-    pub(crate) fn parse_next_solver_config(slot: &mut NextSolverConfig, v: Option<&str>) -> bool {
+    pub(crate) fn parse_next_solver_config(
+        slot: &mut Option<NextSolverConfig>,
+        v: Option<&str>,
+    ) -> bool {
         if let Some(config) = v {
-            *slot = match config {
-                "no" => NextSolverConfig { coherence: false, globally: false },
-                "coherence" => NextSolverConfig { coherence: true, globally: false },
-                "globally" => NextSolverConfig { coherence: true, globally: true },
-                _ => return false,
-            };
+            let mut coherence = false;
+            let mut globally = true;
+            for c in config.split(',') {
+                match c {
+                    "globally" => globally = true,
+                    "coherence" => {
+                        globally = false;
+                        coherence = true;
+                    }
+                    _ => return false,
+                }
+            }
+
+            *slot = Some(NextSolverConfig { coherence: coherence || globally, globally });
         } else {
-            *slot = NextSolverConfig { coherence: true, globally: true };
+            *slot = Some(NextSolverConfig { coherence: true, globally: true });
         }
 
         true
@@ -1867,7 +1878,7 @@ options! {
         "the size at which the `large_assignments` lint starts to be emitted"),
     mutable_noalias: bool = (true, parse_bool, [TRACKED],
         "emit noalias metadata for mutable references (default: yes)"),
-    next_solver: NextSolverConfig = (NextSolverConfig::default(), parse_next_solver_config, [TRACKED],
+    next_solver: Option<NextSolverConfig> = (None, parse_next_solver_config, [TRACKED],
         "enable and configure the next generation trait solver used by rustc"),
     nll_facts: bool = (false, parse_bool, [UNTRACKED],
         "dump facts from NLL analysis into side files (default: no)"),
@@ -2014,6 +2025,8 @@ written to standard error output)"),
     simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
         to rust's source base directory. only meant for testing purposes"),
+    small_data_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
+        "Set the threshold for objects to be stored in a \"small data\" section"),
     span_debug: bool = (false, parse_bool, [UNTRACKED],
         "forward proc_macro::Span's `Debug` impl to `Span`"),
     /// o/w tests have closure@path
diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs
index d65b1b8b3f1..b212f6afa17 100644
--- a/compiler/rustc_session/src/search_paths.rs
+++ b/compiler/rustc_session/src/search_paths.rs
@@ -96,7 +96,7 @@ impl SearchPath {
         Self::new(PathKind::All, make_target_lib_path(sysroot, triple))
     }
 
-    fn new(kind: PathKind, dir: PathBuf) -> Self {
+    pub fn new(kind: PathKind, dir: PathBuf) -> Self {
         // Get the files within the directory.
         let files = match std::fs::read_dir(&dir) {
             Ok(files) => files
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 70430d82ab5..387ae1b78c4 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -30,8 +30,8 @@ use rustc_span::source_map::{FilePathMapping, SourceMap};
 use rustc_span::{FileNameDisplayPreference, RealFileName, Span, Symbol};
 use rustc_target::asm::InlineAsmArch;
 use rustc_target::spec::{
-    CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo,
-    StackProtector, Target, TargetTriple, TlsModel,
+    CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet,
+    SmallDataThresholdSupport, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel,
 };
 
 use crate::code_stats::CodeStats;
@@ -1278,6 +1278,14 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         }
     }
 
+    if sess.opts.unstable_opts.small_data_threshold.is_some() {
+        if sess.target.small_data_threshold_support() == SmallDataThresholdSupport::None {
+            sess.dcx().emit_warn(errors::SmallDataThresholdNotSupportedForTarget {
+                target_triple: &sess.opts.target_triple,
+            })
+        }
+    }
+
     if sess.opts.unstable_opts.branch_protection.is_some() && sess.target.arch != "aarch64" {
         sess.dcx().emit_err(errors::BranchProtectionRequiresAArch64);
     }
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index f914e8dc1ba..98447147d3e 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -779,7 +779,7 @@ impl SourceMap {
                     return Ok(false);
                 }
             }
-            return Ok(true);
+            Ok(true)
         })
         .is_ok_and(|is_accessible| is_accessible)
     }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7572d57309c..28d18f2dfcc 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1255,6 +1255,7 @@ symbols! {
         mut_preserve_binding_mode_2024,
         mut_ref,
         naked,
+        naked_asm,
         naked_functions,
         name,
         names,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 75f4499352b..ba35a37c32c 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -381,7 +381,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
                     let consts = [
                         start.unwrap_or(self.tcx.consts.unit),
                         end.unwrap_or(self.tcx.consts.unit),
-                        ty::Const::from_bool(self.tcx, include_end).into(),
+                        ty::Const::from_bool(self.tcx, include_end),
                     ];
                     // HACK: Represent as tuple until we have something better.
                     // HACK: constants are used in arrays, even if the types don't match.
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 082c169b210..c2826b55dc5 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -188,7 +188,7 @@ impl ArgAttributes {
         if self.arg_ext != other.arg_ext {
             return false;
         }
-        return true;
+        true
     }
 }
 
@@ -632,7 +632,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
             PassMode::Indirect { .. } => {
                 self.mode = PassMode::Direct(ArgAttributes::new());
             }
-            PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) => return, // already direct
+            PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) => {} // already direct
             _ => panic!("Tried to make {:?} direct", self.mode),
         }
     }
@@ -646,7 +646,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
             }
             PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
                 // already indirect
-                return;
             }
             _ => panic!("Tried to make {:?} indirect", self.mode),
         }
@@ -661,7 +660,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
             }
             PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
                 // already indirect
-                return;
             }
             _ => panic!("Tried to make {:?} indirect (expected `PassMode::Ignore`)", self.mode),
         }
diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs
index 2954d9642df..835353f76fc 100644
--- a/compiler/rustc_target/src/abi/call/sparc64.rs
+++ b/compiler/rustc_target/src/abi/call/sparc64.rs
@@ -66,7 +66,7 @@ where
         data.last_offset = offset + Reg::f64().size;
     }
     data.prefix_index += 1;
-    return data;
+    data
 }
 
 fn arg_scalar_pair<C>(
@@ -92,7 +92,7 @@ where
         offset += Size::from_bytes(4 - (offset.bytes() % 4));
     }
     data = arg_scalar(cx, scalar2, offset, data);
-    return data;
+    data
 }
 
 fn parse_structure<'a, Ty, C>(
@@ -128,7 +128,7 @@ where
         }
     }
 
-    return data;
+    data
 }
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size)
diff --git a/compiler/rustc_target/src/abi/call/xtensa.rs b/compiler/rustc_target/src/abi/call/xtensa.rs
index cb61bf2c56b..d7b5fe9d4cc 100644
--- a/compiler/rustc_target/src/abi/call/xtensa.rs
+++ b/compiler/rustc_target/src/abi/call/xtensa.rs
@@ -69,29 +69,27 @@ where
 
     if must_use_stack {
         arg.make_indirect_byval(None);
-    } else {
-        if is_xtensa_aggregate(arg) {
-            // Aggregates which are <= max_size will be passed in
-            // registers if possible, so coerce to integers.
+    } else if is_xtensa_aggregate(arg) {
+        // Aggregates which are <= max_size will be passed in
+        // registers if possible, so coerce to integers.
 
-            // Use a single `xlen` int if possible, 2 * `xlen` if 2 * `xlen` alignment
-            // is required, and a 2-element `xlen` array if only `xlen` alignment is
-            // required.
-            if size <= 32 {
-                arg.cast_to(Reg::i32());
-            } else {
-                let reg = if needed_align == 2 * 32 { Reg::i64() } else { Reg::i32() };
-                let total = Size::from_bits(((size + 32 - 1) / 32) * 32);
-                arg.cast_to(Uniform::new(reg, total));
-            }
+        // Use a single `xlen` int if possible, 2 * `xlen` if 2 * `xlen` alignment
+        // is required, and a 2-element `xlen` array if only `xlen` alignment is
+        // required.
+        if size <= 32 {
+            arg.cast_to(Reg::i32());
         } else {
-            // All integral types are promoted to `xlen`
-            // width.
-            //
-            // We let the LLVM backend handle integral types >= xlen.
-            if size < 32 {
-                arg.extend_integer_width_to(32);
-            }
+            let reg = if needed_align == 2 * 32 { Reg::i64() } else { Reg::i32() };
+            let total = Size::from_bits(((size + 32 - 1) / 32) * 32);
+            arg.cast_to(Uniform::new(reg, total));
+        }
+    } else {
+        // All integral types are promoted to `xlen`
+        // width.
+        //
+        // We let the LLVM backend handle integral types >= xlen.
+        if size < 32 {
+            arg.extend_integer_width_to(32);
         }
     }
 }
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index b1fe49f76ca..e78e3222115 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -168,7 +168,26 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs {
         ["-platform_version".into(), platform_name, min_version, sdk_version].into_iter(),
     );
 
-    if abi != TargetAbi::MacCatalyst {
+    // We need to communicate four things to the C compiler to be able to link:
+    // - The architecture.
+    // - The operating system (and that it's an Apple platform).
+    // - The deployment target.
+    // - The environment / ABI.
+    //
+    // We'd like to use `-target` everywhere, since that can uniquely
+    // communicate all of these, but that doesn't work on GCC, and since we
+    // don't know whether the `cc` compiler is Clang, GCC, or something else,
+    // we fall back to other options that also work on GCC when compiling for
+    // macOS.
+    //
+    // Targets other than macOS are ill-supported by GCC (it doesn't even
+    // support e.g. `-miphoneos-version-min`), so in those cases we can fairly
+    // safely use `-target`. See also the following, where it is made explicit
+    // that the recommendation by LLVM developers is to use `-target`:
+    // <https://github.com/llvm/llvm-project/issues/88271>
+    if os == "macos" {
+        // `-arch` communicates the architecture.
+        //
         // CC forwards the `-arch` to the linker, so we use the same value
         // here intentionally.
         add_link_args(
@@ -176,6 +195,15 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs {
             LinkerFlavor::Darwin(Cc::Yes, Lld::No),
             &["-arch", arch.ld_arch()],
         );
+        // The presence of `-mmacosx-version-min` makes CC default to macOS,
+        // and it sets the deployment target.
+        let (major, minor, patch) = deployment_target(os, arch, abi);
+        let opt = format!("-mmacosx-version-min={major}.{minor}.{patch}").into();
+        add_link_args_iter(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), [opt].into_iter());
+        // macOS has no environment, so with these two, we've told CC all the
+        // desired parameters.
+        //
+        // We avoid `-m32`/`-m64`, as this is already encoded by `-arch`.
     } else {
         add_link_args_iter(
             &mut args,
@@ -323,12 +351,18 @@ fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) {
     };
 
     // On certain targets it makes sense to raise the minimum OS version.
+    //
+    // This matches what LLVM does, see:
+    // <https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L1900-L1932>
     let min = match (os, arch, abi) {
-        // Use 11.0 on Aarch64 as that's the earliest version with M1 support.
         ("macos", Arch::Arm64 | Arch::Arm64e, _) => (11, 0, 0),
-        ("ios", Arch::Arm64e, _) => (14, 0, 0),
+        ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::MacCatalyst) => (14, 0, 0),
+        ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0),
+        ("ios", Arch::Arm64e, TargetAbi::Normal) => (14, 0, 0),
         // Mac Catalyst defaults to 13.1 in Clang.
         ("ios", _, TargetAbi::MacCatalyst) => (13, 1, 0),
+        ("tvos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0),
+        ("watchos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (7, 0, 0),
         _ => os_min,
     };
 
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index c3e7f74c564..f12e3e595ad 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -855,6 +855,43 @@ impl ToJson for RelroLevel {
     }
 }
 
+#[derive(Clone, Debug, PartialEq, Hash)]
+pub enum SmallDataThresholdSupport {
+    None,
+    DefaultForArch,
+    LlvmModuleFlag(StaticCow<str>),
+    LlvmArg(StaticCow<str>),
+}
+
+impl FromStr for SmallDataThresholdSupport {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        if s == "none" {
+            Ok(Self::None)
+        } else if s == "default-for-arch" {
+            Ok(Self::DefaultForArch)
+        } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") {
+            Ok(Self::LlvmModuleFlag(flag.to_string().into()))
+        } else if let Some(arg) = s.strip_prefix("llvm-arg=") {
+            Ok(Self::LlvmArg(arg.to_string().into()))
+        } else {
+            Err(())
+        }
+    }
+}
+
+impl ToJson for SmallDataThresholdSupport {
+    fn to_json(&self) -> Value {
+        match self {
+            Self::None => "none".to_json(),
+            Self::DefaultForArch => "default-for-arch".to_json(),
+            Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(),
+            Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(),
+        }
+    }
+}
+
 #[derive(Clone, Copy, Debug, PartialEq, Hash)]
 pub enum MergeFunctions {
     Disabled,
@@ -2392,6 +2429,9 @@ pub struct TargetOptions {
 
     /// Whether the target supports XRay instrumentation.
     pub supports_xray: bool,
+
+    /// Whether the targets supports -Z small-data-threshold
+    small_data_threshold_support: SmallDataThresholdSupport,
 }
 
 /// Add arguments for the given flavor and also for its "twin" flavors
@@ -2609,6 +2649,7 @@ impl Default for TargetOptions {
             entry_name: "main".into(),
             entry_abi: Conv::C,
             supports_xray: false,
+            small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
         }
     }
 }
@@ -2884,6 +2925,15 @@ impl Target {
                     Some(Ok(()))
                 })).unwrap_or(Ok(()))
             } );
+            ($key_name:ident, SmallDataThresholdSupport) => ( {
+                obj.remove("small-data-threshold-support").and_then(|o| o.as_str().and_then(|s| {
+                    match s.parse::<SmallDataThresholdSupport>() {
+                        Ok(support) => base.small_data_threshold_support = support,
+                        _ => return Some(Err(format!("'{s}' is not a valid value for small-data-threshold-support."))),
+                    }
+                    Some(Ok(()))
+                })).unwrap_or(Ok(()))
+            } );
             ($key_name:ident, PanicStrategy) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
                 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
@@ -3321,6 +3371,7 @@ impl Target {
         key!(supported_sanitizers, SanitizerSet)?;
         key!(generate_arange_section, bool);
         key!(supports_stack_protector, bool);
+        key!(small_data_threshold_support, SmallDataThresholdSupport)?;
         key!(entry_name);
         key!(entry_abi, Conv)?;
         key!(supports_xray, bool);
@@ -3415,6 +3466,30 @@ impl Target {
             }
         }
     }
+
+    /// Return the target's small data threshold support, converting
+    /// `DefaultForArch` into a concrete value.
+    pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
+        match &self.options.small_data_threshold_support {
+            // Avoid having to duplicate the small data support in every
+            // target file by supporting a default value for each
+            // architecture.
+            SmallDataThresholdSupport::DefaultForArch => match self.arch.as_ref() {
+                "mips" | "mips64" | "mips32r6" => {
+                    SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
+                }
+                "hexagon" => {
+                    SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
+                }
+                "m68k" => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
+                "riscv32" | "riscv64" => {
+                    SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
+                }
+                _ => SmallDataThresholdSupport::None,
+            },
+            s => s.clone(),
+        }
+    }
 }
 
 impl ToJson for Target {
@@ -3577,6 +3652,7 @@ impl ToJson for Target {
         target_option_val!(c_enum_min_bits);
         target_option_val!(generate_arange_section);
         target_option_val!(supports_stack_protector);
+        target_option_val!(small_data_threshold_support);
         target_option_val!(entry_name);
         target_option_val!(entry_abi);
         target_option_val!(supports_xray);
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index 67afe35bee4..3e27f1f899b 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -1,10 +1,8 @@
 use crate::spec::base::apple::{base, Arch, TargetAbi};
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
+use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (mut opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
-    opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
-
+    let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index e7f14aa9209..4304dfc3f68 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -1,9 +1,8 @@
 use crate::spec::base::apple::{base, Arch, TargetAbi};
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
-    opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
+    let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index f44bc660a62..9fb5a46187a 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -1,11 +1,10 @@
 use crate::spec::base::apple::{base, Arch, TargetAbi};
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal);
     opts.max_atomic_width = Some(128);
     opts.frame_pointer = FramePointer::Always;
-    opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
     opts.supported_sanitizers =
         SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 65d21518491..d486416f22a 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -1323,23 +1323,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 label_or_note(span, terr.to_string(self.tcx));
                 label_or_note(sp, msg);
             }
-        } else {
-            if let Some(values) = values
-                && let Some((e, f)) = values.ty()
-                && let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr
-            {
-                let e = self.tcx.erase_regions(e);
-                let f = self.tcx.erase_regions(f);
-                let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
-                let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
-                if expected == found {
-                    label_or_note(span, terr.to_string(self.tcx));
-                } else {
-                    label_or_note(span, Cow::from(format!("expected {expected}, found {found}")));
-                }
-            } else {
+        } else if let Some(values) = values
+            && let Some((e, f)) = values.ty()
+            && let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr
+        {
+            let e = self.tcx.erase_regions(e);
+            let f = self.tcx.erase_regions(f);
+            let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
+            let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
+            if expected == found {
                 label_or_note(span, terr.to_string(self.tcx));
+            } else {
+                label_or_note(span, Cow::from(format!("expected {expected}, found {found}")));
             }
+        } else {
+            label_or_note(span, terr.to_string(self.tcx));
         }
 
         if let Some((expected, found, path)) = expected_found {
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 0372105a02b..38d06f53fa6 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -852,18 +852,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         impl<'hir, 'tcx> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'tcx, '_> {
             fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) {
                 if lt.res == self.needle {
-                    let (pos, span) = lt.suggestion_position();
-                    let new_lt = &self.new_lt;
-                    let sugg = match pos {
-                        hir::LifetimeSuggestionPosition::Normal => format!("{new_lt}"),
-                        hir::LifetimeSuggestionPosition::Ampersand => format!("{new_lt} "),
-                        hir::LifetimeSuggestionPosition::ElidedPath => format!("<{new_lt}>"),
-                        hir::LifetimeSuggestionPosition::ElidedPathArgument => {
-                            format!("{new_lt}, ")
-                        }
-                        hir::LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lt}"),
-                    };
-                    self.add_lt_suggs.push((span, sugg));
+                    self.add_lt_suggs.push(lt.suggestion(self.new_lt));
                 }
             }
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 45e157b1080..b13aede509a 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -3237,16 +3237,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 // then the tuple must be the one containing capture types.
                 let is_upvar_tys_infer_tuple = if !matches!(ty.kind(), ty::Tuple(..)) {
                     false
+                } else if let ObligationCauseCode::BuiltinDerived(data) = &*data.parent_code {
+                    let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
+                    let nested_ty = parent_trait_ref.skip_binder().self_ty();
+                    matches!(nested_ty.kind(), ty::Coroutine(..))
+                        || matches!(nested_ty.kind(), ty::Closure(..))
                 } else {
-                    if let ObligationCauseCode::BuiltinDerived(data) = &*data.parent_code {
-                        let parent_trait_ref =
-                            self.resolve_vars_if_possible(data.parent_trait_pred);
-                        let nested_ty = parent_trait_ref.skip_binder().self_ty();
-                        matches!(nested_ty.kind(), ty::Coroutine(..))
-                            || matches!(nested_ty.kind(), ty::Closure(..))
-                    } else {
-                        false
-                    }
+                    false
                 };
 
                 if !is_upvar_tys_infer_tuple {
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index c8811bc37b3..de1d4ef15ac 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -35,8 +35,10 @@ where
         if infcx.next_trait_solver() {
             Box::new(NextFulfillmentCtxt::new(infcx))
         } else {
+            let new_solver_globally =
+                infcx.tcx.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally);
             assert!(
-                !infcx.tcx.next_trait_solver_globally(),
+                !new_solver_globally,
                 "using old solver even though new solver is enabled globally"
             );
             Box::new(FulfillmentContext::new(infcx))
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 630acc91fbe..c27a9285b3a 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -408,7 +408,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
             debug!("opt_normalize_projection_type: found error");
             let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
             obligations.extend(result.obligations);
-            return Ok(Some(result.value.into()));
+            return Ok(Some(result.value));
         }
     }
 
@@ -478,7 +478,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
             }
             let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
             obligations.extend(result.obligations);
-            Ok(Some(result.value.into()))
+            Ok(Some(result.value))
         }
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 77efc2fc2db..3e3589538c7 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -426,13 +426,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     } else if kind == ty::ClosureKind::FnOnce {
                         candidates.vec.push(ClosureCandidate { is_const });
                     }
+                } else if kind == ty::ClosureKind::FnOnce {
+                    candidates.vec.push(ClosureCandidate { is_const });
                 } else {
-                    if kind == ty::ClosureKind::FnOnce {
-                        candidates.vec.push(ClosureCandidate { is_const });
-                    } else {
-                        // This stays ambiguous until kind+upvars are determined.
-                        candidates.ambiguous = true;
-                    }
+                    // This stays ambiguous until kind+upvars are determined.
+                    candidates.ambiguous = true;
                 }
             }
             ty::Infer(ty::TyVar(_)) => {
@@ -513,10 +511,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // then there's nothing else to check.
         if let Some(closure_kind) = self_ty.to_opt_closure_kind()
             && let Some(goal_kind) = target_kind_ty.to_opt_closure_kind()
+            && closure_kind.extends(goal_kind)
         {
-            if closure_kind.extends(goal_kind) {
-                candidates.vec.push(AsyncFnKindHelperCandidate);
-            }
+            candidates.vec.push(AsyncFnKindHelperCandidate);
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 241c3a3d141..f5cd7273ca2 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1334,16 +1334,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return;
         }
 
-        if self.can_use_global_caches(param_env) {
-            if !trait_pred.has_infer() {
-                debug!(?trait_pred, ?result, "insert_evaluation_cache global");
-                // This may overwrite the cache with the same value
-                // FIXME: Due to #50507 this overwrites the different values
-                // This should be changed to use HashMapExt::insert_same
-                // when that is fixed
-                self.tcx().evaluation_cache.insert((param_env, trait_pred), dep_node, result);
-                return;
-            }
+        if self.can_use_global_caches(param_env) && !trait_pred.has_infer() {
+            debug!(?trait_pred, ?result, "insert_evaluation_cache global");
+            // This may overwrite the cache with the same value
+            // FIXME: Due to #50507 this overwrites the different values
+            // This should be changed to use HashMapExt::insert_same
+            // when that is fixed
+            self.tcx().evaluation_cache.insert((param_env, trait_pred), dep_node, result);
+            return;
         }
 
         debug!(?trait_pred, ?result, "insert_evaluation_cache");
@@ -1584,13 +1582,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         if self.can_use_global_caches(param_env) {
             if let Err(Overflow(OverflowError::Canonical)) = candidate {
                 // Don't cache overflow globally; we only produce this in certain modes.
-            } else if !pred.has_infer() {
-                if !candidate.has_infer() {
-                    debug!(?pred, ?candidate, "insert_candidate_cache global");
-                    // This may overwrite the cache with the same value.
-                    tcx.selection_cache.insert((param_env, pred), dep_node, candidate);
-                    return;
-                }
+            } else if !pred.has_infer() && !candidate.has_infer() {
+                debug!(?pred, ?candidate, "insert_candidate_cache global");
+                // This may overwrite the cache with the same value.
+                tcx.selection_cache.insert((param_env, pred), dep_node, candidate);
+                return;
             }
         }
 
@@ -1980,10 +1976,10 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 // impls have to be always applicable, meaning that the only allowed
                 // region constraints may be constraints also present on the default impl.
                 let tcx = self.tcx();
-                if other.evaluation.must_apply_modulo_regions() {
-                    if tcx.specializes((other_def, victim_def)) {
-                        return DropVictim::Yes;
-                    }
+                if other.evaluation.must_apply_modulo_regions()
+                    && tcx.specializes((other_def, victim_def))
+                {
+                    return DropVictim::Yes;
                 }
 
                 match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index e899284674c..6b24929467b 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -143,10 +143,8 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
         match origin {
             rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {}
             rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => {
-                if !in_assoc_ty {
-                    if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
-                        return;
-                    }
+                if !in_assoc_ty && !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
+                    return;
                 }
             }
         }
diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs
index 433c444e701..f30419c801f 100644
--- a/compiler/rustc_type_ir/src/elaborate.rs
+++ b/compiler/rustc_type_ir/src/elaborate.rs
@@ -237,7 +237,7 @@ pub fn supertrait_def_ids<I: Interner>(
     cx: I,
     trait_def_id: I::DefId,
 ) -> impl Iterator<Item = I::DefId> {
-    let mut set: HashSet<I::DefId> = HashSet::default();
+    let mut set = HashSet::default();
     let mut stack = vec![trait_def_id];
 
     set.insert(trait_def_id);
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index f2492ede4f5..8dec2133a45 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -137,6 +137,8 @@ pub trait Interner:
         f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R,
     ) -> R;
 
+    fn evaluation_is_concurrent(&self) -> bool;
+
     fn expand_abstract_consts<T: TypeFoldable<Self>>(self, t: T) -> T;
 
     type GenericsOf: GenericsOf<Self>;
@@ -404,4 +406,7 @@ impl<I: Interner> search_graph::Cx for I {
     ) -> R {
         I::with_global_cache(self, mode, f)
     }
+    fn evaluation_is_concurrent(&self) -> bool {
+        self.evaluation_is_concurrent()
+    }
 }
diff --git a/compiler/rustc_type_ir/src/search_graph/global_cache.rs b/compiler/rustc_type_ir/src/search_graph/global_cache.rs
index 47f7cefac6a..0ce927b58bb 100644
--- a/compiler/rustc_type_ir/src/search_graph/global_cache.rs
+++ b/compiler/rustc_type_ir/src/search_graph/global_cache.rs
@@ -44,22 +44,28 @@ impl<X: Cx> GlobalCache<X> {
         cx: X,
         input: X::Input,
 
-        result: X::Result,
+        origin_result: X::Result,
         dep_node: X::DepNodeIndex,
 
         additional_depth: usize,
         encountered_overflow: bool,
         nested_goals: NestedGoals<X>,
     ) {
-        let result = cx.mk_tracked(result, dep_node);
+        let result = cx.mk_tracked(origin_result, dep_node);
         let entry = self.map.entry(input).or_default();
         if encountered_overflow {
             let with_overflow = WithOverflow { nested_goals, result };
             let prev = entry.with_overflow.insert(additional_depth, with_overflow);
-            assert!(prev.is_none());
+            if let Some(prev) = &prev {
+                assert!(cx.evaluation_is_concurrent());
+                assert_eq!(cx.get_tracked(&prev.result), origin_result);
+            }
         } else {
             let prev = entry.success.replace(Success { additional_depth, nested_goals, result });
-            assert!(prev.is_none());
+            if let Some(prev) = &prev {
+                assert!(cx.evaluation_is_concurrent());
+                assert_eq!(cx.get_tracked(&prev.result), origin_result);
+            }
         }
     }
 
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index 418139c3aad..ac4d0795a92 100644
--- a/compiler/rustc_type_ir/src/search_graph/mod.rs
+++ b/compiler/rustc_type_ir/src/search_graph/mod.rs
@@ -53,6 +53,8 @@ pub trait Cx: Copy {
         mode: SolverMode,
         f: impl FnOnce(&mut GlobalCache<Self>) -> R,
     ) -> R;
+
+    fn evaluation_is_concurrent(&self) -> bool;
 }
 
 pub trait Delegate {