about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-02-15 07:14:46 +0000
committerGitHub <noreply@github.com>2025-02-15 07:14:46 +0000
commit487346680f6d78d29023d511a2ba71f8ff4d8d01 (patch)
tree6d0bd72ad374a7aa08ae07ae53b9e5a7a8c9adeb /compiler
parent17f218dcbef5aaa8cc0d0c3e3e4bd7d6fab82aea (diff)
parent03076f17b05e1c05816fd59c0c50dc1cf444d240 (diff)
downloadrust-487346680f6d78d29023d511a2ba71f8ff4d8d01.tar.gz
rust-487346680f6d78d29023d511a2ba71f8ff4d8d01.zip
Merge pull request #4194 from rust-lang/rustup-2025-02-15
Automatic Rustup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_abi/src/extern_abi.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs47
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/back/lto.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs26
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_llvm/messages.ftl3
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs37
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs27
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs781
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/mod.rs88
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs27
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs22
-rw-r--r--compiler/rustc_codegen_ssa/src/size_of_val.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs48
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs48
-rw-r--r--compiler/rustc_data_structures/src/owned_slice.rs15
-rw-r--r--compiler/rustc_data_structures/src/sync.rs43
-rw-r--r--compiler/rustc_data_structures/src/sync/freeze.rs4
-rw-r--r--compiler/rustc_data_structures/src/sync/worker_local.rs11
-rw-r--r--compiler/rustc_errors/src/emitter.rs25
-rw-r--r--compiler/rustc_errors/src/lib.rs30
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs8
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl6
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs45
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs88
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs28
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs42
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl8
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs35
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs106
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs33
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs48
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs95
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs7
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs83
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs5
-rw-r--r--compiler/rustc_middle/src/arena.rs1
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs15
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs6
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs98
-rw-r--r--compiler/rustc_middle/src/ty/context.rs45
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs3
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs24
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs12
-rw-r--r--compiler/rustc_mir_dataflow/src/drop_flag_effects.rs21
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/initialized.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs3
-rw-r--r--compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs2
-rw-r--r--compiler/rustc_mir_transform/src/add_subtyping_projections.rs3
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs5
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters.rs8
-rw-r--r--compiler/rustc_mir_transform/src/coverage/query.rs19
-rw-r--r--compiler/rustc_mir_transform/src/deref_separator.rs3
-rw-r--r--compiler/rustc_mir_transform/src/early_otherwise_branch.rs2
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs3
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drop.rs (renamed from compiler/rustc_mir_dataflow/src/elaborate_drops.rs)31
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs9
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs3
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/match_branches.rs2
-rw-r--r--compiler/rustc_mir_transform/src/patch.rs (renamed from compiler/rustc_middle/src/mir/patch.rs)46
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs3
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs8
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs3
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_enum_branching.rs3
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_prop.rs3
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs7
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs51
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/effect_goals.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs254
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs28
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs4
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs23
-rw-r--r--compiler/rustc_session/src/config.rs26
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/abi.rs1
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs6
-rw-r--r--compiler/rustc_target/src/json.rs1
-rw-r--r--compiler/rustc_target/src/spec/base/apple/mod.rs10
-rw-r--r--compiler/rustc_target/src/spec/base/cygwin.rs46
-rw-r--r--compiler/rustc_target/src/spec/base/mod.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs14
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_linux_android.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs14
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs5
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs24
-rw-r--r--compiler/rustc_target/src/target_features.rs8
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs128
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/select.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs4
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs2
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs12
-rw-r--r--compiler/rustc_type_ir/src/solve/inspect.rs2
130 files changed, 1903 insertions, 1240 deletions
diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs
index c29db522511..543c2f8ab12 100644
--- a/compiler/rustc_abi/src/extern_abi.rs
+++ b/compiler/rustc_abi/src/extern_abi.rs
@@ -195,7 +195,6 @@ impl ExternAbi {
         // * C and Cdecl obviously support varargs.
         // * C can be based on Aapcs, SysV64 or Win64, so they must support varargs.
         // * EfiApi is based on Win64 or C, so it also supports it.
-        // * System falls back to C for functions with varargs.
         //
         // * Stdcall does not, because it would be impossible for the callee to clean
         //   up the arguments. (callee doesn't know how many arguments are there)
@@ -204,7 +203,6 @@ impl ExternAbi {
         match self {
             Self::C { .. }
             | Self::Cdecl { .. }
-            | Self::System { .. }
             | Self::Aapcs { .. }
             | Self::Win64 { .. }
             | Self::SysV64 { .. }
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index b809b40a399..b7e2510e035 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -147,9 +147,7 @@ pub(crate) enum RegionErrorKind<'tcx> {
 pub(crate) struct ErrorConstraintInfo<'tcx> {
     // fr: outlived_fr
     pub(super) fr: RegionVid,
-    pub(super) fr_is_local: bool,
     pub(super) outlived_fr: RegionVid,
-    pub(super) outlived_fr_is_local: bool,
 
     // Category and span for best blame constraint
     pub(super) category: ConstraintCategory<'tcx>,
@@ -316,13 +314,16 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     let type_test_span = type_test.span;
 
                     if let Some(lower_bound_region) = lower_bound_region {
-                        let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
+                        let generic_ty = self.regioncx.name_regions(
+                            self.infcx.tcx,
+                            type_test.generic_kind.to_ty(self.infcx.tcx),
+                        );
                         let origin = RelateParamBound(type_test_span, generic_ty, None);
                         self.buffer_error(self.infcx.err_ctxt().construct_generic_bound_failure(
                             self.body.source.def_id().expect_local(),
                             type_test_span,
                             Some(origin),
-                            type_test.generic_kind,
+                            self.regioncx.name_regions(self.infcx.tcx, type_test.generic_kind),
                             lower_bound_region,
                         ));
                     } else {
@@ -468,14 +469,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             fr_is_local, outlived_fr_is_local, category
         );
 
-        let errci = ErrorConstraintInfo {
-            fr,
-            outlived_fr,
-            fr_is_local,
-            outlived_fr_is_local,
-            category,
-            span: cause.span,
-        };
+        let errci = ErrorConstraintInfo { fr, outlived_fr, category, span: cause.span };
 
         let mut diag = match (category, fr_is_local, outlived_fr_is_local) {
             (ConstraintCategory::Return(kind), true, false) if self.is_closure_fn_mut(fr) => {
@@ -677,11 +671,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 && self.regioncx.universal_regions().defining_ty.is_fn_def())
             || self.regioncx.universal_regions().defining_ty.is_const()
         {
-            return self.report_general_error(&ErrorConstraintInfo {
-                fr_is_local: true,
-                outlived_fr_is_local: false,
-                ..*errci
-            });
+            return self.report_general_error(errci);
         }
 
         let mut diag =
@@ -759,15 +749,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     /// ```
     #[allow(rustc::diagnostic_outside_of_impl)] // FIXME
     fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'infcx> {
-        let ErrorConstraintInfo {
-            fr,
-            fr_is_local,
-            outlived_fr,
-            outlived_fr_is_local,
-            span,
-            category,
-            ..
-        } = errci;
+        let ErrorConstraintInfo { fr, outlived_fr, span, category, .. } = errci;
 
         let mir_def_name = self.infcx.tcx.def_descr(self.mir_def_id().to_def_id());
 
@@ -786,19 +768,22 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let outlived_fr_name = self.give_region_a_name(*outlived_fr).unwrap();
         outlived_fr_name.highlight_region_name(&mut diag);
 
-        let err_category = match (category, outlived_fr_is_local, fr_is_local) {
-            (ConstraintCategory::Return(_), true, _) => LifetimeReturnCategoryErr::WrongReturn {
+        let err_category = if matches!(category, ConstraintCategory::Return(_))
+            && self.regioncx.universal_regions().is_local_free_region(*outlived_fr)
+        {
+            LifetimeReturnCategoryErr::WrongReturn {
                 span: *span,
                 mir_def_name,
                 outlived_fr_name,
                 fr_name: &fr_name,
-            },
-            _ => LifetimeReturnCategoryErr::ShortReturn {
+            }
+        } else {
+            LifetimeReturnCategoryErr::ShortReturn {
                 span: *span,
                 category_desc: category.description(),
                 free_region_name: &fr_name,
                 outlived_fr_name,
-            },
+            }
         };
 
         diag.subdiagnostic(err_category);
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index fdcd9caf4ac..756a2226753 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -65,11 +65,7 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call
             sess.dcx().fatal("C-cmse-nonsecure-entry call conv is not yet implemented");
         }
 
-        Conv::Msp430Intr
-        | Conv::PtxKernel
-        | Conv::GpuKernel
-        | Conv::AvrInterrupt
-        | Conv::AvrNonBlockingInterrupt => {
+        Conv::Msp430Intr | Conv::GpuKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => {
             unreachable!("tried to use {c:?} call conv which only exists on an unsupported target");
         }
     }
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index b0153419903..a3f43744875 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -289,7 +289,7 @@ fn build_isa(sess: &Session) -> Arc<dyn TargetIsa + 'static> {
             flags_builder.set("opt_level", "none").unwrap();
         }
         OptLevel::Less
-        | OptLevel::Default
+        | OptLevel::More
         | OptLevel::Size
         | OptLevel::SizeMin
         | OptLevel::Aggressive => {
diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs
index e419bd18099..cb4caec8c32 100644
--- a/compiler/rustc_codegen_gcc/src/back/lto.rs
+++ b/compiler/rustc_codegen_gcc/src/back/lto.rs
@@ -710,10 +710,6 @@ pub struct ThinBuffer {
     context: Arc<SyncContext>,
 }
 
-// TODO: check if this makes sense to make ThinBuffer Send and Sync.
-unsafe impl Send for ThinBuffer {}
-unsafe impl Sync for ThinBuffer {}
-
 impl ThinBuffer {
     pub(crate) fn new(context: &Arc<SyncContext>) -> Self {
         Self { context: Arc::clone(context) }
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 1c3d6cc899a..b8e37b60480 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -665,6 +665,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         a + b
     }
 
+    // TODO(antoyo): should we also override the `unchecked_` versions?
     fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
         self.gcc_sub(a, b)
     }
@@ -832,31 +833,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         set_rvalue_location(self, self.gcc_not(a))
     }
 
-    fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        set_rvalue_location(self, self.gcc_add(a, b))
-    }
-
-    fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        set_rvalue_location(self, self.gcc_add(a, b))
-    }
-
-    fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        set_rvalue_location(self, self.gcc_sub(a, b))
-    }
-
-    fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        // TODO(antoyo): should generate poison value?
-        set_rvalue_location(self, self.gcc_sub(a, b))
-    }
-
-    fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        set_rvalue_location(self, self.gcc_mul(a, b))
-    }
-
-    fn unchecked_umul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        set_rvalue_location(self, self.gcc_mul(a, b))
-    }
-
     fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
         // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
         set_rvalue_location(self, lhs + rhs)
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index ce88ac39021..6455bcec685 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -476,7 +476,7 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
         Some(level) => match level {
             OptLevel::No => OptimizationLevel::None,
             OptLevel::Less => OptimizationLevel::Limited,
-            OptLevel::Default => OptimizationLevel::Standard,
+            OptLevel::More => OptimizationLevel::Standard,
             OptLevel::Aggressive => OptimizationLevel::Aggressive,
             OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited,
         },
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index 9585848cbf0..399d7ffea8e 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -38,9 +38,6 @@ codegen_llvm_lto_proc_macro = lto cannot be used for `proc-macro` crate type wit
 codegen_llvm_mismatch_data_layout =
     data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}`
 
-codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
-codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
-
 codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
 codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}
 
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 13846c8ab4b..28f423efc21 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -687,7 +687,6 @@ impl llvm::CallConv {
             Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt,
             Conv::ArmAapcs => llvm::ArmAapcsCallConv,
             Conv::Msp430Intr => llvm::Msp430Intr,
-            Conv::PtxKernel => llvm::PtxKernel,
             Conv::X86Fastcall => llvm::X86FastcallCallConv,
             Conv::X86Intr => llvm::X86_Intr,
             Conv::X86Stdcall => llvm::X86StdcallCallConv,
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 3722d4350a2..be5673eddf9 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -286,7 +286,9 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                 InlineAsmArch::M68k => {
                     constraints.push("~{ccr}".to_string());
                 }
-                InlineAsmArch::CSKY => {}
+                InlineAsmArch::CSKY => {
+                    constraints.push("~{psr}".to_string());
+                }
             }
         }
         if !options.contains(InlineAsmOptions::NOMEM) {
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 58933a77e53..9fa10e96068 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -141,7 +141,7 @@ fn to_llvm_opt_settings(cfg: config::OptLevel) -> (llvm::CodeGenOptLevel, llvm::
     match cfg {
         No => (llvm::CodeGenOptLevel::None, llvm::CodeGenOptSizeNone),
         Less => (llvm::CodeGenOptLevel::Less, llvm::CodeGenOptSizeNone),
-        Default => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeNone),
+        More => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeNone),
         Aggressive => (llvm::CodeGenOptLevel::Aggressive, llvm::CodeGenOptSizeNone),
         Size => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeDefault),
         SizeMin => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeAggressive),
@@ -153,7 +153,7 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel
     match cfg {
         No => llvm::PassBuilderOptLevel::O0,
         Less => llvm::PassBuilderOptLevel::O1,
-        Default => llvm::PassBuilderOptLevel::O2,
+        More => llvm::PassBuilderOptLevel::O2,
         Aggressive => llvm::PassBuilderOptLevel::O3,
         Size => llvm::PassBuilderOptLevel::Os,
         SizeMin => llvm::PassBuilderOptLevel::Oz,
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index da093e5d54b..e10a4d63407 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -465,6 +465,37 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unchecked_umul(x, y) => LLVMBuildNUWMul,
     }
 
+    fn unchecked_suadd(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value {
+        unsafe {
+            let add = llvm::LLVMBuildAdd(self.llbuilder, a, b, UNNAMED);
+            if llvm::LLVMIsAInstruction(add).is_some() {
+                llvm::LLVMSetNUW(add, True);
+                llvm::LLVMSetNSW(add, True);
+            }
+            add
+        }
+    }
+    fn unchecked_susub(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value {
+        unsafe {
+            let sub = llvm::LLVMBuildSub(self.llbuilder, a, b, UNNAMED);
+            if llvm::LLVMIsAInstruction(sub).is_some() {
+                llvm::LLVMSetNUW(sub, True);
+                llvm::LLVMSetNSW(sub, True);
+            }
+            sub
+        }
+    }
+    fn unchecked_sumul(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value {
+        unsafe {
+            let mul = llvm::LLVMBuildMul(self.llbuilder, a, b, UNNAMED);
+            if llvm::LLVMIsAInstruction(mul).is_some() {
+                llvm::LLVMSetNUW(mul, True);
+                llvm::LLVMSetNSW(mul, True);
+            }
+            mul
+        }
+    }
+
     fn or_disjoint(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value {
         unsafe {
             let or = llvm::LLVMBuildOr(self.llbuilder, a, b, UNNAMED);
@@ -587,7 +618,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe {
             let alloca = llvm::LLVMBuildAlloca(bx.llbuilder, ty, UNNAMED);
             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
-            alloca
+            // Cast to default addrspace if necessary
+            llvm::LLVMBuildPointerCast(bx.llbuilder, alloca, self.cx().type_ptr(), UNNAMED)
         }
     }
 
@@ -596,7 +628,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             let alloca =
                 llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), size, UNNAMED);
             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
-            alloca
+            // Cast to default addrspace if necessary
+            llvm::LLVMBuildPointerCast(self.llbuilder, alloca, self.cx().type_ptr(), UNNAMED)
         }
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index 11824398f24..187d97c54c8 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -437,6 +437,12 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>(
         .source_info
         .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER));
 
+    let discr = discr_value.opt_single_val().map(|value| {
+        let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout);
+        let size = cx.size_of(tag_base_type);
+        cx.const_uint_big(cx.type_ix(size.bits()), value)
+    });
+
     unsafe {
         llvm::LLVMRustDIBuilderCreateVariantMemberType(
             DIB(cx),
@@ -448,7 +454,7 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>(
             enum_type_and_layout.size.bits(),
             enum_type_and_layout.align.abi.bits() as u32,
             Size::ZERO.bits(),
-            discr_value.opt_single_val().map(|value| cx.const_u128(value)),
+            discr,
             DIFlags::FlagZero,
             variant_member_info.variant_struct_type_di_node,
         )
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index f4c9491f758..97f49256165 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -131,8 +131,6 @@ pub enum LlvmError<'a> {
     LoadBitcode { name: CString },
     #[diag(codegen_llvm_write_thinlto_key)]
     WriteThinLtoKey { err: std::io::Error },
-    #[diag(codegen_llvm_multiple_source_dicompileunit)]
-    MultipleSourceDiCompileUnit,
     #[diag(codegen_llvm_prepare_thin_lto_module)]
     PrepareThinLtoModule,
     #[diag(codegen_llvm_parse_bitcode)]
@@ -155,9 +153,6 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for WithLlvmError<'_> {
             PrepareThinLtoContext => fluent::codegen_llvm_prepare_thin_lto_context_with_llvm_err,
             LoadBitcode { .. } => fluent::codegen_llvm_load_bitcode_with_llvm_err,
             WriteThinLtoKey { .. } => fluent::codegen_llvm_write_thinlto_key_with_llvm_err,
-            MultipleSourceDiCompileUnit => {
-                fluent::codegen_llvm_multiple_source_dicompileunit_with_llvm_err
-            }
             PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err,
             ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err,
             PrepareAutoDiff { .. } => fluent::codegen_llvm_prepare_autodiff_with_llvm_err,
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index bcb1cc72b56..e9e1b644f18 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -245,9 +245,6 @@ impl WriteBackendMethods for LlvmCodegenBackend {
     }
 }
 
-unsafe impl Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
-unsafe impl Sync for LlvmCodegenBackend {}
-
 impl LlvmCodegenBackend {
     pub fn new() -> Box<dyn CodegenBackend> {
         Box::new(LlvmCodegenBackend(()))
diff --git a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs
index 4dabde55e98..63b2b15c514 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs
@@ -26,7 +26,7 @@ impl ArchiveRO {
     ///
     /// If this archive is used with a mutable method, then an error will be
     /// raised.
-    pub fn open(dst: &Path) -> Result<ArchiveRO, String> {
+    pub(crate) fn open(dst: &Path) -> Result<ArchiveRO, String> {
         unsafe {
             let s = path_to_c_string(dst);
             let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| {
@@ -36,7 +36,7 @@ impl ArchiveRO {
         }
     }
 
-    pub fn iter(&self) -> Iter<'_> {
+    pub(crate) fn iter(&self) -> Iter<'_> {
         unsafe { Iter { raw: super::LLVMRustArchiveIteratorNew(self.raw) } }
     }
 }
@@ -71,7 +71,7 @@ impl<'a> Drop for Iter<'a> {
 }
 
 impl<'a> Child<'a> {
-    pub fn name(&self) -> Option<&'a str> {
+    pub(crate) fn name(&self) -> Option<&'a str> {
         unsafe {
             let mut name_len = 0;
             let name_ptr = super::LLVMRustArchiveChildName(self.raw, &mut name_len);
diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
index 92b0ce8ffe1..39bac13a968 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
@@ -1,4 +1,5 @@
 #![allow(non_camel_case_types)]
+#![expect(dead_code)]
 
 use libc::{c_char, c_uint};
 
@@ -8,23 +9,23 @@ use crate::llvm::Bool;
 #[link(name = "llvm-wrapper", kind = "static")]
 extern "C" {
     // Enzyme
-    pub fn LLVMRustHasMetadata(I: &Value, KindID: c_uint) -> bool;
-    pub fn LLVMRustEraseInstUntilInclusive(BB: &BasicBlock, I: &Value);
-    pub fn LLVMRustGetLastInstruction<'a>(BB: &BasicBlock) -> Option<&'a Value>;
-    pub fn LLVMRustDIGetInstMetadata(I: &Value) -> Option<&Metadata>;
-    pub fn LLVMRustEraseInstFromParent(V: &Value);
-    pub fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value;
-    pub fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool;
+    pub(crate) fn LLVMRustHasMetadata(I: &Value, KindID: c_uint) -> bool;
+    pub(crate) fn LLVMRustEraseInstUntilInclusive(BB: &BasicBlock, I: &Value);
+    pub(crate) fn LLVMRustGetLastInstruction<'a>(BB: &BasicBlock) -> Option<&'a Value>;
+    pub(crate) fn LLVMRustDIGetInstMetadata(I: &Value) -> Option<&Metadata>;
+    pub(crate) fn LLVMRustEraseInstFromParent(V: &Value);
+    pub(crate) fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value;
+    pub(crate) fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool;
 }
 
 extern "C" {
     // Enzyme
-    pub fn LLVMDumpModule(M: &Module);
-    pub fn LLVMDumpValue(V: &Value);
-    pub fn LLVMGetFunctionCallConv(F: &Value) -> c_uint;
-    pub fn LLVMGetReturnType(T: &Type) -> &Type;
-    pub fn LLVMGetParams(Fnc: &Value, parms: *mut &Value);
-    pub fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> Option<&Value>;
+    pub(crate) fn LLVMDumpModule(M: &Module);
+    pub(crate) fn LLVMDumpValue(V: &Value);
+    pub(crate) fn LLVMGetFunctionCallConv(F: &Value) -> c_uint;
+    pub(crate) fn LLVMGetReturnType(T: &Type) -> &Type;
+    pub(crate) fn LLVMGetParams(Fnc: &Value, parms: *mut &Value);
+    pub(crate) fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> Option<&Value>;
 }
 
 #[repr(C)]
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 441d144ce50..3b0187b9d37 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -160,7 +160,7 @@ pub enum Visibility {
 }
 
 impl Visibility {
-    pub fn from_generic(visibility: SymbolVisibility) -> Self {
+    pub(crate) fn from_generic(visibility: SymbolVisibility) -> Self {
         match visibility {
             SymbolVisibility::Hidden => Visibility::Hidden,
             SymbolVisibility::Protected => Visibility::Protected,
@@ -255,7 +255,7 @@ pub enum IntPredicate {
 }
 
 impl IntPredicate {
-    pub fn from_generic(intpre: rustc_codegen_ssa::common::IntPredicate) -> Self {
+    pub(crate) fn from_generic(intpre: rustc_codegen_ssa::common::IntPredicate) -> Self {
         use rustc_codegen_ssa::common::IntPredicate as Common;
         match intpre {
             Common::IntEQ => Self::IntEQ,
@@ -295,7 +295,7 @@ pub enum RealPredicate {
 }
 
 impl RealPredicate {
-    pub fn from_generic(realp: rustc_codegen_ssa::common::RealPredicate) -> Self {
+    pub(crate) fn from_generic(realp: rustc_codegen_ssa::common::RealPredicate) -> Self {
         use rustc_codegen_ssa::common::RealPredicate as Common;
         match realp {
             Common::RealPredicateFalse => Self::RealPredicateFalse,
@@ -344,7 +344,7 @@ pub enum TypeKind {
 }
 
 impl TypeKind {
-    pub fn to_generic(self) -> rustc_codegen_ssa::common::TypeKind {
+    pub(crate) fn to_generic(self) -> rustc_codegen_ssa::common::TypeKind {
         use rustc_codegen_ssa::common::TypeKind as Common;
         match self {
             Self::Void => Common::Void,
@@ -388,7 +388,7 @@ pub enum AtomicRmwBinOp {
 }
 
 impl AtomicRmwBinOp {
-    pub fn from_generic(op: rustc_codegen_ssa::common::AtomicRmwBinOp) -> Self {
+    pub(crate) fn from_generic(op: rustc_codegen_ssa::common::AtomicRmwBinOp) -> Self {
         use rustc_codegen_ssa::common::AtomicRmwBinOp as Common;
         match op {
             Common::AtomicXchg => Self::AtomicXchg,
@@ -422,7 +422,7 @@ pub enum AtomicOrdering {
 }
 
 impl AtomicOrdering {
-    pub fn from_generic(ao: rustc_codegen_ssa::common::AtomicOrdering) -> Self {
+    pub(crate) fn from_generic(ao: rustc_codegen_ssa::common::AtomicOrdering) -> Self {
         use rustc_codegen_ssa::common::AtomicOrdering as Common;
         match ao {
             Common::Unordered => Self::Unordered,
@@ -908,7 +908,7 @@ pub mod debuginfo {
     }
 
     impl DebugEmissionKind {
-        pub fn from_generic(kind: rustc_session::config::DebugInfo) -> Self {
+        pub(crate) fn from_generic(kind: rustc_session::config::DebugInfo) -> Self {
             // We should be setting LLVM's emission kind to `LineTablesOnly` if
             // we are compiling with "limited" debuginfo. However, some of the
             // existing tools relied on slightly more debuginfo being generated than
@@ -967,49 +967,55 @@ pub type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c
 
 unsafe extern "C" {
     // Create and destroy contexts.
-    pub fn LLVMContextDispose(C: &'static mut Context);
-    pub fn LLVMGetMDKindIDInContext(C: &Context, Name: *const c_char, SLen: c_uint) -> c_uint;
+    pub(crate) fn LLVMContextDispose(C: &'static mut Context);
+    pub(crate) fn LLVMGetMDKindIDInContext(
+        C: &Context,
+        Name: *const c_char,
+        SLen: c_uint,
+    ) -> c_uint;
 
     // Create modules.
-    pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: &Context) -> &Module;
-    pub fn LLVMGetModuleContext(M: &Module) -> &Context;
-    pub fn LLVMCloneModule(M: &Module) -> &Module;
+    pub(crate) fn LLVMModuleCreateWithNameInContext(
+        ModuleID: *const c_char,
+        C: &Context,
+    ) -> &Module;
+    pub(crate) fn LLVMCloneModule(M: &Module) -> &Module;
 
     /// Data layout. See Module::getDataLayout.
-    pub fn LLVMGetDataLayoutStr(M: &Module) -> *const c_char;
-    pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char);
+    pub(crate) fn LLVMGetDataLayoutStr(M: &Module) -> *const c_char;
+    pub(crate) fn LLVMSetDataLayout(M: &Module, Triple: *const c_char);
 
     /// See Module::setModuleInlineAsm.
-    pub fn LLVMAppendModuleInlineAsm(M: &Module, Asm: *const c_char, Len: size_t);
+    pub(crate) fn LLVMAppendModuleInlineAsm(M: &Module, Asm: *const c_char, Len: size_t);
 
     // Operations on integer types
-    pub fn LLVMInt1TypeInContext(C: &Context) -> &Type;
-    pub fn LLVMInt8TypeInContext(C: &Context) -> &Type;
-    pub fn LLVMInt16TypeInContext(C: &Context) -> &Type;
-    pub fn LLVMInt32TypeInContext(C: &Context) -> &Type;
-    pub fn LLVMInt64TypeInContext(C: &Context) -> &Type;
-    pub fn LLVMIntTypeInContext(C: &Context, NumBits: c_uint) -> &Type;
+    pub(crate) fn LLVMInt1TypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMInt8TypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMInt16TypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMInt32TypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMInt64TypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMIntTypeInContext(C: &Context, NumBits: c_uint) -> &Type;
 
-    pub fn LLVMGetIntTypeWidth(IntegerTy: &Type) -> c_uint;
+    pub(crate) fn LLVMGetIntTypeWidth(IntegerTy: &Type) -> c_uint;
 
     // Operations on real types
-    pub fn LLVMHalfTypeInContext(C: &Context) -> &Type;
-    pub fn LLVMFloatTypeInContext(C: &Context) -> &Type;
-    pub fn LLVMDoubleTypeInContext(C: &Context) -> &Type;
-    pub fn LLVMFP128TypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMHalfTypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMFloatTypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMDoubleTypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMFP128TypeInContext(C: &Context) -> &Type;
 
     // Operations on function types
-    pub fn LLVMFunctionType<'a>(
+    pub(crate) fn LLVMFunctionType<'a>(
         ReturnType: &'a Type,
         ParamTypes: *const &'a Type,
         ParamCount: c_uint,
         IsVarArg: Bool,
     ) -> &'a Type;
-    pub fn LLVMCountParamTypes(FunctionTy: &Type) -> c_uint;
-    pub fn LLVMGetParamTypes<'a>(FunctionTy: &'a Type, Dest: *mut &'a Type);
+    pub(crate) fn LLVMCountParamTypes(FunctionTy: &Type) -> c_uint;
+    pub(crate) fn LLVMGetParamTypes<'a>(FunctionTy: &'a Type, Dest: *mut &'a Type);
 
     // Operations on struct types
-    pub fn LLVMStructTypeInContext<'a>(
+    pub(crate) fn LLVMStructTypeInContext<'a>(
         C: &'a Context,
         ElementTypes: *const &'a Type,
         ElementCount: c_uint,
@@ -1017,111 +1023,123 @@ unsafe extern "C" {
     ) -> &'a Type;
 
     // Operations on array, pointer, and vector types (sequence types)
-    pub fn LLVMPointerTypeInContext(C: &Context, AddressSpace: c_uint) -> &Type;
-    pub fn LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type;
+    pub(crate) fn LLVMPointerTypeInContext(C: &Context, AddressSpace: c_uint) -> &Type;
+    pub(crate) fn LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type;
 
-    pub fn LLVMGetElementType(Ty: &Type) -> &Type;
-    pub fn LLVMGetVectorSize(VectorTy: &Type) -> c_uint;
+    pub(crate) fn LLVMGetElementType(Ty: &Type) -> &Type;
+    pub(crate) fn LLVMGetVectorSize(VectorTy: &Type) -> c_uint;
 
     // Operations on other types
-    pub fn LLVMVoidTypeInContext(C: &Context) -> &Type;
-    pub fn LLVMTokenTypeInContext(C: &Context) -> &Type;
-    pub fn LLVMMetadataTypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMVoidTypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMTokenTypeInContext(C: &Context) -> &Type;
+    pub(crate) fn LLVMMetadataTypeInContext(C: &Context) -> &Type;
 
     // Operations on all values
-    pub fn LLVMIsUndef(Val: &Value) -> Bool;
-    pub fn LLVMTypeOf(Val: &Value) -> &Type;
-    pub fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char;
-    pub fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);
-    pub fn LLVMReplaceAllUsesWith<'a>(OldVal: &'a Value, NewVal: &'a Value);
-    pub fn LLVMSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Node: &'a Value);
-    pub fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
-    pub fn LLVMValueAsMetadata(Node: &Value) -> &Metadata;
+    pub(crate) fn LLVMIsUndef(Val: &Value) -> Bool;
+    pub(crate) fn LLVMTypeOf(Val: &Value) -> &Type;
+    pub(crate) fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char;
+    pub(crate) fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);
+    pub(crate) fn LLVMReplaceAllUsesWith<'a>(OldVal: &'a Value, NewVal: &'a Value);
+    pub(crate) fn LLVMSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Node: &'a Value);
+    pub(crate) fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
+    pub(crate) fn LLVMValueAsMetadata(Node: &Value) -> &Metadata;
 
     // Operations on constants of any type
-    pub fn LLVMConstNull(Ty: &Type) -> &Value;
-    pub fn LLVMGetUndef(Ty: &Type) -> &Value;
-    pub fn LLVMGetPoison(Ty: &Type) -> &Value;
+    pub(crate) fn LLVMConstNull(Ty: &Type) -> &Value;
+    pub(crate) fn LLVMGetUndef(Ty: &Type) -> &Value;
+    pub(crate) fn LLVMGetPoison(Ty: &Type) -> &Value;
 
     // Operations on metadata
-    pub fn LLVMMDStringInContext2(C: &Context, Str: *const c_char, SLen: size_t) -> &Metadata;
-    pub fn LLVMMDNodeInContext2<'a>(
+    pub(crate) fn LLVMMDStringInContext2(
+        C: &Context,
+        Str: *const c_char,
+        SLen: size_t,
+    ) -> &Metadata;
+    pub(crate) fn LLVMMDNodeInContext2<'a>(
         C: &'a Context,
         Vals: *const &'a Metadata,
         Count: size_t,
     ) -> &'a Metadata;
-    pub fn LLVMAddNamedMetadataOperand<'a>(M: &'a Module, Name: *const c_char, Val: &'a Value);
+    pub(crate) fn LLVMAddNamedMetadataOperand<'a>(
+        M: &'a Module,
+        Name: *const c_char,
+        Val: &'a Value,
+    );
 
     // Operations on scalar constants
-    pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value;
-    pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value;
-    pub fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value;
+    pub(crate) fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value;
+    pub(crate) fn LLVMConstIntOfArbitraryPrecision(
+        IntTy: &Type,
+        Wn: c_uint,
+        Ws: *const u64,
+    ) -> &Value;
+    pub(crate) fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value;
 
     // Operations on composite constants
-    pub fn LLVMConstArray2<'a>(
+    pub(crate) fn LLVMConstArray2<'a>(
         ElementTy: &'a Type,
         ConstantVals: *const &'a Value,
         Length: u64,
     ) -> &'a Value;
-    pub fn LLVMArrayType2(ElementType: &Type, ElementCount: u64) -> &Type;
-    pub fn LLVMConstStringInContext2(
+    pub(crate) fn LLVMArrayType2(ElementType: &Type, ElementCount: u64) -> &Type;
+    pub(crate) fn LLVMConstStringInContext2(
         C: &Context,
         Str: *const c_char,
         Length: size_t,
         DontNullTerminate: Bool,
     ) -> &Value;
-    pub fn LLVMConstStructInContext<'a>(
+    pub(crate) fn LLVMConstStructInContext<'a>(
         C: &'a Context,
         ConstantVals: *const &'a Value,
         Count: c_uint,
         Packed: Bool,
     ) -> &'a Value;
-    pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value;
+    pub(crate) fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value;
 
     // Constant expressions
-    pub fn LLVMConstInBoundsGEP2<'a>(
+    pub(crate) fn LLVMConstInBoundsGEP2<'a>(
         ty: &'a Type,
         ConstantVal: &'a Value,
         ConstantIndices: *const &'a Value,
         NumIndices: c_uint,
     ) -> &'a Value;
-    pub fn LLVMConstPtrToInt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
-    pub fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
-    pub fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
-    pub fn LLVMConstPointerCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
-    pub fn LLVMGetAggregateElement(ConstantVal: &Value, Idx: c_uint) -> Option<&Value>;
-    pub fn LLVMGetConstOpcode(ConstantVal: &Value) -> Opcode;
-    pub fn LLVMIsAConstantExpr(Val: &Value) -> Option<&Value>;
+    pub(crate) fn LLVMConstPtrToInt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub(crate) fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub(crate) fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub(crate) fn LLVMConstPointerCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub(crate) fn LLVMGetAggregateElement(ConstantVal: &Value, Idx: c_uint) -> Option<&Value>;
+    pub(crate) fn LLVMGetConstOpcode(ConstantVal: &Value) -> Opcode;
+    pub(crate) fn LLVMIsAConstantExpr(Val: &Value) -> Option<&Value>;
 
     // Operations on global variables, functions, and aliases (globals)
-    pub fn LLVMIsDeclaration(Global: &Value) -> Bool;
-    pub fn LLVMGetLinkage(Global: &Value) -> RawEnum<Linkage>;
-    pub fn LLVMSetLinkage(Global: &Value, RustLinkage: Linkage);
-    pub fn LLVMSetSection(Global: &Value, Section: *const c_char);
-    pub fn LLVMGetVisibility(Global: &Value) -> RawEnum<Visibility>;
-    pub fn LLVMSetVisibility(Global: &Value, Viz: Visibility);
-    pub fn LLVMGetAlignment(Global: &Value) -> c_uint;
-    pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
-    pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass);
-    pub fn LLVMGlobalGetValueType(Global: &Value) -> &Type;
+    pub(crate) fn LLVMIsDeclaration(Global: &Value) -> Bool;
+    pub(crate) fn LLVMGetLinkage(Global: &Value) -> RawEnum<Linkage>;
+    pub(crate) fn LLVMSetLinkage(Global: &Value, RustLinkage: Linkage);
+    pub(crate) fn LLVMSetSection(Global: &Value, Section: *const c_char);
+    pub(crate) fn LLVMGetVisibility(Global: &Value) -> RawEnum<Visibility>;
+    pub(crate) fn LLVMSetVisibility(Global: &Value, Viz: Visibility);
+    pub(crate) fn LLVMGetAlignment(Global: &Value) -> c_uint;
+    pub(crate) fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
+    pub(crate) fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass);
+    pub(crate) fn LLVMGlobalGetValueType(Global: &Value) -> &Type;
 
     // Operations on global variables
-    pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
-    pub fn LLVMAddGlobal<'a>(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value;
-    pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>;
-    pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>;
-    pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>;
-    pub fn LLVMDeleteGlobal(GlobalVar: &Value);
-    pub fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>;
-    pub fn LLVMSetInitializer<'a>(GlobalVar: &'a Value, ConstantVal: &'a Value);
-    pub fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool;
-    pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
-    pub fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
-    pub fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
-    pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
+    pub(crate) fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
+    pub(crate) fn LLVMAddGlobal<'a>(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value;
+    pub(crate) fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>;
+    pub(crate) fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>;
+    pub(crate) fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>;
+    pub(crate) fn LLVMDeleteGlobal(GlobalVar: &Value);
+    pub(crate) fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>;
+    pub(crate) fn LLVMSetInitializer<'a>(GlobalVar: &'a Value, ConstantVal: &'a Value);
+    pub(crate) fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool;
+    pub(crate) fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
+    pub(crate) fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
+    pub(crate) fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
+    pub(crate) fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
 
     // Operations on attributes
-    pub fn LLVMCreateStringAttribute(
+    pub(crate) fn LLVMCreateStringAttribute(
         C: &Context,
         Name: *const c_char,
         NameLen: c_uint,
@@ -1130,34 +1148,34 @@ unsafe extern "C" {
     ) -> &Attribute;
 
     // Operations on functions
-    pub fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint);
+    pub(crate) fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint);
 
     // Operations on parameters
-    pub fn LLVMIsAArgument(Val: &Value) -> Option<&Value>;
-    pub fn LLVMCountParams(Fn: &Value) -> c_uint;
-    pub fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value;
+    pub(crate) fn LLVMIsAArgument(Val: &Value) -> Option<&Value>;
+    pub(crate) fn LLVMCountParams(Fn: &Value) -> c_uint;
+    pub(crate) fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value;
 
     // Operations on basic blocks
-    pub fn LLVMGetBasicBlockParent(BB: &BasicBlock) -> &Value;
-    pub fn LLVMAppendBasicBlockInContext<'a>(
+    pub(crate) fn LLVMGetBasicBlockParent(BB: &BasicBlock) -> &Value;
+    pub(crate) fn LLVMAppendBasicBlockInContext<'a>(
         C: &'a Context,
         Fn: &'a Value,
         Name: *const c_char,
     ) -> &'a BasicBlock;
 
     // Operations on instructions
-    pub fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>;
-    pub fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock;
-    pub fn LLVMGetOperand(Val: &Value, Index: c_uint) -> Option<&Value>;
+    pub(crate) fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>;
+    pub(crate) fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock;
+    pub(crate) fn LLVMGetOperand(Val: &Value, Index: c_uint) -> Option<&Value>;
 
     // Operations on call sites
-    pub fn LLVMSetInstructionCallConv(Instr: &Value, CC: c_uint);
+    pub(crate) fn LLVMSetInstructionCallConv(Instr: &Value, CC: c_uint);
 
     // Operations on load/store instructions (only)
-    pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool);
+    pub(crate) fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool);
 
     // Operations on phi nodes
-    pub fn LLVMAddIncoming<'a>(
+    pub(crate) fn LLVMAddIncoming<'a>(
         PhiNode: &'a Value,
         IncomingValues: *const &'a Value,
         IncomingBlocks: *const &'a BasicBlock,
@@ -1165,266 +1183,278 @@ unsafe extern "C" {
     );
 
     // Instruction builders
-    pub fn LLVMCreateBuilderInContext(C: &Context) -> &mut Builder<'_>;
-    pub fn LLVMPositionBuilderAtEnd<'a>(Builder: &Builder<'a>, Block: &'a BasicBlock);
-    pub fn LLVMGetInsertBlock<'a>(Builder: &Builder<'a>) -> &'a BasicBlock;
-    pub fn LLVMDisposeBuilder<'a>(Builder: &'a mut Builder<'a>);
+    pub(crate) fn LLVMCreateBuilderInContext(C: &Context) -> &mut Builder<'_>;
+    pub(crate) fn LLVMPositionBuilderAtEnd<'a>(Builder: &Builder<'a>, Block: &'a BasicBlock);
+    pub(crate) fn LLVMGetInsertBlock<'a>(Builder: &Builder<'a>) -> &'a BasicBlock;
+    pub(crate) fn LLVMDisposeBuilder<'a>(Builder: &'a mut Builder<'a>);
 
     // Metadata
-    pub fn LLVMSetCurrentDebugLocation2<'a>(Builder: &Builder<'a>, Loc: *const Metadata);
-    pub fn LLVMGetCurrentDebugLocation2<'a>(Builder: &Builder<'a>) -> Option<&'a Metadata>;
+    pub(crate) fn LLVMSetCurrentDebugLocation2<'a>(Builder: &Builder<'a>, Loc: *const Metadata);
+    pub(crate) fn LLVMGetCurrentDebugLocation2<'a>(Builder: &Builder<'a>) -> Option<&'a Metadata>;
 
     // Terminators
-    pub fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value;
-    pub fn LLVMBuildRet<'a>(B: &Builder<'a>, V: &'a Value) -> &'a Value;
-    pub fn LLVMBuildBr<'a>(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value;
-    pub fn LLVMBuildCondBr<'a>(
+    pub(crate) fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value;
+    pub(crate) fn LLVMBuildRet<'a>(B: &Builder<'a>, V: &'a Value) -> &'a Value;
+    pub(crate) fn LLVMBuildBr<'a>(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value;
+    pub(crate) fn LLVMBuildCondBr<'a>(
         B: &Builder<'a>,
         If: &'a Value,
         Then: &'a BasicBlock,
         Else: &'a BasicBlock,
     ) -> &'a Value;
-    pub fn LLVMBuildSwitch<'a>(
+    pub(crate) fn LLVMBuildSwitch<'a>(
         B: &Builder<'a>,
         V: &'a Value,
         Else: &'a BasicBlock,
         NumCases: c_uint,
     ) -> &'a Value;
-    pub fn LLVMBuildLandingPad<'a>(
+    pub(crate) fn LLVMBuildLandingPad<'a>(
         B: &Builder<'a>,
         Ty: &'a Type,
         PersFn: Option<&'a Value>,
         NumClauses: c_uint,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildResume<'a>(B: &Builder<'a>, Exn: &'a Value) -> &'a Value;
-    pub fn LLVMBuildUnreachable<'a>(B: &Builder<'a>) -> &'a Value;
+    pub(crate) fn LLVMBuildResume<'a>(B: &Builder<'a>, Exn: &'a Value) -> &'a Value;
+    pub(crate) fn LLVMBuildUnreachable<'a>(B: &Builder<'a>) -> &'a Value;
 
-    pub fn LLVMBuildCleanupPad<'a>(
+    pub(crate) fn LLVMBuildCleanupPad<'a>(
         B: &Builder<'a>,
         ParentPad: Option<&'a Value>,
         Args: *const &'a Value,
         NumArgs: c_uint,
         Name: *const c_char,
     ) -> Option<&'a Value>;
-    pub fn LLVMBuildCleanupRet<'a>(
+    pub(crate) fn LLVMBuildCleanupRet<'a>(
         B: &Builder<'a>,
         CleanupPad: &'a Value,
         BB: Option<&'a BasicBlock>,
     ) -> Option<&'a Value>;
-    pub fn LLVMBuildCatchPad<'a>(
+    pub(crate) fn LLVMBuildCatchPad<'a>(
         B: &Builder<'a>,
         ParentPad: &'a Value,
         Args: *const &'a Value,
         NumArgs: c_uint,
         Name: *const c_char,
     ) -> Option<&'a Value>;
-    pub fn LLVMBuildCatchRet<'a>(
+    pub(crate) fn LLVMBuildCatchRet<'a>(
         B: &Builder<'a>,
         CatchPad: &'a Value,
         BB: &'a BasicBlock,
     ) -> Option<&'a Value>;
-    pub fn LLVMBuildCatchSwitch<'a>(
+    pub(crate) fn LLVMBuildCatchSwitch<'a>(
         Builder: &Builder<'a>,
         ParentPad: Option<&'a Value>,
         UnwindBB: Option<&'a BasicBlock>,
         NumHandlers: c_uint,
         Name: *const c_char,
     ) -> Option<&'a Value>;
-    pub fn LLVMAddHandler<'a>(CatchSwitch: &'a Value, Dest: &'a BasicBlock);
-    pub fn LLVMSetPersonalityFn<'a>(Func: &'a Value, Pers: &'a Value);
+    pub(crate) fn LLVMAddHandler<'a>(CatchSwitch: &'a Value, Dest: &'a BasicBlock);
+    pub(crate) fn LLVMSetPersonalityFn<'a>(Func: &'a Value, Pers: &'a Value);
 
     // Add a case to the switch instruction
-    pub fn LLVMAddCase<'a>(Switch: &'a Value, OnVal: &'a Value, Dest: &'a BasicBlock);
+    pub(crate) fn LLVMAddCase<'a>(Switch: &'a Value, OnVal: &'a Value, Dest: &'a BasicBlock);
 
     // Add a clause to the landing pad instruction
-    pub fn LLVMAddClause<'a>(LandingPad: &'a Value, ClauseVal: &'a Value);
+    pub(crate) fn LLVMAddClause<'a>(LandingPad: &'a Value, ClauseVal: &'a Value);
 
     // Set the cleanup on a landing pad instruction
-    pub fn LLVMSetCleanup(LandingPad: &Value, Val: Bool);
+    pub(crate) fn LLVMSetCleanup(LandingPad: &Value, Val: Bool);
 
     // Arithmetic
-    pub fn LLVMBuildAdd<'a>(
+    pub(crate) fn LLVMBuildAdd<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildFAdd<'a>(
+    pub(crate) fn LLVMBuildFAdd<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildSub<'a>(
+    pub(crate) fn LLVMBuildSub<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildFSub<'a>(
+    pub(crate) fn LLVMBuildFSub<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildMul<'a>(
+    pub(crate) fn LLVMBuildMul<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildFMul<'a>(
+    pub(crate) fn LLVMBuildFMul<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildUDiv<'a>(
+    pub(crate) fn LLVMBuildUDiv<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildExactUDiv<'a>(
+    pub(crate) fn LLVMBuildExactUDiv<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildSDiv<'a>(
+    pub(crate) fn LLVMBuildSDiv<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildExactSDiv<'a>(
+    pub(crate) fn LLVMBuildExactSDiv<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildFDiv<'a>(
+    pub(crate) fn LLVMBuildFDiv<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildURem<'a>(
+    pub(crate) fn LLVMBuildURem<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildSRem<'a>(
+    pub(crate) fn LLVMBuildSRem<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildFRem<'a>(
+    pub(crate) fn LLVMBuildFRem<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildShl<'a>(
+    pub(crate) fn LLVMBuildShl<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildLShr<'a>(
+    pub(crate) fn LLVMBuildLShr<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildAShr<'a>(
+    pub(crate) fn LLVMBuildAShr<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildNSWAdd<'a>(
+    pub(crate) fn LLVMBuildNSWAdd<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildNUWAdd<'a>(
+    pub(crate) fn LLVMBuildNUWAdd<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildNSWSub<'a>(
+    pub(crate) fn LLVMBuildNSWSub<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildNUWSub<'a>(
+    pub(crate) fn LLVMBuildNUWSub<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildNSWMul<'a>(
+    pub(crate) fn LLVMBuildNSWMul<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildNUWMul<'a>(
+    pub(crate) fn LLVMBuildNUWMul<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildAnd<'a>(
+    pub(crate) fn LLVMBuildAnd<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildOr<'a>(
+    pub(crate) fn LLVMBuildOr<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildXor<'a>(
+    pub(crate) fn LLVMBuildXor<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
-    pub fn LLVMBuildFNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
-    pub fn LLVMBuildNot<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
+    pub(crate) fn LLVMBuildNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char)
+    -> &'a Value;
+    pub(crate) fn LLVMBuildFNeg<'a>(
+        B: &Builder<'a>,
+        V: &'a Value,
+        Name: *const c_char,
+    ) -> &'a Value;
+    pub(crate) fn LLVMBuildNot<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char)
+    -> &'a Value;
 
     // Extra flags on arithmetic
-    pub fn LLVMSetIsDisjoint(Instr: &Value, IsDisjoint: Bool);
+    pub(crate) fn LLVMSetIsDisjoint(Instr: &Value, IsDisjoint: Bool);
+    pub(crate) fn LLVMSetNUW(ArithInst: &Value, HasNUW: Bool);
+    pub(crate) fn LLVMSetNSW(ArithInst: &Value, HasNSW: Bool);
 
     // Memory
-    pub fn LLVMBuildAlloca<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value;
-    pub fn LLVMBuildArrayAlloca<'a>(
+    pub(crate) fn LLVMBuildAlloca<'a>(
+        B: &Builder<'a>,
+        Ty: &'a Type,
+        Name: *const c_char,
+    ) -> &'a Value;
+    pub(crate) fn LLVMBuildArrayAlloca<'a>(
         B: &Builder<'a>,
         Ty: &'a Type,
         Val: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildLoad2<'a>(
+    pub(crate) fn LLVMBuildLoad2<'a>(
         B: &Builder<'a>,
         Ty: &'a Type,
         PointerVal: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
 
-    pub fn LLVMBuildStore<'a>(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value;
+    pub(crate) fn LLVMBuildStore<'a>(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value;
 
-    pub fn LLVMBuildGEP2<'a>(
+    pub(crate) fn LLVMBuildGEP2<'a>(
         B: &Builder<'a>,
         Ty: &'a Type,
         Pointer: &'a Value,
@@ -1432,7 +1462,7 @@ unsafe extern "C" {
         NumIndices: c_uint,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildInBoundsGEP2<'a>(
+    pub(crate) fn LLVMBuildInBoundsGEP2<'a>(
         B: &Builder<'a>,
         Ty: &'a Type,
         Pointer: &'a Value,
@@ -1442,85 +1472,85 @@ unsafe extern "C" {
     ) -> &'a Value;
 
     // Casts
-    pub fn LLVMBuildTrunc<'a>(
+    pub(crate) fn LLVMBuildTrunc<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildZExt<'a>(
+    pub(crate) fn LLVMBuildZExt<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildSExt<'a>(
+    pub(crate) fn LLVMBuildSExt<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildFPToUI<'a>(
+    pub(crate) fn LLVMBuildFPToUI<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildFPToSI<'a>(
+    pub(crate) fn LLVMBuildFPToSI<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildUIToFP<'a>(
+    pub(crate) fn LLVMBuildUIToFP<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildSIToFP<'a>(
+    pub(crate) fn LLVMBuildSIToFP<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildFPTrunc<'a>(
+    pub(crate) fn LLVMBuildFPTrunc<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildFPExt<'a>(
+    pub(crate) fn LLVMBuildFPExt<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildPtrToInt<'a>(
+    pub(crate) fn LLVMBuildPtrToInt<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildIntToPtr<'a>(
+    pub(crate) fn LLVMBuildIntToPtr<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildBitCast<'a>(
+    pub(crate) fn LLVMBuildBitCast<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildPointerCast<'a>(
+    pub(crate) fn LLVMBuildPointerCast<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildIntCast2<'a>(
+    pub(crate) fn LLVMBuildIntCast2<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
@@ -1529,14 +1559,14 @@ unsafe extern "C" {
     ) -> &'a Value;
 
     // Comparisons
-    pub fn LLVMBuildICmp<'a>(
+    pub(crate) fn LLVMBuildICmp<'a>(
         B: &Builder<'a>,
         Op: c_uint,
         LHS: &'a Value,
         RHS: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildFCmp<'a>(
+    pub(crate) fn LLVMBuildFCmp<'a>(
         B: &Builder<'a>,
         Op: c_uint,
         LHS: &'a Value,
@@ -1545,47 +1575,48 @@ unsafe extern "C" {
     ) -> &'a Value;
 
     // Miscellaneous instructions
-    pub fn LLVMBuildPhi<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value;
-    pub fn LLVMBuildSelect<'a>(
+    pub(crate) fn LLVMBuildPhi<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char)
+    -> &'a Value;
+    pub(crate) fn LLVMBuildSelect<'a>(
         B: &Builder<'a>,
         If: &'a Value,
         Then: &'a Value,
         Else: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildVAArg<'a>(
+    pub(crate) fn LLVMBuildVAArg<'a>(
         B: &Builder<'a>,
         list: &'a Value,
         Ty: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildExtractElement<'a>(
+    pub(crate) fn LLVMBuildExtractElement<'a>(
         B: &Builder<'a>,
         VecVal: &'a Value,
         Index: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildInsertElement<'a>(
+    pub(crate) fn LLVMBuildInsertElement<'a>(
         B: &Builder<'a>,
         VecVal: &'a Value,
         EltVal: &'a Value,
         Index: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildShuffleVector<'a>(
+    pub(crate) fn LLVMBuildShuffleVector<'a>(
         B: &Builder<'a>,
         V1: &'a Value,
         V2: &'a Value,
         Mask: &'a Value,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildExtractValue<'a>(
+    pub(crate) fn LLVMBuildExtractValue<'a>(
         B: &Builder<'a>,
         AggVal: &'a Value,
         Index: c_uint,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMBuildInsertValue<'a>(
+    pub(crate) fn LLVMBuildInsertValue<'a>(
         B: &Builder<'a>,
         AggVal: &'a Value,
         EltVal: &'a Value,
@@ -1594,7 +1625,7 @@ unsafe extern "C" {
     ) -> &'a Value;
 
     // Atomic Operations
-    pub fn LLVMBuildAtomicCmpXchg<'a>(
+    pub(crate) fn LLVMBuildAtomicCmpXchg<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
         CMP: &'a Value,
@@ -1604,9 +1635,9 @@ unsafe extern "C" {
         SingleThreaded: Bool,
     ) -> &'a Value;
 
-    pub fn LLVMSetWeak(CmpXchgInst: &Value, IsWeak: Bool);
+    pub(crate) fn LLVMSetWeak(CmpXchgInst: &Value, IsWeak: Bool);
 
-    pub fn LLVMBuildAtomicRMW<'a>(
+    pub(crate) fn LLVMBuildAtomicRMW<'a>(
         B: &Builder<'a>,
         Op: AtomicRmwBinOp,
         LHS: &'a Value,
@@ -1615,7 +1646,7 @@ unsafe extern "C" {
         SingleThreaded: Bool,
     ) -> &'a Value;
 
-    pub fn LLVMBuildFence<'a>(
+    pub(crate) fn LLVMBuildFence<'a>(
         B: &Builder<'a>,
         Order: AtomicOrdering,
         SingleThreaded: Bool,
@@ -1623,36 +1654,36 @@ unsafe extern "C" {
     ) -> &'a Value;
 
     /// Writes a module to the specified path. Returns 0 on success.
-    pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int;
+    pub(crate) fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int;
 
     /// Creates a legacy pass manager -- only used for final codegen.
-    pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>;
+    pub(crate) fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>;
 
-    pub fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>);
+    pub(crate) fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>);
 
-    pub fn LLVMGetHostCPUFeatures() -> *mut c_char;
+    pub(crate) fn LLVMGetHostCPUFeatures() -> *mut c_char;
 
-    pub fn LLVMDisposeMessage(message: *mut c_char);
+    pub(crate) fn LLVMDisposeMessage(message: *mut c_char);
 
-    pub fn LLVMIsMultithreaded() -> Bool;
+    pub(crate) fn LLVMIsMultithreaded() -> Bool;
 
-    pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type;
+    pub(crate) fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type;
 
-    pub fn LLVMStructSetBody<'a>(
+    pub(crate) fn LLVMStructSetBody<'a>(
         StructTy: &'a Type,
         ElementTypes: *const &'a Type,
         ElementCount: c_uint,
         Packed: Bool,
     );
 
-    pub fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
+    pub(crate) fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
 
-    pub fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr);
+    pub(crate) fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr);
 
-    pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>;
+    pub(crate) fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>;
 
-    pub fn LLVMGetOrInsertComdat(M: &Module, Name: *const c_char) -> &Comdat;
-    pub fn LLVMSetComdat(V: &Value, C: &Comdat);
+    pub(crate) fn LLVMGetOrInsertComdat(M: &Module, Name: *const c_char) -> &Comdat;
+    pub(crate) fn LLVMSetComdat(V: &Value, C: &Comdat);
 
     pub(crate) fn LLVMCreateOperandBundle(
         Tag: *const c_char,
@@ -1745,22 +1776,26 @@ unsafe extern "C" {
 
 #[link(name = "llvm-wrapper", kind = "static")]
 unsafe extern "C" {
-    pub fn LLVMRustInstallErrorHandlers();
-    pub fn LLVMRustDisableSystemDialogsOnCrash();
+    pub(crate) fn LLVMRustInstallErrorHandlers();
+    pub(crate) fn LLVMRustDisableSystemDialogsOnCrash();
 
     // Create and destroy contexts.
-    pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context;
+    pub(crate) fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context;
 
     /// See llvm::LLVMTypeKind::getTypeID.
-    pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind;
+    pub(crate) fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind;
 
     // Operations on all values
-    pub fn LLVMRustGlobalAddMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
-    pub fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool;
+    pub(crate) fn LLVMRustGlobalAddMetadata<'a>(
+        Val: &'a Value,
+        KindID: c_uint,
+        Metadata: &'a Metadata,
+    );
+    pub(crate) fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool;
 
     // Operations on scalar constants
-    pub fn LLVMRustConstIntGetZExtValue(ConstantVal: &ConstantInt, Value: &mut u64) -> bool;
-    pub fn LLVMRustConstInt128Get(
+    pub(crate) fn LLVMRustConstIntGetZExtValue(ConstantVal: &ConstantInt, Value: &mut u64) -> bool;
+    pub(crate) fn LLVMRustConstInt128Get(
         ConstantVal: &ConstantInt,
         SExt: bool,
         high: &mut u64,
@@ -1768,35 +1803,38 @@ unsafe extern "C" {
     ) -> bool;
 
     // Operations on global variables, functions, and aliases (globals)
-    pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool);
+    pub(crate) fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool);
 
     // Operations on global variables
-    pub fn LLVMRustGetOrInsertGlobal<'a>(
+    pub(crate) fn LLVMRustGetOrInsertGlobal<'a>(
         M: &'a Module,
         Name: *const c_char,
         NameLen: size_t,
         T: &'a Type,
     ) -> &'a Value;
-    pub fn LLVMRustInsertPrivateGlobal<'a>(M: &'a Module, T: &'a Type) -> &'a Value;
-    pub fn LLVMRustGetNamedValue(
+    pub(crate) fn LLVMRustInsertPrivateGlobal<'a>(M: &'a Module, T: &'a Type) -> &'a Value;
+    pub(crate) fn LLVMRustGetNamedValue(
         M: &Module,
         Name: *const c_char,
         NameLen: size_t,
     ) -> Option<&Value>;
 
     // Operations on attributes
-    pub fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute;
-    pub fn LLVMRustCreateAlignmentAttr(C: &Context, bytes: u64) -> &Attribute;
-    pub fn LLVMRustCreateDereferenceableAttr(C: &Context, bytes: u64) -> &Attribute;
-    pub fn LLVMRustCreateDereferenceableOrNullAttr(C: &Context, bytes: u64) -> &Attribute;
-    pub fn LLVMRustCreateByValAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute;
-    pub fn LLVMRustCreateStructRetAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute;
-    pub fn LLVMRustCreateElementTypeAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute;
-    pub fn LLVMRustCreateUWTableAttr(C: &Context, async_: bool) -> &Attribute;
-    pub fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute;
-    pub fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute;
-    pub fn LLVMRustCreateMemoryEffectsAttr(C: &Context, effects: MemoryEffects) -> &Attribute;
-    pub fn LLVMRustCreateRangeAttribute(
+    pub(crate) fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute;
+    pub(crate) fn LLVMRustCreateAlignmentAttr(C: &Context, bytes: u64) -> &Attribute;
+    pub(crate) fn LLVMRustCreateDereferenceableAttr(C: &Context, bytes: u64) -> &Attribute;
+    pub(crate) fn LLVMRustCreateDereferenceableOrNullAttr(C: &Context, bytes: u64) -> &Attribute;
+    pub(crate) fn LLVMRustCreateByValAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute;
+    pub(crate) fn LLVMRustCreateStructRetAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute;
+    pub(crate) fn LLVMRustCreateElementTypeAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute;
+    pub(crate) fn LLVMRustCreateUWTableAttr(C: &Context, async_: bool) -> &Attribute;
+    pub(crate) fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute;
+    pub(crate) fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute;
+    pub(crate) fn LLVMRustCreateMemoryEffectsAttr(
+        C: &Context,
+        effects: MemoryEffects,
+    ) -> &Attribute;
+    pub(crate) fn LLVMRustCreateRangeAttribute(
         C: &Context,
         num_bits: c_uint,
         lower_words: *const u64,
@@ -1804,13 +1842,13 @@ unsafe extern "C" {
     ) -> &Attribute;
 
     // Operations on functions
-    pub fn LLVMRustGetOrInsertFunction<'a>(
+    pub(crate) fn LLVMRustGetOrInsertFunction<'a>(
         M: &'a Module,
         Name: *const c_char,
         NameLen: size_t,
         FunctionTy: &'a Type,
     ) -> &'a Value;
-    pub fn LLVMRustAddFunctionAttributes<'a>(
+    pub(crate) fn LLVMRustAddFunctionAttributes<'a>(
         Fn: &'a Value,
         index: c_uint,
         Attrs: *const &'a Attribute,
@@ -1818,19 +1856,19 @@ unsafe extern "C" {
     );
 
     // Operations on call sites
-    pub fn LLVMRustAddCallSiteAttributes<'a>(
+    pub(crate) fn LLVMRustAddCallSiteAttributes<'a>(
         Instr: &'a Value,
         index: c_uint,
         Attrs: *const &'a Attribute,
         AttrsLen: size_t,
     );
 
-    pub fn LLVMRustSetFastMath(Instr: &Value);
-    pub fn LLVMRustSetAlgebraicMath(Instr: &Value);
-    pub fn LLVMRustSetAllowReassoc(Instr: &Value);
+    pub(crate) fn LLVMRustSetFastMath(Instr: &Value);
+    pub(crate) fn LLVMRustSetAlgebraicMath(Instr: &Value);
+    pub(crate) fn LLVMRustSetAllowReassoc(Instr: &Value);
 
     // Miscellaneous instructions
-    pub fn LLVMRustBuildMemCpy<'a>(
+    pub(crate) fn LLVMRustBuildMemCpy<'a>(
         B: &Builder<'a>,
         Dst: &'a Value,
         DstAlign: c_uint,
@@ -1839,7 +1877,7 @@ unsafe extern "C" {
         Size: &'a Value,
         IsVolatile: bool,
     ) -> &'a Value;
-    pub fn LLVMRustBuildMemMove<'a>(
+    pub(crate) fn LLVMRustBuildMemMove<'a>(
         B: &Builder<'a>,
         Dst: &'a Value,
         DstAlign: c_uint,
@@ -1848,7 +1886,7 @@ unsafe extern "C" {
         Size: &'a Value,
         IsVolatile: bool,
     ) -> &'a Value;
-    pub fn LLVMRustBuildMemSet<'a>(
+    pub(crate) fn LLVMRustBuildMemSet<'a>(
         B: &Builder<'a>,
         Dst: &'a Value,
         DstAlign: c_uint,
@@ -1857,47 +1895,55 @@ unsafe extern "C" {
         IsVolatile: bool,
     ) -> &'a Value;
 
-    pub fn LLVMRustBuildVectorReduceFAdd<'a>(
+    pub(crate) fn LLVMRustBuildVectorReduceFAdd<'a>(
         B: &Builder<'a>,
         Acc: &'a Value,
         Src: &'a Value,
     ) -> &'a Value;
-    pub fn LLVMRustBuildVectorReduceFMul<'a>(
+    pub(crate) fn LLVMRustBuildVectorReduceFMul<'a>(
         B: &Builder<'a>,
         Acc: &'a Value,
         Src: &'a Value,
     ) -> &'a Value;
-    pub fn LLVMRustBuildVectorReduceAdd<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
-    pub fn LLVMRustBuildVectorReduceMul<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
-    pub fn LLVMRustBuildVectorReduceAnd<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
-    pub fn LLVMRustBuildVectorReduceOr<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
-    pub fn LLVMRustBuildVectorReduceXor<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
-    pub fn LLVMRustBuildVectorReduceMin<'a>(
+    pub(crate) fn LLVMRustBuildVectorReduceAdd<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
+    pub(crate) fn LLVMRustBuildVectorReduceMul<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
+    pub(crate) fn LLVMRustBuildVectorReduceAnd<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
+    pub(crate) fn LLVMRustBuildVectorReduceOr<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
+    pub(crate) fn LLVMRustBuildVectorReduceXor<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
+    pub(crate) fn LLVMRustBuildVectorReduceMin<'a>(
         B: &Builder<'a>,
         Src: &'a Value,
         IsSigned: bool,
     ) -> &'a Value;
-    pub fn LLVMRustBuildVectorReduceMax<'a>(
+    pub(crate) fn LLVMRustBuildVectorReduceMax<'a>(
         B: &Builder<'a>,
         Src: &'a Value,
         IsSigned: bool,
     ) -> &'a Value;
-    pub fn LLVMRustBuildVectorReduceFMin<'a>(
+    pub(crate) fn LLVMRustBuildVectorReduceFMin<'a>(
         B: &Builder<'a>,
         Src: &'a Value,
         IsNaN: bool,
     ) -> &'a Value;
-    pub fn LLVMRustBuildVectorReduceFMax<'a>(
+    pub(crate) fn LLVMRustBuildVectorReduceFMax<'a>(
         B: &Builder<'a>,
         Src: &'a Value,
         IsNaN: bool,
     ) -> &'a Value;
 
-    pub fn LLVMRustBuildMinNum<'a>(B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value) -> &'a Value;
-    pub fn LLVMRustBuildMaxNum<'a>(B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value) -> &'a Value;
+    pub(crate) fn LLVMRustBuildMinNum<'a>(
+        B: &Builder<'a>,
+        LHS: &'a Value,
+        LHS: &'a Value,
+    ) -> &'a Value;
+    pub(crate) fn LLVMRustBuildMaxNum<'a>(
+        B: &Builder<'a>,
+        LHS: &'a Value,
+        LHS: &'a Value,
+    ) -> &'a Value;
 
     // Atomic Operations
-    pub fn LLVMRustBuildAtomicLoad<'a>(
+    pub(crate) fn LLVMRustBuildAtomicLoad<'a>(
         B: &Builder<'a>,
         ElementType: &'a Type,
         PointerVal: &'a Value,
@@ -1905,21 +1951,21 @@ unsafe extern "C" {
         Order: AtomicOrdering,
     ) -> &'a Value;
 
-    pub fn LLVMRustBuildAtomicStore<'a>(
+    pub(crate) fn LLVMRustBuildAtomicStore<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         Ptr: &'a Value,
         Order: AtomicOrdering,
     ) -> &'a Value;
 
-    pub fn LLVMRustTimeTraceProfilerInitialize();
+    pub(crate) fn LLVMRustTimeTraceProfilerInitialize();
 
-    pub fn LLVMRustTimeTraceProfilerFinishThread();
+    pub(crate) fn LLVMRustTimeTraceProfilerFinishThread();
 
-    pub fn LLVMRustTimeTraceProfilerFinish(FileName: *const c_char);
+    pub(crate) fn LLVMRustTimeTraceProfilerFinish(FileName: *const c_char);
 
     /// Returns a string describing the last error caused by an LLVMRust* call.
-    pub fn LLVMRustGetLastError() -> *const c_char;
+    pub(crate) fn LLVMRustGetLastError() -> *const c_char;
 
     /// Prints the timing information collected by `-Ztime-llvm-passes`.
     pub(crate) fn LLVMRustPrintPassTimings(OutStr: &RustString);
@@ -1928,7 +1974,7 @@ unsafe extern "C" {
     pub(crate) fn LLVMRustPrintStatistics(OutStr: &RustString);
 
     /// Prepares inline assembly.
-    pub fn LLVMRustInlineAsm(
+    pub(crate) fn LLVMRustInlineAsm(
         Ty: &Type,
         AsmString: *const c_char,
         AsmStringLen: size_t,
@@ -1939,7 +1985,7 @@ unsafe extern "C" {
         Dialect: AsmDialect,
         CanThrow: Bool,
     ) -> &Value;
-    pub fn LLVMRustInlineAsmVerify(
+    pub(crate) fn LLVMRustInlineAsmVerify(
         Ty: &Type,
         Constraints: *const c_char,
         ConstraintsLen: size_t,
@@ -1983,16 +2029,16 @@ unsafe extern "C" {
     pub(crate) fn LLVMRustCoverageWriteCovmapVarNameToString(OutStr: &RustString);
 
     pub(crate) fn LLVMRustCoverageMappingVersion() -> u32;
-    pub fn LLVMRustDebugMetadataVersion() -> u32;
-    pub fn LLVMRustVersionMajor() -> u32;
-    pub fn LLVMRustVersionMinor() -> u32;
-    pub fn LLVMRustVersionPatch() -> u32;
+    pub(crate) fn LLVMRustDebugMetadataVersion() -> u32;
+    pub(crate) fn LLVMRustVersionMajor() -> u32;
+    pub(crate) fn LLVMRustVersionMinor() -> u32;
+    pub(crate) fn LLVMRustVersionPatch() -> u32;
 
     /// Add LLVM module flags.
     ///
     /// In order for Rust-C LTO to work, module flags must be compatible with Clang. What
     /// "compatible" means depends on the merge behaviors involved.
-    pub fn LLVMRustAddModuleFlagU32(
+    pub(crate) fn LLVMRustAddModuleFlagU32(
         M: &Module,
         MergeBehavior: ModuleFlagMergeBehavior,
         Name: *const c_char,
@@ -2000,7 +2046,7 @@ unsafe extern "C" {
         Value: u32,
     );
 
-    pub fn LLVMRustAddModuleFlagString(
+    pub(crate) fn LLVMRustAddModuleFlagString(
         M: &Module,
         MergeBehavior: ModuleFlagMergeBehavior,
         Name: *const c_char,
@@ -2009,7 +2055,7 @@ unsafe extern "C" {
         ValueLen: size_t,
     );
 
-    pub fn LLVMRustDIBuilderCreateCompileUnit<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateCompileUnit<'a>(
         Builder: &DIBuilder<'a>,
         Lang: c_uint,
         File: &'a DIFile,
@@ -2026,7 +2072,7 @@ unsafe extern "C" {
         DebugNameTableKind: DebugNameTableKind,
     ) -> &'a DIDescriptor;
 
-    pub fn LLVMRustDIBuilderCreateFile<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateFile<'a>(
         Builder: &DIBuilder<'a>,
         Filename: *const c_char,
         FilenameLen: size_t,
@@ -2039,12 +2085,12 @@ unsafe extern "C" {
         SourceLen: size_t,
     ) -> &'a DIFile;
 
-    pub fn LLVMRustDIBuilderCreateSubroutineType<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateSubroutineType<'a>(
         Builder: &DIBuilder<'a>,
         ParameterTypes: &'a DIArray,
     ) -> &'a DICompositeType;
 
-    pub fn LLVMRustDIBuilderCreateFunction<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateFunction<'a>(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIDescriptor,
         Name: *const c_char,
@@ -2062,7 +2108,7 @@ unsafe extern "C" {
         Decl: Option<&'a DIDescriptor>,
     ) -> &'a DISubprogram;
 
-    pub fn LLVMRustDIBuilderCreateMethod<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateMethod<'a>(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIDescriptor,
         Name: *const c_char,
@@ -2077,7 +2123,7 @@ unsafe extern "C" {
         TParam: &'a DIArray,
     ) -> &'a DISubprogram;
 
-    pub fn LLVMRustDIBuilderCreateBasicType<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateBasicType<'a>(
         Builder: &DIBuilder<'a>,
         Name: *const c_char,
         NameLen: size_t,
@@ -2085,7 +2131,7 @@ unsafe extern "C" {
         Encoding: c_uint,
     ) -> &'a DIBasicType;
 
-    pub fn LLVMRustDIBuilderCreateTypedef<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateTypedef<'a>(
         Builder: &DIBuilder<'a>,
         Type: &'a DIBasicType,
         Name: *const c_char,
@@ -2095,7 +2141,7 @@ unsafe extern "C" {
         Scope: Option<&'a DIScope>,
     ) -> &'a DIDerivedType;
 
-    pub fn LLVMRustDIBuilderCreatePointerType<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreatePointerType<'a>(
         Builder: &DIBuilder<'a>,
         PointeeTy: &'a DIType,
         SizeInBits: u64,
@@ -2105,7 +2151,7 @@ unsafe extern "C" {
         NameLen: size_t,
     ) -> &'a DIDerivedType;
 
-    pub fn LLVMRustDIBuilderCreateStructType<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateStructType<'a>(
         Builder: &DIBuilder<'a>,
         Scope: Option<&'a DIDescriptor>,
         Name: *const c_char,
@@ -2123,7 +2169,7 @@ unsafe extern "C" {
         UniqueIdLen: size_t,
     ) -> &'a DICompositeType;
 
-    pub fn LLVMRustDIBuilderCreateMemberType<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateMemberType<'a>(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIDescriptor,
         Name: *const c_char,
@@ -2137,7 +2183,7 @@ unsafe extern "C" {
         Ty: &'a DIType,
     ) -> &'a DIDerivedType;
 
-    pub fn LLVMRustDIBuilderCreateVariantMemberType<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateVariantMemberType<'a>(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIScope,
         Name: *const c_char,
@@ -2152,7 +2198,7 @@ unsafe extern "C" {
         Ty: &'a DIType,
     ) -> &'a DIType;
 
-    pub fn LLVMRustDIBuilderCreateStaticMemberType<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateStaticMemberType<'a>(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIDescriptor,
         Name: *const c_char,
@@ -2165,13 +2211,13 @@ unsafe extern "C" {
         AlignInBits: u32,
     ) -> &'a DIDerivedType;
 
-    pub fn LLVMRustDIBuilderCreateQualifiedType<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateQualifiedType<'a>(
         Builder: &DIBuilder<'a>,
         Tag: c_uint,
         Type: &'a DIType,
     ) -> &'a DIDerivedType;
 
-    pub fn LLVMRustDIBuilderCreateStaticVariable<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateStaticVariable<'a>(
         Builder: &DIBuilder<'a>,
         Context: Option<&'a DIScope>,
         Name: *const c_char,
@@ -2187,7 +2233,7 @@ unsafe extern "C" {
         AlignInBits: u32,
     ) -> &'a DIGlobalVariableExpression;
 
-    pub fn LLVMRustDIBuilderCreateVariable<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateVariable<'a>(
         Builder: &DIBuilder<'a>,
         Tag: c_uint,
         Scope: &'a DIDescriptor,
@@ -2202,7 +2248,7 @@ unsafe extern "C" {
         AlignInBits: u32,
     ) -> &'a DIVariable;
 
-    pub fn LLVMRustDIBuilderCreateArrayType<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateArrayType<'a>(
         Builder: &DIBuilder<'a>,
         Size: u64,
         AlignInBits: u32,
@@ -2210,19 +2256,19 @@ unsafe extern "C" {
         Subscripts: &'a DIArray,
     ) -> &'a DIType;
 
-    pub fn LLVMRustDIBuilderGetOrCreateSubrange<'a>(
+    pub(crate) fn LLVMRustDIBuilderGetOrCreateSubrange<'a>(
         Builder: &DIBuilder<'a>,
         Lo: i64,
         Count: i64,
     ) -> &'a DISubrange;
 
-    pub fn LLVMRustDIBuilderGetOrCreateArray<'a>(
+    pub(crate) fn LLVMRustDIBuilderGetOrCreateArray<'a>(
         Builder: &DIBuilder<'a>,
         Ptr: *const Option<&'a DIDescriptor>,
         Count: c_uint,
     ) -> &'a DIArray;
 
-    pub fn LLVMRustDIBuilderInsertDeclareAtEnd<'a>(
+    pub(crate) fn LLVMRustDIBuilderInsertDeclareAtEnd<'a>(
         Builder: &DIBuilder<'a>,
         Val: &'a Value,
         VarInfo: &'a DIVariable,
@@ -2232,7 +2278,7 @@ unsafe extern "C" {
         InsertAtEnd: &'a BasicBlock,
     );
 
-    pub fn LLVMRustDIBuilderCreateEnumerator<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateEnumerator<'a>(
         Builder: &DIBuilder<'a>,
         Name: *const c_char,
         NameLen: size_t,
@@ -2241,7 +2287,7 @@ unsafe extern "C" {
         IsUnsigned: bool,
     ) -> &'a DIEnumerator;
 
-    pub fn LLVMRustDIBuilderCreateEnumerationType<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateEnumerationType<'a>(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIScope,
         Name: *const c_char,
@@ -2255,7 +2301,7 @@ unsafe extern "C" {
         IsScoped: bool,
     ) -> &'a DIType;
 
-    pub fn LLVMRustDIBuilderCreateUnionType<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateUnionType<'a>(
         Builder: &DIBuilder<'a>,
         Scope: Option<&'a DIScope>,
         Name: *const c_char,
@@ -2271,7 +2317,7 @@ unsafe extern "C" {
         UniqueIdLen: size_t,
     ) -> &'a DIType;
 
-    pub fn LLVMRustDIBuilderCreateVariantPart<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateVariantPart<'a>(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIScope,
         Name: *const c_char,
@@ -2287,7 +2333,7 @@ unsafe extern "C" {
         UniqueIdLen: size_t,
     ) -> &'a DIDerivedType;
 
-    pub fn LLVMRustDIBuilderCreateTemplateTypeParameter<'a>(
+    pub(crate) fn LLVMRustDIBuilderCreateTemplateTypeParameter<'a>(
         Builder: &DIBuilder<'a>,
         Scope: Option<&'a DIScope>,
         Name: *const c_char,
@@ -2295,37 +2341,37 @@ unsafe extern "C" {
         Ty: &'a DIType,
     ) -> &'a DITemplateTypeParameter;
 
-    pub fn LLVMRustDICompositeTypeReplaceArrays<'a>(
+    pub(crate) fn LLVMRustDICompositeTypeReplaceArrays<'a>(
         Builder: &DIBuilder<'a>,
         CompositeType: &'a DIType,
         Elements: Option<&'a DIArray>,
         Params: Option<&'a DIArray>,
     );
 
-    pub fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>(
+    pub(crate) fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>(
         Location: &'a DILocation,
         BD: c_uint,
     ) -> Option<&'a DILocation>;
 
-    pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString);
-    pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString);
+    pub(crate) fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString);
+    pub(crate) fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString);
 
-    pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
+    pub(crate) fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
 
     pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString);
-    pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t;
-    pub fn LLVMRustGetTargetFeature(
+    pub(crate) fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t;
+    pub(crate) fn LLVMRustGetTargetFeature(
         T: &TargetMachine,
         Index: size_t,
         Feature: &mut *const c_char,
         Desc: &mut *const c_char,
     );
 
-    pub fn LLVMRustGetHostCPUName(LenOut: &mut size_t) -> *const u8;
+    pub(crate) fn LLVMRustGetHostCPUName(LenOut: &mut size_t) -> *const u8;
 
     // This function makes copies of pointed to data, so the data's lifetime may end after this
     // function returns.
-    pub fn LLVMRustCreateTargetMachine(
+    pub(crate) fn LLVMRustCreateTargetMachine(
         Triple: *const c_char,
         CPU: *const c_char,
         Features: *const c_char,
@@ -2351,13 +2397,13 @@ unsafe extern "C" {
         ArgsCstrBuffLen: usize,
     ) -> *mut TargetMachine;
 
-    pub fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);
-    pub fn LLVMRustAddLibraryInfo<'a>(
+    pub(crate) fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);
+    pub(crate) fn LLVMRustAddLibraryInfo<'a>(
         PM: &PassManager<'a>,
         M: &'a Module,
         DisableSimplifyLibCalls: bool,
     );
-    pub fn LLVMRustWriteOutputFile<'a>(
+    pub(crate) fn LLVMRustWriteOutputFile<'a>(
         T: &'a TargetMachine,
         PM: *mut PassManager<'a>,
         M: &'a Module,
@@ -2366,7 +2412,7 @@ unsafe extern "C" {
         FileType: FileType,
         VerifyIR: bool,
     ) -> LLVMRustResult;
-    pub fn LLVMRustOptimize<'a>(
+    pub(crate) fn LLVMRustOptimize<'a>(
         M: &'a Module,
         TM: &'a TargetMachine,
         OptLevel: PassBuilderOptLevel,
@@ -2398,29 +2444,32 @@ unsafe extern "C" {
         LLVMPlugins: *const c_char,
         LLVMPluginsLen: size_t,
     ) -> LLVMRustResult;
-    pub fn LLVMRustPrintModule(
+    pub(crate) fn LLVMRustPrintModule(
         M: &Module,
         Output: *const c_char,
         Demangle: extern "C" fn(*const c_char, size_t, *mut c_char, size_t) -> size_t,
     ) -> LLVMRustResult;
-    pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
-    pub fn LLVMRustPrintPasses();
-    pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char);
-    pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t);
-
-    pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>;
-    pub fn LLVMRustArchiveIteratorNew(AR: &Archive) -> &mut ArchiveIterator<'_>;
-    pub fn LLVMRustArchiveIteratorNext<'a>(
+    pub(crate) fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
+    pub(crate) fn LLVMRustPrintPasses();
+    pub(crate) fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char);
+    pub(crate) fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t);
+
+    pub(crate) fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>;
+    pub(crate) fn LLVMRustArchiveIteratorNew(AR: &Archive) -> &mut ArchiveIterator<'_>;
+    pub(crate) fn LLVMRustArchiveIteratorNext<'a>(
         AIR: &ArchiveIterator<'a>,
     ) -> Option<&'a mut ArchiveChild<'a>>;
-    pub fn LLVMRustArchiveChildName(ACR: &ArchiveChild<'_>, size: &mut size_t) -> *const c_char;
-    pub fn LLVMRustArchiveChildFree<'a>(ACR: &'a mut ArchiveChild<'a>);
-    pub fn LLVMRustArchiveIteratorFree<'a>(AIR: &'a mut ArchiveIterator<'a>);
-    pub fn LLVMRustDestroyArchive(AR: &'static mut Archive);
+    pub(crate) fn LLVMRustArchiveChildName(
+        ACR: &ArchiveChild<'_>,
+        size: &mut size_t,
+    ) -> *const c_char;
+    pub(crate) fn LLVMRustArchiveChildFree<'a>(ACR: &'a mut ArchiveChild<'a>);
+    pub(crate) fn LLVMRustArchiveIteratorFree<'a>(AIR: &'a mut ArchiveIterator<'a>);
+    pub(crate) fn LLVMRustDestroyArchive(AR: &'static mut Archive);
 
-    pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
+    pub(crate) fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
 
-    pub fn LLVMRustUnpackOptimizationDiagnostic<'a>(
+    pub(crate) fn LLVMRustUnpackOptimizationDiagnostic<'a>(
         DI: &'a DiagnosticInfo,
         pass_name_out: &RustString,
         function_out: &mut Option<&'a Value>,
@@ -2430,22 +2479,22 @@ unsafe extern "C" {
         message_out: &RustString,
     );
 
-    pub fn LLVMRustUnpackInlineAsmDiagnostic<'a>(
+    pub(crate) fn LLVMRustUnpackInlineAsmDiagnostic<'a>(
         DI: &'a DiagnosticInfo,
         level_out: &mut DiagnosticLevel,
         cookie_out: &mut u64,
         message_out: &mut Option<&'a Twine>,
     );
 
-    pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString);
-    pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind;
+    pub(crate) fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString);
+    pub(crate) fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind;
 
-    pub fn LLVMRustGetSMDiagnostic<'a>(
+    pub(crate) fn LLVMRustGetSMDiagnostic<'a>(
         DI: &'a DiagnosticInfo,
         cookie_out: &mut u64,
     ) -> &'a SMDiagnostic;
 
-    pub fn LLVMRustUnpackSMDiagnostic(
+    pub(crate) fn LLVMRustUnpackSMDiagnostic(
         d: &SMDiagnostic,
         message_out: &RustString,
         buffer_out: &RustString,
@@ -2455,7 +2504,7 @@ unsafe extern "C" {
         num_ranges: &mut usize,
     ) -> bool;
 
-    pub fn LLVMRustWriteArchive(
+    pub(crate) fn LLVMRustWriteArchive(
         Dst: *const c_char,
         NumMembers: size_t,
         Members: *const &RustArchiveMember<'_>,
@@ -2463,63 +2512,63 @@ unsafe extern "C" {
         Kind: ArchiveKind,
         isEC: bool,
     ) -> LLVMRustResult;
-    pub fn LLVMRustArchiveMemberNew<'a>(
+    pub(crate) fn LLVMRustArchiveMemberNew<'a>(
         Filename: *const c_char,
         Name: *const c_char,
         Child: Option<&ArchiveChild<'a>>,
     ) -> &'a mut RustArchiveMember<'a>;
-    pub fn LLVMRustArchiveMemberFree<'a>(Member: &'a mut RustArchiveMember<'a>);
+    pub(crate) fn LLVMRustArchiveMemberFree<'a>(Member: &'a mut RustArchiveMember<'a>);
 
-    pub fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine);
+    pub(crate) fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine);
 
-    pub fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock);
+    pub(crate) fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock);
 
-    pub fn LLVMRustSetModulePICLevel(M: &Module);
-    pub fn LLVMRustSetModulePIELevel(M: &Module);
-    pub fn LLVMRustSetModuleCodeModel(M: &Module, Model: CodeModel);
-    pub fn LLVMRustModuleBufferCreate(M: &Module) -> &'static mut ModuleBuffer;
-    pub fn LLVMRustModuleBufferPtr(p: &ModuleBuffer) -> *const u8;
-    pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize;
-    pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer);
-    pub fn LLVMRustModuleCost(M: &Module) -> u64;
-    pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString);
+    pub(crate) fn LLVMRustSetModulePICLevel(M: &Module);
+    pub(crate) fn LLVMRustSetModulePIELevel(M: &Module);
+    pub(crate) fn LLVMRustSetModuleCodeModel(M: &Module, Model: CodeModel);
+    pub(crate) fn LLVMRustModuleBufferCreate(M: &Module) -> &'static mut ModuleBuffer;
+    pub(crate) fn LLVMRustModuleBufferPtr(p: &ModuleBuffer) -> *const u8;
+    pub(crate) fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize;
+    pub(crate) fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer);
+    pub(crate) fn LLVMRustModuleCost(M: &Module) -> u64;
+    pub(crate) fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString);
 
-    pub fn LLVMRustThinLTOBufferCreate(
+    pub(crate) fn LLVMRustThinLTOBufferCreate(
         M: &Module,
         is_thin: bool,
         emit_summary: bool,
     ) -> &'static mut ThinLTOBuffer;
-    pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
-    pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char;
-    pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t;
-    pub fn LLVMRustThinLTOBufferThinLinkDataPtr(M: &ThinLTOBuffer) -> *const c_char;
-    pub fn LLVMRustThinLTOBufferThinLinkDataLen(M: &ThinLTOBuffer) -> size_t;
-    pub fn LLVMRustCreateThinLTOData(
+    pub(crate) fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
+    pub(crate) fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char;
+    pub(crate) fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t;
+    pub(crate) fn LLVMRustThinLTOBufferThinLinkDataPtr(M: &ThinLTOBuffer) -> *const c_char;
+    pub(crate) fn LLVMRustThinLTOBufferThinLinkDataLen(M: &ThinLTOBuffer) -> size_t;
+    pub(crate) fn LLVMRustCreateThinLTOData(
         Modules: *const ThinLTOModule,
         NumModules: size_t,
         PreservedSymbols: *const *const c_char,
         PreservedSymbolsLen: size_t,
     ) -> Option<&'static mut ThinLTOData>;
-    pub fn LLVMRustPrepareThinLTORename(
+    pub(crate) fn LLVMRustPrepareThinLTORename(
         Data: &ThinLTOData,
         Module: &Module,
         Target: &TargetMachine,
     );
-    pub fn LLVMRustPrepareThinLTOResolveWeak(Data: &ThinLTOData, Module: &Module) -> bool;
-    pub fn LLVMRustPrepareThinLTOInternalize(Data: &ThinLTOData, Module: &Module) -> bool;
-    pub fn LLVMRustPrepareThinLTOImport(
+    pub(crate) fn LLVMRustPrepareThinLTOResolveWeak(Data: &ThinLTOData, Module: &Module) -> bool;
+    pub(crate) fn LLVMRustPrepareThinLTOInternalize(Data: &ThinLTOData, Module: &Module) -> bool;
+    pub(crate) fn LLVMRustPrepareThinLTOImport(
         Data: &ThinLTOData,
         Module: &Module,
         Target: &TargetMachine,
     ) -> bool;
-    pub fn LLVMRustFreeThinLTOData(Data: &'static mut ThinLTOData);
-    pub fn LLVMRustParseBitcodeForLTO(
+    pub(crate) fn LLVMRustFreeThinLTOData(Data: &'static mut ThinLTOData);
+    pub(crate) fn LLVMRustParseBitcodeForLTO(
         Context: &Context,
         Data: *const u8,
         len: usize,
         Identifier: *const c_char,
     ) -> Option<&Module>;
-    pub fn LLVMRustGetSliceFromObjectDataByName(
+    pub(crate) fn LLVMRustGetSliceFromObjectDataByName(
         data: *const u8,
         len: usize,
         name: *const u8,
@@ -2527,25 +2576,27 @@ unsafe extern "C" {
         out_len: &mut usize,
     ) -> *const u8;
 
-    pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>;
-    pub fn LLVMRustLinkerAdd(
+    pub(crate) fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>;
+    pub(crate) fn LLVMRustLinkerAdd(
         linker: &Linker<'_>,
         bytecode: *const c_char,
         bytecode_len: usize,
     ) -> bool;
-    pub fn LLVMRustLinkerFree<'a>(linker: &'a mut Linker<'a>);
-    pub fn LLVMRustComputeLTOCacheKey(
+    pub(crate) fn LLVMRustLinkerFree<'a>(linker: &'a mut Linker<'a>);
+    pub(crate) fn LLVMRustComputeLTOCacheKey(
         key_out: &RustString,
         mod_id: *const c_char,
         data: &ThinLTOData,
     );
 
-    pub fn LLVMRustContextGetDiagnosticHandler(Context: &Context) -> Option<&DiagnosticHandler>;
-    pub fn LLVMRustContextSetDiagnosticHandler(
+    pub(crate) fn LLVMRustContextGetDiagnosticHandler(
+        Context: &Context,
+    ) -> Option<&DiagnosticHandler>;
+    pub(crate) fn LLVMRustContextSetDiagnosticHandler(
         context: &Context,
         diagnostic_handler: Option<&DiagnosticHandler>,
     );
-    pub fn LLVMRustContextConfigureDiagnosticHandler(
+    pub(crate) fn LLVMRustContextConfigureDiagnosticHandler(
         context: &Context,
         diagnostic_handler_callback: DiagnosticHandlerTy,
         diagnostic_handler_context: *mut c_void,
@@ -2556,15 +2607,15 @@ unsafe extern "C" {
         pgo_available: bool,
     );
 
-    pub fn LLVMRustGetMangledName(V: &Value, out: &RustString);
+    pub(crate) fn LLVMRustGetMangledName(V: &Value, out: &RustString);
 
-    pub fn LLVMRustGetElementTypeArgIndex(CallSite: &Value) -> i32;
+    pub(crate) fn LLVMRustGetElementTypeArgIndex(CallSite: &Value) -> i32;
 
-    pub fn LLVMRustLLVMHasZlibCompressionForDebugSymbols() -> bool;
+    pub(crate) fn LLVMRustLLVMHasZlibCompressionForDebugSymbols() -> bool;
 
-    pub fn LLVMRustLLVMHasZstdCompressionForDebugSymbols() -> bool;
+    pub(crate) fn LLVMRustLLVMHasZstdCompressionForDebugSymbols() -> bool;
 
-    pub fn LLVMRustGetSymbols(
+    pub(crate) fn LLVMRustGetSymbols(
         buf_ptr: *const u8,
         buf_len: usize,
         state: *mut c_void,
@@ -2572,10 +2623,10 @@ unsafe extern "C" {
         error_callback: GetSymbolsErrorCallback,
     ) -> *mut c_void;
 
-    pub fn LLVMRustIs64BitSymbolicFile(buf_ptr: *const u8, buf_len: usize) -> bool;
+    pub(crate) fn LLVMRustIs64BitSymbolicFile(buf_ptr: *const u8, buf_len: usize) -> bool;
 
-    pub fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool;
+    pub(crate) fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool;
 
-    pub fn LLVMRustSetNoSanitizeAddress(Global: &Value);
-    pub fn LLVMRustSetNoSanitizeHWAddress(Global: &Value);
+    pub(crate) fn LLVMRustSetNoSanitizeAddress(Global: &Value);
+    pub(crate) fn LLVMRustSetNoSanitizeHWAddress(Global: &Value);
 }
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index 7becba4ccd4..efc9cf2ef69 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -24,7 +24,7 @@ mod ffi;
 pub use self::enzyme_ffi::*;
 
 impl LLVMRustResult {
-    pub fn into_result(self) -> Result<(), ()> {
+    pub(crate) fn into_result(self) -> Result<(), ()> {
         match self {
             LLVMRustResult::Success => Ok(()),
             LLVMRustResult::Failure => Err(()),
@@ -32,13 +32,17 @@ impl LLVMRustResult {
     }
 }
 
-pub fn AddFunctionAttributes<'ll>(llfn: &'ll Value, idx: AttributePlace, attrs: &[&'ll Attribute]) {
+pub(crate) fn AddFunctionAttributes<'ll>(
+    llfn: &'ll Value,
+    idx: AttributePlace,
+    attrs: &[&'ll Attribute],
+) {
     unsafe {
         LLVMRustAddFunctionAttributes(llfn, idx.as_uint(), attrs.as_ptr(), attrs.len());
     }
 }
 
-pub fn AddCallSiteAttributes<'ll>(
+pub(crate) fn AddCallSiteAttributes<'ll>(
     callsite: &'ll Value,
     idx: AttributePlace,
     attrs: &[&'ll Attribute],
@@ -48,7 +52,11 @@ pub fn AddCallSiteAttributes<'ll>(
     }
 }
 
-pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &str, value: &str) -> &'ll Attribute {
+pub(crate) fn CreateAttrStringValue<'ll>(
+    llcx: &'ll Context,
+    attr: &str,
+    value: &str,
+) -> &'ll Attribute {
     unsafe {
         LLVMCreateStringAttribute(
             llcx,
@@ -60,7 +68,7 @@ pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &str, value: &str) -
     }
 }
 
-pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute {
+pub(crate) fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute {
     unsafe {
         LLVMCreateStringAttribute(
             llcx,
@@ -72,39 +80,39 @@ pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute {
     }
 }
 
-pub fn CreateAlignmentAttr(llcx: &Context, bytes: u64) -> &Attribute {
+pub(crate) fn CreateAlignmentAttr(llcx: &Context, bytes: u64) -> &Attribute {
     unsafe { LLVMRustCreateAlignmentAttr(llcx, bytes) }
 }
 
-pub fn CreateDereferenceableAttr(llcx: &Context, bytes: u64) -> &Attribute {
+pub(crate) fn CreateDereferenceableAttr(llcx: &Context, bytes: u64) -> &Attribute {
     unsafe { LLVMRustCreateDereferenceableAttr(llcx, bytes) }
 }
 
-pub fn CreateDereferenceableOrNullAttr(llcx: &Context, bytes: u64) -> &Attribute {
+pub(crate) fn CreateDereferenceableOrNullAttr(llcx: &Context, bytes: u64) -> &Attribute {
     unsafe { LLVMRustCreateDereferenceableOrNullAttr(llcx, bytes) }
 }
 
-pub fn CreateByValAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
+pub(crate) fn CreateByValAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
     unsafe { LLVMRustCreateByValAttr(llcx, ty) }
 }
 
-pub fn CreateStructRetAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
+pub(crate) fn CreateStructRetAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute {
     unsafe { LLVMRustCreateStructRetAttr(llcx, ty) }
 }
 
-pub fn CreateUWTableAttr(llcx: &Context, async_: bool) -> &Attribute {
+pub(crate) fn CreateUWTableAttr(llcx: &Context, async_: bool) -> &Attribute {
     unsafe { LLVMRustCreateUWTableAttr(llcx, async_) }
 }
 
-pub fn CreateAllocSizeAttr(llcx: &Context, size_arg: u32) -> &Attribute {
+pub(crate) fn CreateAllocSizeAttr(llcx: &Context, size_arg: u32) -> &Attribute {
     unsafe { LLVMRustCreateAllocSizeAttr(llcx, size_arg) }
 }
 
-pub fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &Attribute {
+pub(crate) fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &Attribute {
     unsafe { LLVMRustCreateAllocKindAttr(llcx, kind_arg.bits()) }
 }
 
-pub fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) -> &Attribute {
+pub(crate) fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) -> &Attribute {
     let lower = range.start;
     let upper = range.end.wrapping_add(1);
     let lower_words = [lower as u64, (lower >> 64) as u64];
@@ -127,7 +135,7 @@ pub enum AttributePlace {
 }
 
 impl AttributePlace {
-    pub fn as_uint(self) -> c_uint {
+    pub(crate) fn as_uint(self) -> c_uint {
         match self {
             AttributePlace::ReturnValue => 0,
             AttributePlace::Argument(i) => 1 + i,
@@ -159,12 +167,12 @@ impl FromStr for ArchiveKind {
     }
 }
 
-pub fn SetInstructionCallConv(instr: &Value, cc: CallConv) {
+pub(crate) fn SetInstructionCallConv(instr: &Value, cc: CallConv) {
     unsafe {
         LLVMSetInstructionCallConv(instr, cc as c_uint);
     }
 }
-pub fn SetFunctionCallConv(fn_: &Value, cc: CallConv) {
+pub(crate) fn SetFunctionCallConv(fn_: &Value, cc: CallConv) {
     unsafe {
         LLVMSetFunctionCallConv(fn_, cc as c_uint);
     }
@@ -176,20 +184,20 @@ pub fn SetFunctionCallConv(fn_: &Value, cc: CallConv) {
 // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
 // function.
 // For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52
-pub fn SetUniqueComdat(llmod: &Module, val: &Value) {
+pub(crate) fn SetUniqueComdat(llmod: &Module, val: &Value) {
     let name_buf = get_value_name(val).to_vec();
     let name =
         CString::from_vec_with_nul(name_buf).or_else(|buf| CString::new(buf.into_bytes())).unwrap();
     set_comdat(llmod, val, &name);
 }
 
-pub fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) {
+pub(crate) fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) {
     unsafe {
         LLVMSetUnnamedAddress(global, unnamed);
     }
 }
 
-pub fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
+pub(crate) fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
     unsafe {
         LLVMSetThreadLocalMode(global, mode);
     }
@@ -197,65 +205,65 @@ pub fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
 
 impl AttributeKind {
     /// Create an LLVM Attribute with no associated value.
-    pub fn create_attr(self, llcx: &Context) -> &Attribute {
+    pub(crate) fn create_attr(self, llcx: &Context) -> &Attribute {
         unsafe { LLVMRustCreateAttrNoValue(llcx, self) }
     }
 }
 
 impl MemoryEffects {
     /// Create an LLVM Attribute with these memory effects.
-    pub fn create_attr(self, llcx: &Context) -> &Attribute {
+    pub(crate) fn create_attr(self, llcx: &Context) -> &Attribute {
         unsafe { LLVMRustCreateMemoryEffectsAttr(llcx, self) }
     }
 }
 
-pub fn set_section(llglobal: &Value, section_name: &CStr) {
+pub(crate) fn set_section(llglobal: &Value, section_name: &CStr) {
     unsafe {
         LLVMSetSection(llglobal, section_name.as_ptr());
     }
 }
 
-pub fn add_global<'a>(llmod: &'a Module, ty: &'a Type, name_cstr: &CStr) -> &'a Value {
+pub(crate) fn add_global<'a>(llmod: &'a Module, ty: &'a Type, name_cstr: &CStr) -> &'a Value {
     unsafe { LLVMAddGlobal(llmod, ty, name_cstr.as_ptr()) }
 }
 
-pub fn set_initializer(llglobal: &Value, constant_val: &Value) {
+pub(crate) fn set_initializer(llglobal: &Value, constant_val: &Value) {
     unsafe {
         LLVMSetInitializer(llglobal, constant_val);
     }
 }
 
-pub fn set_global_constant(llglobal: &Value, is_constant: bool) {
+pub(crate) fn set_global_constant(llglobal: &Value, is_constant: bool) {
     unsafe {
         LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
     }
 }
 
-pub fn get_linkage(llglobal: &Value) -> Linkage {
+pub(crate) fn get_linkage(llglobal: &Value) -> Linkage {
     unsafe { LLVMGetLinkage(llglobal) }.to_rust()
 }
 
-pub fn set_linkage(llglobal: &Value, linkage: Linkage) {
+pub(crate) fn set_linkage(llglobal: &Value, linkage: Linkage) {
     unsafe {
         LLVMSetLinkage(llglobal, linkage);
     }
 }
 
-pub fn is_declaration(llglobal: &Value) -> bool {
+pub(crate) fn is_declaration(llglobal: &Value) -> bool {
     unsafe { LLVMIsDeclaration(llglobal) == ffi::True }
 }
 
-pub fn get_visibility(llglobal: &Value) -> Visibility {
+pub(crate) fn get_visibility(llglobal: &Value) -> Visibility {
     unsafe { LLVMGetVisibility(llglobal) }.to_rust()
 }
 
-pub fn set_visibility(llglobal: &Value, visibility: Visibility) {
+pub(crate) fn set_visibility(llglobal: &Value, visibility: Visibility) {
     unsafe {
         LLVMSetVisibility(llglobal, visibility);
     }
 }
 
-pub fn set_alignment(llglobal: &Value, align: Align) {
+pub(crate) fn set_alignment(llglobal: &Value, align: Align) {
     unsafe {
         ffi::LLVMSetAlignment(llglobal, align.bytes() as c_uint);
     }
@@ -265,7 +273,7 @@ pub fn set_alignment(llglobal: &Value, align: Align) {
 ///
 /// Inserts the comdat into `llmod` if it does not exist.
 /// It is an error to call this if the target does not support comdat.
-pub fn set_comdat(llmod: &Module, llglobal: &Value, name: &CStr) {
+pub(crate) fn set_comdat(llmod: &Module, llglobal: &Value, name: &CStr) {
     unsafe {
         let comdat = LLVMGetOrInsertComdat(llmod, name.as_ptr());
         LLVMSetComdat(llglobal, comdat);
@@ -273,7 +281,7 @@ pub fn set_comdat(llmod: &Module, llglobal: &Value, name: &CStr) {
 }
 
 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
-pub fn get_param(llfn: &Value, index: c_uint) -> &Value {
+pub(crate) fn get_param(llfn: &Value, index: c_uint) -> &Value {
     unsafe {
         assert!(
             index < LLVMCountParams(llfn),
@@ -286,7 +294,7 @@ pub fn get_param(llfn: &Value, index: c_uint) -> &Value {
 }
 
 /// Safe wrapper for `LLVMGetValueName2` into a byte slice
-pub fn get_value_name(value: &Value) -> &[u8] {
+pub(crate) fn get_value_name(value: &Value) -> &[u8] {
     unsafe {
         let mut len = 0;
         let data = LLVMGetValueName2(value, &mut len);
@@ -295,28 +303,28 @@ pub fn get_value_name(value: &Value) -> &[u8] {
 }
 
 /// Safe wrapper for `LLVMSetValueName2` from a byte slice
-pub fn set_value_name(value: &Value, name: &[u8]) {
+pub(crate) fn set_value_name(value: &Value, name: &[u8]) {
     unsafe {
         let data = name.as_c_char_ptr();
         LLVMSetValueName2(value, data, name.len());
     }
 }
 
-pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
+pub(crate) fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
     String::from_utf8(RustString::build_byte_buffer(f))
 }
 
-pub fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec<u8> {
+pub(crate) fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec<u8> {
     RustString::build_byte_buffer(f)
 }
 
-pub fn twine_to_string(tr: &Twine) -> String {
+pub(crate) fn twine_to_string(tr: &Twine) -> String {
     unsafe {
         build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
     }
 }
 
-pub fn last_error() -> Option<String> {
+pub(crate) fn last_error() -> Option<String> {
     unsafe {
         let cstr = LLVMRustGetLastError();
         if cstr.is_null() {
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 8fb831471a9..05d6ff35751 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -410,7 +410,7 @@ impl<'a> GccLinker<'a> {
         let opt_level = match self.sess.opts.optimize {
             config::OptLevel::No => "O0",
             config::OptLevel::Less => "O1",
-            config::OptLevel::Default | config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
+            config::OptLevel::More | config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
             config::OptLevel::Aggressive => "O3",
         };
 
@@ -685,7 +685,7 @@ impl<'a> Linker for GccLinker<'a> {
 
         // GNU-style linkers support optimization with -O. GNU ld doesn't
         // need a numeric argument, but other linkers do.
-        if self.sess.opts.optimize == config::OptLevel::Default
+        if self.sess.opts.optimize == config::OptLevel::More
             || self.sess.opts.optimize == config::OptLevel::Aggressive
         {
             self.link_arg("-O1");
@@ -1213,7 +1213,7 @@ impl<'a> Linker for EmLinker<'a> {
         self.cc_arg(match self.sess.opts.optimize {
             OptLevel::No => "-O0",
             OptLevel::Less => "-O1",
-            OptLevel::Default => "-O2",
+            OptLevel::More => "-O2",
             OptLevel::Aggressive => "-O3",
             OptLevel::Size => "-Os",
             OptLevel::SizeMin => "-Oz",
@@ -1384,7 +1384,7 @@ impl<'a> Linker for WasmLd<'a> {
         self.link_arg(match self.sess.opts.optimize {
             OptLevel::No => "-O0",
             OptLevel::Less => "-O1",
-            OptLevel::Default => "-O2",
+            OptLevel::More => "-O2",
             OptLevel::Aggressive => "-O3",
             // Currently LLD doesn't support `Os` and `Oz`, so pass through `O2`
             // instead.
@@ -1451,7 +1451,7 @@ impl<'a> WasmLd<'a> {
         let opt_level = match self.sess.opts.optimize {
             config::OptLevel::No => "O0",
             config::OptLevel::Less => "O1",
-            config::OptLevel::Default => "O2",
+            config::OptLevel::More => "O2",
             config::OptLevel::Aggressive => "O3",
             // wasm-ld only handles integer LTO opt levels. Use O2
             config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
@@ -1525,7 +1525,7 @@ impl<'a> Linker for L4Bender<'a> {
     fn optimize(&mut self) {
         // GNU-style linkers support optimization with -O. GNU ld doesn't
         // need a numeric argument, but other linkers do.
-        if self.sess.opts.optimize == config::OptLevel::Default
+        if self.sess.opts.optimize == config::OptLevel::More
             || self.sess.opts.optimize == config::OptLevel::Aggressive
         {
             self.link_arg("-O1");
@@ -1929,7 +1929,7 @@ impl<'a> Linker for LlbcLinker<'a> {
         match self.sess.opts.optimize {
             OptLevel::No => "-O0",
             OptLevel::Less => "-O1",
-            OptLevel::Default => "-O2",
+            OptLevel::More => "-O2",
             OptLevel::Aggressive => "-O3",
             OptLevel::Size => "-Os",
             OptLevel::SizeMin => "-Oz",
@@ -2006,7 +2006,7 @@ impl<'a> Linker for BpfLinker<'a> {
         self.link_arg(match self.sess.opts.optimize {
             OptLevel::No => "-O0",
             OptLevel::Less => "-O1",
-            OptLevel::Default => "-O2",
+            OptLevel::More => "-O2",
             OptLevel::Aggressive => "-O3",
             OptLevel::Size => "-Os",
             OptLevel::SizeMin => "-Oz",
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index ce2161a07eb..f029c08a808 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -236,7 +236,7 @@ impl ModuleConfig {
             // Copy what clang does by turning on loop vectorization at O2 and
             // slp vectorization at O3.
             vectorize_loop: !sess.opts.cg.no_vectorize_loops
-                && (sess.opts.optimize == config::OptLevel::Default
+                && (sess.opts.optimize == config::OptLevel::More
                     || sess.opts.optimize == config::OptLevel::Aggressive),
             vectorize_slp: !sess.opts.cg.no_vectorize_slp
                 && sess.opts.optimize == config::OptLevel::Aggressive,
@@ -260,7 +260,7 @@ impl ModuleConfig {
                 MergeFunctions::Trampolines | MergeFunctions::Aliases => {
                     use config::OptLevel::*;
                     match sess.opts.optimize {
-                        Aggressive | Default | SizeMin | Size => true,
+                        Aggressive | More | SizeMin | Size => true,
                         Less | No => false,
                     }
                 }
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index d9fbf539fd3..e800492dad0 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -1054,12 +1054,12 @@ pub(crate) fn provide(providers: &mut Providers) {
             config::OptLevel::No => return config::OptLevel::No,
             // If globally optimise-speed is already specified, just use that level.
             config::OptLevel::Less => return config::OptLevel::Less,
-            config::OptLevel::Default => return config::OptLevel::Default,
+            config::OptLevel::More => return config::OptLevel::More,
             config::OptLevel::Aggressive => return config::OptLevel::Aggressive,
             // If globally optimize-for-size has been requested, use -O2 instead (if optimize(size)
             // are present).
-            config::OptLevel::Size => config::OptLevel::Default,
-            config::OptLevel::SizeMin => config::OptLevel::Default,
+            config::OptLevel::Size => config::OptLevel::More,
+            config::OptLevel::SizeMin => config::OptLevel::More,
         };
 
         let defids = tcx.collect_and_partition_mono_items(cratenum).all_mono_items;
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 1d8f61806f5..3e9dfcea58b 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -272,10 +272,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                 if safe_target_features {
                     if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
                         // The `#[target_feature]` attribute is allowed on
-                        // WebAssembly targets on all functions, including safe
-                        // ones. Other targets require that `#[target_feature]` is
-                        // only applied to unsafe functions (pending the
-                        // `target_feature_11` feature) because on most targets
+                        // WebAssembly targets on all functions. Prior to stabilizing
+                        // the `target_feature_11` feature, `#[target_feature]` was
+                        // only permitted on unsafe functions because on most targets
                         // execution of instructions that are not supported is
                         // considered undefined behavior. For WebAssembly which is a
                         // 100% safe target at execution time it's not possible to
@@ -289,17 +288,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                         // if a target is documenting some wasm-specific code then
                         // it's not spuriously denied.
                         //
-                        // This exception needs to be kept in sync with allowing
-                        // `#[target_feature]` on `main` and `start`.
-                    } else if !tcx.features().target_feature_11() {
-                        feature_err(
-                            &tcx.sess,
-                            sym::target_feature_11,
-                            attr.span,
-                            "`#[target_feature(..)]` can only be applied to `unsafe` functions",
-                        )
-                        .with_span_label(tcx.def_span(did), "not an `unsafe` function")
-                        .emit();
+                        // Now that `#[target_feature]` is permitted on safe functions,
+                        // this exception must still exist for allowing the attribute on
+                        // `main`, `start`, and other functions that are not usually
+                        // allowed.
                     } else {
                         check_target_feature_trait_unsafe(tcx, did, attr.span);
                     }
@@ -628,10 +620,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
     // its parent function, which effectively inherits the features anyway. Boxing this closure
     // would result in this closure being compiled without the inherited target features, but this
     // is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
-    if tcx.features().target_feature_11()
-        && tcx.is_closure_like(did.to_def_id())
-        && !codegen_fn_attrs.inline.always()
-    {
+    if tcx.is_closure_like(did.to_def_id()) && codegen_fn_attrs.inline != InlineAttr::Always {
         let owner_id = tcx.parent(did.to_def_id());
         if tcx.def_kind(owner_id).has_codegen_attrs() {
             codegen_fn_attrs
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 3b7fefee80a..4c5b183cfe9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -435,18 +435,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         scalar: abi::Scalar,
         backend_ty: Bx::Type,
     ) {
-        if matches!(self.cx.sess().opts.optimize, OptLevel::No)
-            // For now, the critical niches are all over `Int`eger values.
-            // Should floating-point values or pointers ever get more complex
-            // niches, then this code will probably want to handle them too.
-            || !matches!(scalar.primitive(), abi::Primitive::Int(..))
-            || scalar.is_always_valid(self.cx)
-        {
+        if matches!(self.cx.sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(self.cx) {
             return;
         }
 
-        let range = scalar.valid_range(self.cx);
-        bx.assume_integer_range(imm, backend_ty, range);
+        match scalar.primitive() {
+            abi::Primitive::Int(..) => {
+                let range = scalar.valid_range(self.cx);
+                bx.assume_integer_range(imm, backend_ty, range);
+            }
+            abi::Primitive::Pointer(abi::AddressSpace::DATA)
+                if !scalar.valid_range(self.cx).contains(0) =>
+            {
+                bx.assume_nonnull(imm);
+            }
+            abi::Primitive::Pointer(..) | abi::Primitive::Float(..) => {}
+        }
     }
 
     pub(crate) fn codegen_rvalue_unsized(
diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs
index 71a2f916db5..ac2366340fb 100644
--- a/compiler/rustc_codegen_ssa/src/size_of_val.rs
+++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs
@@ -45,14 +45,9 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             // The info in this case is the length of the str, so the size is that
             // times the unit size.
             (
-                // All slice sizes must fit into `isize`, so this multiplication cannot (signed)
-                // wrap.
-                // NOTE: ideally, we want the effects of both `unchecked_smul` and `unchecked_umul`
-                // (resulting in `mul nsw nuw` in LLVM IR), since we know that the multiplication
-                // cannot signed wrap, and that both operands are non-negative. But at the time of
-                // writing, the `LLVM-C` binding can't do this, and it doesn't seem to enable any
-                // further optimizations.
-                bx.unchecked_smul(info.unwrap(), bx.const_usize(unit.size.bytes())),
+                // All slice sizes must fit into `isize`, so this multiplication cannot
+                // wrap -- neither signed nor unsigned.
+                bx.unchecked_sumul(info.unwrap(), bx.const_usize(unit.size.bytes())),
                 bx.const_usize(unit.align.abi.bytes()),
             )
         }
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index a98068f26b0..48ae000f2c6 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -173,12 +173,35 @@ pub trait BuilderMethods<'a, 'tcx>:
     /// must be interpreted as unsigned and can be assumed to be less than the size of the left
     /// operand.
     fn ashr(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
-    fn unchecked_sadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
-    fn unchecked_uadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
-    fn unchecked_ssub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
-    fn unchecked_usub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
-    fn unchecked_smul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
-    fn unchecked_umul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
+    fn unchecked_sadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
+        self.add(lhs, rhs)
+    }
+    fn unchecked_uadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
+        self.add(lhs, rhs)
+    }
+    fn unchecked_suadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
+        self.unchecked_sadd(lhs, rhs)
+    }
+    fn unchecked_ssub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
+        self.sub(lhs, rhs)
+    }
+    fn unchecked_usub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
+        self.sub(lhs, rhs)
+    }
+    fn unchecked_susub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
+        self.unchecked_ssub(lhs, rhs)
+    }
+    fn unchecked_smul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
+        self.mul(lhs, rhs)
+    }
+    fn unchecked_umul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
+        self.mul(lhs, rhs)
+    }
+    fn unchecked_sumul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
+        // Which to default to is a fairly arbitrary choice,
+        // but this is what slice layout was using before.
+        self.unchecked_smul(lhs, rhs)
+    }
     fn and(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn or(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     /// Defaults to [`Self::or`], but guarantees `(lhs & rhs) == 0` so some backends
@@ -257,6 +280,19 @@ pub trait BuilderMethods<'a, 'tcx>:
         self.assume(cmp);
     }
 
+    /// Emits an `assume` that the `val` of pointer type is non-null.
+    ///
+    /// You may want to check the optimization level before bothering calling this.
+    fn assume_nonnull(&mut self, val: Self::Value) {
+        // Arguably in LLVM it'd be better to emit an assume operand bundle instead
+        // <https://llvm.org/docs/LangRef.html#assume-operand-bundles>
+        // but this works fine for all backends.
+
+        let null = self.const_null(self.type_ptr());
+        let is_null = self.icmp(IntPredicate::IntNE, val, null);
+        self.assume(is_null);
+    }
+
     fn range_metadata(&mut self, load: Self::Value, range: WrappingRange);
     fn nonnull_metadata(&mut self, load: Self::Value);
 
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index c35910a706b..3776fb55c2e 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -2,7 +2,7 @@ use rustc_abi::{BackendRepr, VariantIdx};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ReportedErrorInfo};
 use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
-use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{bug, mir};
 use rustc_span::DUMMY_SP;
 use tracing::{debug, instrument, trace};
@@ -21,7 +21,7 @@ use crate::interpret::{
 fn branches<'tcx>(
     ecx: &CompileTimeInterpCx<'tcx>,
     place: &MPlaceTy<'tcx>,
-    n: usize,
+    field_count: usize,
     variant: Option<VariantIdx>,
     num_nodes: &mut usize,
 ) -> ValTreeCreationResult<'tcx> {
@@ -29,30 +29,28 @@ fn branches<'tcx>(
         Some(variant) => ecx.project_downcast(place, variant).unwrap(),
         None => place.clone(),
     };
-    let variant = variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
-    debug!(?place, ?variant);
+    debug!(?place);
 
-    let mut fields = Vec::with_capacity(n);
-    for i in 0..n {
-        let field = ecx.project_field(&place, i).unwrap();
-        let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?;
-        fields.push(Some(valtree));
-    }
+    let mut branches = Vec::with_capacity(field_count + variant.is_some() as usize);
 
     // For enums, we prepend their variant index before the variant's fields so we can figure out
     // the variant again when just seeing a valtree.
-    let branches = variant
-        .into_iter()
-        .chain(fields.into_iter())
-        .collect::<Option<Vec<_>>>()
-        .expect("should have already checked for errors in ValTree creation");
+    if let Some(variant) = variant {
+        branches.push(ty::ValTree::from_scalar_int(*ecx.tcx, variant.as_u32().into()));
+    }
+
+    for i in 0..field_count {
+        let field = ecx.project_field(&place, i).unwrap();
+        let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?;
+        branches.push(valtree);
+    }
 
     // Have to account for ZSTs here
     if branches.len() == 0 {
         *num_nodes += 1;
     }
 
-    Ok(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches)))
+    Ok(ty::ValTree::from_branches(*ecx.tcx, branches))
 }
 
 #[instrument(skip(ecx), level = "debug")]
@@ -70,7 +68,7 @@ fn slice_branches<'tcx>(
         elems.push(valtree);
     }
 
-    Ok(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(elems)))
+    Ok(ty::ValTree::from_branches(*ecx.tcx, elems))
 }
 
 #[instrument(skip(ecx), level = "debug")]
@@ -79,6 +77,7 @@ fn const_to_valtree_inner<'tcx>(
     place: &MPlaceTy<'tcx>,
     num_nodes: &mut usize,
 ) -> ValTreeCreationResult<'tcx> {
+    let tcx = *ecx.tcx;
     let ty = place.layout.ty;
     debug!("ty kind: {:?}", ty.kind());
 
@@ -89,14 +88,14 @@ fn const_to_valtree_inner<'tcx>(
     match ty.kind() {
         ty::FnDef(..) => {
             *num_nodes += 1;
-            Ok(ty::ValTree::zst())
+            Ok(ty::ValTree::zst(tcx))
         }
         ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
             let val = ecx.read_immediate(place).unwrap();
             let val = val.to_scalar_int().unwrap();
             *num_nodes += 1;
 
-            Ok(ty::ValTree::Leaf(val))
+            Ok(ty::ValTree::from_scalar_int(tcx, val))
         }
 
         ty::Pat(base, ..) => {
@@ -127,7 +126,7 @@ fn const_to_valtree_inner<'tcx>(
                 return Err(ValTreeCreationError::NonSupportedType(ty));
             };
             // It's just a ScalarInt!
-            Ok(ty::ValTree::Leaf(val))
+            Ok(ty::ValTree::from_scalar_int(tcx, val))
         }
 
         // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
@@ -287,16 +286,11 @@ pub fn valtree_to_const_value<'tcx>(
     // FIXME: Does this need an example?
     match *cv.ty.kind() {
         ty::FnDef(..) => {
-            assert!(cv.valtree.unwrap_branch().is_empty());
+            assert!(cv.valtree.is_zst());
             mir::ConstValue::ZeroSized
         }
         ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char | ty::RawPtr(_, _) => {
-            match cv.valtree {
-                ty::ValTree::Leaf(scalar_int) => mir::ConstValue::Scalar(Scalar::Int(scalar_int)),
-                ty::ValTree::Branch(_) => bug!(
-                    "ValTrees for Bool, Int, Uint, Float, Char or RawPtr should have the form ValTree::Leaf"
-                ),
-            }
+            mir::ConstValue::Scalar(Scalar::Int(cv.valtree.unwrap_leaf()))
         }
         ty::Pat(ty, _) => {
             let cv = ty::Value { valtree: cv.valtree, ty };
diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs
index 17c48aee6fa..0c00e4f4a4b 100644
--- a/compiler/rustc_data_structures/src/owned_slice.rs
+++ b/compiler/rustc_data_structures/src/owned_slice.rs
@@ -2,11 +2,6 @@ use std::borrow::Borrow;
 use std::ops::Deref;
 use std::sync::Arc;
 
-// Use our fake Send/Sync traits when on not parallel compiler,
-// so that `OwnedSlice` only implements/requires Send/Sync
-// for parallel compiler builds.
-use crate::sync;
-
 /// An owned slice.
 ///
 /// This is similar to `Arc<[u8]>` but allows slicing and using anything as the
@@ -34,7 +29,7 @@ pub struct OwnedSlice {
     //       \/
     //      ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
     #[expect(dead_code)]
-    owner: Arc<dyn sync::Send + sync::Sync>,
+    owner: Arc<dyn Send + Sync>,
 }
 
 /// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
@@ -61,7 +56,7 @@ pub struct OwnedSlice {
 /// ```
 pub fn slice_owned<O, F>(owner: O, slicer: F) -> OwnedSlice
 where
-    O: sync::Send + sync::Sync + 'static,
+    O: Send + Sync + 'static,
     F: FnOnce(&O) -> &[u8],
 {
     try_slice_owned(owner, |x| Ok::<_, !>(slicer(x))).into_ok()
@@ -72,7 +67,7 @@ where
 /// See [`slice_owned`] for the infallible version.
 pub fn try_slice_owned<O, F, E>(owner: O, slicer: F) -> Result<OwnedSlice, E>
 where
-    O: sync::Send + sync::Sync + 'static,
+    O: Send + Sync + 'static,
     F: FnOnce(&O) -> Result<&[u8], E>,
 {
     // We wrap the owner of the bytes in, so it doesn't move.
@@ -139,10 +134,10 @@ impl Borrow<[u8]> for OwnedSlice {
 }
 
 // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Send`
-unsafe impl sync::Send for OwnedSlice {}
+unsafe impl Send for OwnedSlice {}
 
 // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Sync`
-unsafe impl sync::Sync for OwnedSlice {}
+unsafe impl Sync for OwnedSlice {}
 
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index bea87a6685d..37b54fe38ff 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -18,14 +18,8 @@
 //!
 //! | Type                    | Serial version      | Parallel version                |
 //! | ----------------------- | ------------------- | ------------------------------- |
-//! |` Weak<T>`               | `rc::Weak<T>`       | `sync::Weak<T>`                 |
 //! | `LRef<'a, T>` [^2]      | `&'a mut T`         | `&'a T`                         |
 //! |                         |                     |                                 |
-//! | `AtomicBool`            | `Cell<bool>`        | `atomic::AtomicBool`            |
-//! | `AtomicU32`             | `Cell<u32>`         | `atomic::AtomicU32`             |
-//! | `AtomicU64`             | `Cell<u64>`         | `atomic::AtomicU64`             |
-//! | `AtomicUsize`           | `Cell<usize>`       | `atomic::AtomicUsize`           |
-//! |                         |                     |                                 |
 //! | `Lock<T>`               | `RefCell<T>`        | `RefCell<T>` or                 |
 //! |                         |                     | `parking_lot::Mutex<T>`         |
 //! | `RwLock<T>`             | `RefCell<T>`        | `parking_lot::RwLock<T>`        |
@@ -103,18 +97,15 @@ mod mode {
 
 // FIXME(parallel_compiler): Get rid of these aliases across the compiler.
 
-pub use std::marker::{Send, Sync};
+pub use std::sync::OnceLock;
 // Use portable AtomicU64 for targets without native 64-bit atomics
 #[cfg(target_has_atomic = "64")]
 pub use std::sync::atomic::AtomicU64;
-pub use std::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize};
-pub use std::sync::{OnceLock, Weak};
 
 pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
 pub use parking_lot::{
-    MappedMutexGuard as MappedLockGuard, MappedRwLockReadGuard as MappedReadGuard,
-    MappedRwLockWriteGuard as MappedWriteGuard, RwLockReadGuard as ReadGuard,
-    RwLockWriteGuard as WriteGuard,
+    MappedRwLockReadGuard as MappedReadGuard, MappedRwLockWriteGuard as MappedWriteGuard,
+    RwLockReadGuard as ReadGuard, RwLockWriteGuard as WriteGuard,
 };
 #[cfg(not(target_has_atomic = "64"))]
 pub use portable_atomic::AtomicU64;
@@ -204,12 +195,6 @@ impl<T> RwLock<T> {
     }
 
     #[inline(always)]
-    #[track_caller]
-    pub fn with_read_lock<F: FnOnce(&T) -> R, R>(&self, f: F) -> R {
-        f(&*self.read())
-    }
-
-    #[inline(always)]
     pub fn try_write(&self) -> Result<WriteGuard<'_, T>, ()> {
         self.0.try_write().ok_or(())
     }
@@ -225,12 +210,6 @@ impl<T> RwLock<T> {
 
     #[inline(always)]
     #[track_caller]
-    pub fn with_write_lock<F: FnOnce(&mut T) -> R, R>(&self, f: F) -> R {
-        f(&mut *self.write())
-    }
-
-    #[inline(always)]
-    #[track_caller]
     pub fn borrow(&self) -> ReadGuard<'_, T> {
         self.read()
     }
@@ -240,20 +219,4 @@ impl<T> RwLock<T> {
     pub fn borrow_mut(&self) -> WriteGuard<'_, T> {
         self.write()
     }
-
-    #[inline(always)]
-    pub fn leak(&self) -> &T {
-        let guard = self.read();
-        let ret = unsafe { &*(&raw const *guard) };
-        std::mem::forget(guard);
-        ret
-    }
-}
-
-// FIXME: Probably a bad idea
-impl<T: Clone> Clone for RwLock<T> {
-    #[inline]
-    fn clone(&self) -> Self {
-        RwLock::new(self.borrow().clone())
-    }
 }
diff --git a/compiler/rustc_data_structures/src/sync/freeze.rs b/compiler/rustc_data_structures/src/sync/freeze.rs
index 5236c9fe156..9720b22ea7d 100644
--- a/compiler/rustc_data_structures/src/sync/freeze.rs
+++ b/compiler/rustc_data_structures/src/sync/freeze.rs
@@ -3,9 +3,9 @@ use std::intrinsics::likely;
 use std::marker::PhantomData;
 use std::ops::{Deref, DerefMut};
 use std::ptr::NonNull;
-use std::sync::atomic::Ordering;
+use std::sync::atomic::{AtomicBool, Ordering};
 
-use crate::sync::{AtomicBool, DynSend, DynSync, ReadGuard, RwLock, WriteGuard};
+use crate::sync::{DynSend, DynSync, ReadGuard, RwLock, WriteGuard};
 
 /// A type which allows mutation using a lock until
 /// the value is frozen and can be accessed lock-free.
diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs
index d75af009850..402ec9827bb 100644
--- a/compiler/rustc_data_structures/src/sync/worker_local.rs
+++ b/compiler/rustc_data_structures/src/sync/worker_local.rs
@@ -106,12 +106,6 @@ pub struct WorkerLocal<T> {
     registry: Registry,
 }
 
-// This is safe because the `deref` call will return a reference to a `T` unique to each thread
-// or it will panic for threads without an associated local. So there isn't a need for `T` to do
-// it's own synchronization. The `verify` method on `RegistryId` has an issue where the id
-// can be reused, but `WorkerLocal` has a reference to `Registry` which will prevent any reuse.
-unsafe impl<T: Send> Sync for WorkerLocal<T> {}
-
 impl<T> WorkerLocal<T> {
     /// Creates a new worker local where the `initial` closure computes the
     /// value this worker local should take for each thread in the registry.
@@ -138,6 +132,11 @@ impl<T> Deref for WorkerLocal<T> {
     fn deref(&self) -> &T {
         // This is safe because `verify` will only return values less than
         // `self.registry.thread_limit` which is the size of the `self.locals` array.
+
+        // The `deref` call will return a reference to a `T` unique to each thread
+        // or it will panic for threads without an associated local. So there isn't a need for `T` to do
+        // it's own synchronization. The `verify` method on `RegistryId` has an issue where the id
+        // can be reused, but `WorkerLocal` has a reference to `Registry` which will prevent any reuse.
         unsafe { &self.locals.get_unchecked(self.registry.id().verify()).0 }
     }
 }
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 4824dc098ad..634afacf539 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1976,13 +1976,16 @@ impl HumanEmitter {
             Some(Style::HeaderMsg),
         );
 
+        let other_suggestions = suggestions.len().saturating_sub(MAX_SUGGESTIONS);
+
         let mut row_num = 2;
         for (i, (complete, parts, highlights, _)) in
-            suggestions.iter().enumerate().take(MAX_SUGGESTIONS)
+            suggestions.into_iter().enumerate().take(MAX_SUGGESTIONS)
         {
             debug!(?complete, ?parts, ?highlights);
 
-            let has_deletion = parts.iter().any(|p| p.is_deletion(sm) || p.is_replacement(sm));
+            let has_deletion =
+                parts.iter().any(|p| p.is_deletion(sm) || p.is_destructive_replacement(sm));
             let is_multiline = complete.lines().count() > 1;
 
             if i == 0 {
@@ -2167,7 +2170,7 @@ impl HumanEmitter {
                 self.draw_code_line(
                     &mut buffer,
                     &mut row_num,
-                    highlight_parts,
+                    &highlight_parts,
                     line_pos + line_start,
                     line,
                     show_code_change,
@@ -2213,7 +2216,12 @@ impl HumanEmitter {
             if let DisplaySuggestion::Diff | DisplaySuggestion::Underline | DisplaySuggestion::Add =
                 show_code_change
             {
-                for part in parts {
+                for mut part in parts {
+                    // If this is a replacement of, e.g. `"a"` into `"ab"`, adjust the
+                    // suggestion and snippet to look as if we just suggested to add
+                    // `"b"`, which is typically much easier for the user to understand.
+                    part.trim_trivial_replacements(sm);
+
                     let snippet = if let Ok(snippet) = sm.span_to_snippet(part.span) {
                         snippet
                     } else {
@@ -2376,9 +2384,12 @@ impl HumanEmitter {
                 row_num = row + 1;
             }
         }
-        if suggestions.len() > MAX_SUGGESTIONS {
-            let others = suggestions.len() - MAX_SUGGESTIONS;
-            let msg = format!("and {} other candidate{}", others, pluralize!(others));
+        if other_suggestions > 0 {
+            let msg = format!(
+                "and {} other candidate{}",
+                other_suggestions,
+                pluralize!(other_suggestions)
+            );
             buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle);
         }
 
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 9af17db9a6e..8ff5dc12596 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -230,10 +230,40 @@ impl SubstitutionPart {
         !self.snippet.is_empty() && self.replaces_meaningful_content(sm)
     }
 
+    /// Whether this is a replacement that overwrites source with a snippet
+    /// in a way that isn't a superset of the original string. For example,
+    /// replacing "abc" with "abcde" is not destructive, but replacing it
+    /// it with "abx" is, since the "c" character is lost.
+    pub fn is_destructive_replacement(&self, sm: &SourceMap) -> bool {
+        self.is_replacement(sm)
+            && !sm.span_to_snippet(self.span).is_ok_and(|snippet| {
+                self.snippet.trim_start().starts_with(snippet.trim_start())
+                    || self.snippet.trim_end().ends_with(snippet.trim_end())
+            })
+    }
+
     fn replaces_meaningful_content(&self, sm: &SourceMap) -> bool {
         sm.span_to_snippet(self.span)
             .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty())
     }
+
+    /// Try to turn a replacement into an addition when the span that is being
+    /// overwritten matches either the prefix or suffix of the replacement.
+    fn trim_trivial_replacements(&mut self, sm: &SourceMap) {
+        if self.snippet.is_empty() {
+            return;
+        }
+        let Ok(snippet) = sm.span_to_snippet(self.span) else {
+            return;
+        };
+        if self.snippet.starts_with(&snippet) {
+            self.span = self.span.shrink_to_hi();
+            self.snippet = self.snippet[snippet.len()..].to_string();
+        } else if self.snippet.ends_with(&snippet) {
+            self.span = self.span.shrink_to_lo();
+            self.snippet = self.snippet[..self.snippet.len() - snippet.len()].to_string();
+        }
+    }
 }
 
 impl CodeSuggestion {
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 76ca0d618d5..2dfb0c8e040 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -386,6 +386,8 @@ declare_features! (
     (accepted, struct_variant, "1.0.0", None),
     /// Allows `#[target_feature(...)]`.
     (accepted, target_feature, "1.27.0", None),
+    /// Allows the use of `#[target_feature]` on safe functions.
+    (accepted, target_feature_11, "CURRENT_RUSTC_VERSION", Some(69098)),
     /// Allows `fn main()` with return types which implements `Termination` (RFC 1937).
     (accepted, termination_trait, "1.26.0", Some(43301)),
     /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937).
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index ee22d8990fa..a638a845c07 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -487,9 +487,11 @@ declare_features! (
     (unstable, exhaustive_patterns, "1.13.0", Some(51085)),
     /// Allows explicit tail calls via `become` expression.
     (incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
-    /// Allows using `efiapi`, `sysv64` and `win64` as calling convention
+    /// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions
     /// for functions with varargs.
     (unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
+    /// Allows using `system` as a calling convention with varargs.
+    (unstable, extern_system_varargs, "CURRENT_RUSTC_VERSION", Some(136946)),
     /// Allows defining `extern type`s.
     (unstable, extern_types, "1.23.0", Some(43467)),
     /// Allow using 128-bit (quad precision) floating point numbers.
@@ -633,8 +635,8 @@ declare_features! (
     (unstable, strict_provenance_lints, "1.61.0", Some(130351)),
     /// Allows string patterns to dereference values to match them.
     (unstable, string_deref_patterns, "1.67.0", Some(87121)),
-    /// Allows the use of `#[target_feature]` on safe functions.
-    (unstable, target_feature_11, "1.45.0", Some(69098)),
+    /// Allows subtrait items to shadow supertrait items.
+    (unstable, supertrait_item_shadowing, "CURRENT_RUSTC_VERSION", Some(89151)),
     /// Allows using `#[thread_local]` on `static` items.
     (unstable, thread_local, "1.0.0", Some(29594)),
     /// Allows defining `trait X = A + B;` alias items.
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 7344ea01fb2..5560d087e96 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -506,6 +506,12 @@ hir_analysis_specialization_trait = implementing `rustc_specialization_trait` tr
 
 hir_analysis_static_specialize = cannot specialize on `'static` lifetime
 
+hir_analysis_supertrait_item_multiple_shadowee = items from several supertraits are shadowed: {$traits}
+
+hir_analysis_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by a subtrait item
+
+hir_analysis_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait
+
 hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature
     .note = this item must mention the opaque type in its signature in order to be able to register hidden types
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 1689437ffb0..4218f4ef0c1 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -12,6 +12,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::{AmbigArg, ItemKind};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
+use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION;
 use rustc_macros::LintDiagnostic;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::query::Providers;
@@ -388,7 +389,12 @@ fn check_trait_item<'tcx>(
         hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span),
         _ => (None, trait_item.span),
     };
+
     check_dyn_incompatible_self_trait_by_name(tcx, trait_item);
+
+    // Check that an item definition in a subtrait is shadowing a supertrait item.
+    lint_item_shadowing_supertrait_item(tcx, def_id);
+
     let mut res = check_associated_item(tcx, def_id, span, method_sig);
 
     if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {
@@ -898,6 +904,45 @@ fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitI
     }
 }
 
+fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_id: LocalDefId) {
+    let item_name = tcx.item_name(trait_item_def_id.to_def_id());
+    let trait_def_id = tcx.local_parent(trait_item_def_id);
+
+    let shadowed: Vec<_> = traits::supertrait_def_ids(tcx, trait_def_id.to_def_id())
+        .skip(1)
+        .flat_map(|supertrait_def_id| {
+            tcx.associated_items(supertrait_def_id).filter_by_name_unhygienic(item_name)
+        })
+        .collect();
+    if !shadowed.is_empty() {
+        let shadowee = if let [shadowed] = shadowed[..] {
+            errors::SupertraitItemShadowee::Labeled {
+                span: tcx.def_span(shadowed.def_id),
+                supertrait: tcx.item_name(shadowed.trait_container(tcx).unwrap()),
+            }
+        } else {
+            let (traits, spans): (Vec<_>, Vec<_>) = shadowed
+                .iter()
+                .map(|item| {
+                    (tcx.item_name(item.trait_container(tcx).unwrap()), tcx.def_span(item.def_id))
+                })
+                .unzip();
+            errors::SupertraitItemShadowee::Several { traits: traits.into(), spans: spans.into() }
+        };
+
+        tcx.emit_node_span_lint(
+            SUPERTRAIT_ITEM_SHADOWING_DEFINITION,
+            tcx.local_def_id_to_hir_id(trait_item_def_id),
+            tcx.def_span(trait_item_def_id),
+            errors::SupertraitItemShadowing {
+                item: item_name,
+                subtrait: tcx.item_name(trait_def_id.to_def_id()),
+                shadowee,
+            },
+        );
+    }
+}
+
 fn check_impl_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_item: &'tcx hir::ImplItem<'tcx>,
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index d2e2ab1da77..41c4cfbaa82 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -30,53 +30,55 @@ fn associated_type_bounds<'tcx>(
     span: Span,
     filter: PredicateFilter,
 ) -> &'tcx [(ty::Clause<'tcx>, Span)] {
-    let item_ty = Ty::new_projection_from_args(
-        tcx,
-        assoc_item_def_id.to_def_id(),
-        GenericArgs::identity_for_item(tcx, assoc_item_def_id),
-    );
-
-    let icx = ItemCtxt::new(tcx, assoc_item_def_id);
-    let mut bounds = Bounds::default();
-    icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
-    // Associated types are implicitly sized unless a `?Sized` bound is found
-    match filter {
-        PredicateFilter::All
-        | PredicateFilter::SelfOnly
-        | PredicateFilter::SelfTraitThatDefines(_)
-        | PredicateFilter::SelfAndAssociatedTypeBounds => {
-            icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
+    ty::print::with_reduced_queries!({
+        let item_ty = Ty::new_projection_from_args(
+            tcx,
+            assoc_item_def_id.to_def_id(),
+            GenericArgs::identity_for_item(tcx, assoc_item_def_id),
+        );
+
+        let icx = ItemCtxt::new(tcx, assoc_item_def_id);
+        let mut bounds = Bounds::default();
+        icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
+        // Associated types are implicitly sized unless a `?Sized` bound is found
+        match filter {
+            PredicateFilter::All
+            | PredicateFilter::SelfOnly
+            | PredicateFilter::SelfTraitThatDefines(_)
+            | PredicateFilter::SelfAndAssociatedTypeBounds => {
+                icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
+            }
+            // `ConstIfConst` is only interested in `~const` bounds.
+            PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
         }
-        // `ConstIfConst` is only interested in `~const` bounds.
-        PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
-    }
 
-    let trait_def_id = tcx.local_parent(assoc_item_def_id);
-    let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
-
-    let item_trait_ref = ty::TraitRef::identity(tcx, tcx.parent(assoc_item_def_id.to_def_id()));
-    let bounds_from_parent =
-        trait_predicates.predicates.iter().copied().filter_map(|(clause, span)| {
-            remap_gat_vars_and_recurse_into_nested_projections(
-                tcx,
-                filter,
-                item_trait_ref,
-                assoc_item_def_id,
-                span,
-                clause,
-            )
-        });
-
-    let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
-    debug!(
-        "associated_type_bounds({}) = {:?}",
-        tcx.def_path_str(assoc_item_def_id.to_def_id()),
-        all_bounds
-    );
+        let trait_def_id = tcx.local_parent(assoc_item_def_id);
+        let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
+
+        let item_trait_ref = ty::TraitRef::identity(tcx, tcx.parent(assoc_item_def_id.to_def_id()));
+        let bounds_from_parent =
+            trait_predicates.predicates.iter().copied().filter_map(|(clause, span)| {
+                remap_gat_vars_and_recurse_into_nested_projections(
+                    tcx,
+                    filter,
+                    item_trait_ref,
+                    assoc_item_def_id,
+                    span,
+                    clause,
+                )
+            });
+
+        let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
+        debug!(
+            "associated_type_bounds({}) = {:?}",
+            tcx.def_path_str(assoc_item_def_id.to_def_id()),
+            all_bounds
+        );
 
-    assert_only_contains_predicates_from(filter, all_bounds, item_ty);
+        assert_only_contains_predicates_from(filter, all_bounds, item_ty);
 
-    all_bounds
+        all_bounds
+    })
 }
 
 /// The code below is quite involved, so let me explain.
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 1574506de60..14ea10461cb 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -3,7 +3,8 @@
 use rustc_abi::ExternAbi;
 use rustc_errors::codes::*;
 use rustc_errors::{
-    Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan,
+    Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
+    MultiSpan,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::Ty;
@@ -1733,3 +1734,28 @@ pub(crate) struct RegisterTypeUnstable<'a> {
     pub span: Span,
     pub ty: Ty<'a>,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(hir_analysis_supertrait_item_shadowing)]
+pub(crate) struct SupertraitItemShadowing {
+    pub item: Symbol,
+    pub subtrait: Symbol,
+    #[subdiagnostic]
+    pub shadowee: SupertraitItemShadowee,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum SupertraitItemShadowee {
+    #[note(hir_analysis_supertrait_item_shadowee)]
+    Labeled {
+        #[primary_span]
+        span: Span,
+        supertrait: Symbol,
+    },
+    #[note(hir_analysis_supertrait_item_multiple_shadowee)]
+    Several {
+        #[primary_span]
+        spans: MultiSpan,
+        traits: DiagSymbolList,
+    },
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 2834d497694..ef6167907b5 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -102,8 +102,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 seen_sized_unbound = true;
                 continue;
             }
-            // There was a `?Trait` bound, but it was not `?Sized`; warn.
-            self.dcx().span_warn(
+            // There was a `?Trait` bound, but it was not `?Sized`
+            self.dcx().span_err(
                 unbound.span,
                 "relaxing a default bound only does something for `?Sized`; \
                 all other traits are not bound by default",
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 c6e47a804dc..88323db6dda 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2161,7 +2161,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     did,
                     path.segments.last().unwrap(),
                 );
-                ty::Const::new_value(tcx, ty::ValTree::zst(), Ty::new_fn_def(tcx, did, args))
+                ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, did, args))
             }
 
             // Exhaustive match to be clear about what exactly we're considering to be
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 323b912ca18..8a529e9c686 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -122,28 +122,42 @@ fn require_c_abi_if_c_variadic(
     const UNSTABLE_EXPLAIN: &str =
         "using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
 
+    // ABIs which can stably use varargs
     if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) {
         return;
     }
 
+    // ABIs with feature-gated stability
     let extended_abi_support = tcx.features().extended_varargs_abi_support();
-    let conventions = match (extended_abi_support, abi.supports_varargs()) {
-        // User enabled additional ABI support for varargs and function ABI matches those ones.
-        (true, true) => return,
+    let extern_system_varargs = tcx.features().extern_system_varargs();
 
-        // Using this ABI would be ok, if the feature for additional ABI support was enabled.
-        // Return CONVENTIONS_STABLE, because we want the other error to look the same.
-        (false, true) => {
-            feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
-                .emit();
-            CONVENTIONS_STABLE
-        }
-
-        (false, false) => CONVENTIONS_STABLE,
-        (true, false) => CONVENTIONS_UNSTABLE,
+    // If the feature gate has been enabled, we can stop here
+    if extern_system_varargs && let ExternAbi::System { .. } = abi {
+        return;
+    };
+    if extended_abi_support && abi.supports_varargs() {
+        return;
     };
 
-    tcx.dcx().emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions });
+    // Looks like we need to pick an error to emit.
+    // Is there any feature which we could have enabled to make this work?
+    match abi {
+        ExternAbi::System { .. } => {
+            feature_err(&tcx.sess, sym::extern_system_varargs, span, UNSTABLE_EXPLAIN)
+        }
+        abi if abi.supports_varargs() => {
+            feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
+        }
+        _ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention {
+            span,
+            conventions: if tcx.sess.opts.unstable_features.is_nightly_build() {
+                CONVENTIONS_UNSTABLE
+            } else {
+                CONVENTIONS_STABLE
+            },
+        }),
+    }
+    .emit();
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 0f424a39840..a994b31aeb4 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -192,6 +192,14 @@ hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `
 
 hir_typeck_suggest_ptr_null_mut = consider using `core::ptr::null_mut` instead
 
+hir_typeck_supertrait_item_multiple_shadowee = items from several supertraits are shadowed: {$traits}
+
+hir_typeck_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by a subtrait item
+
+hir_typeck_supertrait_item_shadower = item from `{$subtrait}` shadows a supertrait item
+
+hir_typeck_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait
+
 hir_typeck_trivial_cast = trivial {$numeric ->
     [true] numeric cast
     *[false] cast
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 143736072aa..1bf8aa4f78d 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -868,3 +868,38 @@ pub(crate) struct ReplaceCommaWithSemicolon {
     pub comma_span: Span,
     pub descr: &'static str,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(hir_typeck_supertrait_item_shadowing)]
+pub(crate) struct SupertraitItemShadowing {
+    pub item: Symbol,
+    pub subtrait: Symbol,
+    #[subdiagnostic]
+    pub shadower: SupertraitItemShadower,
+    #[subdiagnostic]
+    pub shadowee: SupertraitItemShadowee,
+}
+
+#[derive(Subdiagnostic)]
+#[note(hir_typeck_supertrait_item_shadower)]
+pub(crate) struct SupertraitItemShadower {
+    pub subtrait: Symbol,
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum SupertraitItemShadowee {
+    #[note(hir_typeck_supertrait_item_shadowee)]
+    Labeled {
+        #[primary_span]
+        span: Span,
+        supertrait: Symbol,
+    },
+    #[note(hir_typeck_supertrait_item_multiple_shadowee)]
+    Several {
+        #[primary_span]
+        spans: MultiSpan,
+        traits: DiagSymbolList,
+    },
+}
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index d37c68f82fb..860e619be71 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -892,57 +892,75 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
 
         let tcx = self.cx.tcx();
         self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
-            if let PatKind::Binding(_, canonical_id, ..) = pat.kind {
-                debug!("walk_pat: binding place={:?} pat={:?}", place, pat);
-                if let Some(bm) =
-                    self.cx.typeck_results().extract_binding_mode(tcx.sess, pat.hir_id, pat.span)
-                {
-                    debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
-
-                    // pat_ty: the type of the binding being produced.
-                    let pat_ty = self.node_ty(pat.hir_id)?;
-                    debug!("walk_pat: pat_ty={:?}", pat_ty);
+            match pat.kind {
+                PatKind::Binding(_, canonical_id, ..) => {
+                    debug!("walk_pat: binding place={:?} pat={:?}", place, pat);
+                    if let Some(bm) = self
+                        .cx
+                        .typeck_results()
+                        .extract_binding_mode(tcx.sess, pat.hir_id, pat.span)
+                    {
+                        debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
 
-                    let def = Res::Local(canonical_id);
-                    if let Ok(ref binding_place) = self.cat_res(pat.hir_id, pat.span, pat_ty, def) {
-                        self.delegate.borrow_mut().bind(binding_place, binding_place.hir_id);
-                    }
+                        // pat_ty: the type of the binding being produced.
+                        let pat_ty = self.node_ty(pat.hir_id)?;
+                        debug!("walk_pat: pat_ty={:?}", pat_ty);
 
-                    // Subtle: MIR desugaring introduces immutable borrows for each pattern
-                    // binding when lowering pattern guards to ensure that the guard does not
-                    // modify the scrutinee.
-                    if has_guard {
-                        self.delegate.borrow_mut().borrow(
-                            place,
-                            discr_place.hir_id,
-                            BorrowKind::Immutable,
-                        );
-                    }
+                        let def = Res::Local(canonical_id);
+                        if let Ok(ref binding_place) =
+                            self.cat_res(pat.hir_id, pat.span, pat_ty, def)
+                        {
+                            self.delegate.borrow_mut().bind(binding_place, binding_place.hir_id);
+                        }
 
-                    // It is also a borrow or copy/move of the value being matched.
-                    // In a cases of pattern like `let pat = upvar`, don't use the span
-                    // of the pattern, as this just looks confusing, instead use the span
-                    // of the discriminant.
-                    match bm.0 {
-                        hir::ByRef::Yes(m) => {
-                            let bk = ty::BorrowKind::from_mutbl(m);
-                            self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
+                        // Subtle: MIR desugaring introduces immutable borrows for each pattern
+                        // binding when lowering pattern guards to ensure that the guard does not
+                        // modify the scrutinee.
+                        if has_guard {
+                            self.delegate.borrow_mut().borrow(
+                                place,
+                                discr_place.hir_id,
+                                BorrowKind::Immutable,
+                            );
                         }
-                        hir::ByRef::No => {
-                            debug!("walk_pat binding consuming pat");
-                            self.consume_or_copy(place, discr_place.hir_id);
+
+                        // It is also a borrow or copy/move of the value being matched.
+                        // In a cases of pattern like `let pat = upvar`, don't use the span
+                        // of the pattern, as this just looks confusing, instead use the span
+                        // of the discriminant.
+                        match bm.0 {
+                            hir::ByRef::Yes(m) => {
+                                let bk = ty::BorrowKind::from_mutbl(m);
+                                self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
+                            }
+                            hir::ByRef::No => {
+                                debug!("walk_pat binding consuming pat");
+                                self.consume_or_copy(place, discr_place.hir_id);
+                            }
                         }
                     }
                 }
-            } else if let PatKind::Deref(subpattern) = pat.kind {
-                // A deref pattern is a bit special: the binding mode of its inner bindings
-                // determines whether to borrow *at the level of the deref pattern* rather than
-                // borrowing the bound place (since that inner place is inside the temporary that
-                // stores the result of calling `deref()`/`deref_mut()` so can't be captured).
-                let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpattern);
-                let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
-                let bk = ty::BorrowKind::from_mutbl(mutability);
-                self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
+                PatKind::Deref(subpattern) => {
+                    // A deref pattern is a bit special: the binding mode of its inner bindings
+                    // determines whether to borrow *at the level of the deref pattern* rather than
+                    // borrowing the bound place (since that inner place is inside the temporary that
+                    // stores the result of calling `deref()`/`deref_mut()` so can't be captured).
+                    let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpattern);
+                    let mutability =
+                        if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
+                    let bk = ty::BorrowKind::from_mutbl(mutability);
+                    self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
+                }
+                PatKind::Never => {
+                    // A `!` pattern always counts as an immutable read of the discriminant,
+                    // even in an irrefutable pattern.
+                    self.delegate.borrow_mut().borrow(
+                        place,
+                        discr_place.hir_id,
+                        BorrowKind::Immutable,
+                    );
+                }
+                _ => {}
             }
 
             Ok(())
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index e74ffeff343..1113f7f7095 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -798,13 +798,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
             }
         };
+
+        self.register_wf_obligation(
+            ty.raw.into(),
+            qself.span,
+            ObligationCauseCode::WellFormed(None),
+        );
+        self.select_obligations_where_possible(|_| {});
+
         if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
         {
-            self.register_wf_obligation(
-                ty.raw.into(),
-                qself.span,
-                ObligationCauseCode::WellFormed(None),
-            );
             // Return directly on cache hit. This is useful to avoid doubly reporting
             // errors with default match binding modes. See #44614.
             let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
@@ -824,18 +827,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 let trait_missing_method =
                     matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait();
-                // If we have a path like `MyTrait::missing_method`, then don't register
-                // a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
-                // register a WF obligation so that we can detect any additional
-                // errors in the self type.
-                if !trait_missing_method {
-                    self.register_wf_obligation(
-                        ty.raw.into(),
-                        qself.span,
-                        ObligationCauseCode::WellFormed(None),
-                    );
-                }
-
                 if item_name.name != kw::Empty {
                     self.report_method_error(
                         hir_id,
@@ -849,14 +840,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 result
             });
 
-        if result.is_ok() {
-            self.register_wf_obligation(
-                ty.raw.into(),
-                qself.span,
-                ObligationCauseCode::WellFormed(None),
-            );
-        }
-
         // Write back the new resolution.
         self.write_resolution(hir_id, result);
         (
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 36cc9b40d00..8fb425ff0c9 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -10,6 +10,7 @@ use rustc_hir_analysis::hir_ty_lowering::{
     FeedConstTy, GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason,
 };
 use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk};
+use rustc_lint::builtin::SUPERTRAIT_ITEM_SHADOWING_USAGE;
 use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
@@ -24,6 +25,7 @@ use rustc_trait_selection::traits;
 use tracing::debug;
 
 use super::{MethodCallee, probe};
+use crate::errors::{SupertraitItemShadowee, SupertraitItemShadower, SupertraitItemShadowing};
 use crate::{FnCtxt, callee};
 
 struct ConfirmContext<'a, 'tcx> {
@@ -141,7 +143,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         let method_sig = ty::Binder::dummy(method_sig);
 
         // Make sure nobody calls `drop()` explicitly.
-        self.enforce_illegal_method_limitations(pick);
+        self.check_for_illegal_method_calls(pick);
+
+        // Lint when an item is shadowing a supertrait item.
+        self.lint_shadowed_supertrait_items(pick, segment);
 
         // Add any trait/regions obligations specified on the method's type parameters.
         // We won't add these if we encountered an illegal sized bound, so that we can use
@@ -656,7 +661,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             })
     }
 
-    fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) {
+    fn check_for_illegal_method_calls(&self, pick: &probe::Pick<'_>) {
         // Disallow calls to the method `drop` defined in the `Drop` trait.
         if let Some(trait_def_id) = pick.item.trait_container(self.tcx) {
             if let Err(e) = callee::check_legal_trait_for_method_call(
@@ -672,6 +677,45 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         }
     }
 
+    fn lint_shadowed_supertrait_items(
+        &self,
+        pick: &probe::Pick<'_>,
+        segment: &hir::PathSegment<'tcx>,
+    ) {
+        if pick.shadowed_candidates.is_empty() {
+            return;
+        }
+
+        let shadower_span = self.tcx.def_span(pick.item.def_id);
+        let subtrait = self.tcx.item_name(pick.item.trait_container(self.tcx).unwrap());
+        let shadower = SupertraitItemShadower { span: shadower_span, subtrait };
+
+        let shadowee = if let [shadowee] = &pick.shadowed_candidates[..] {
+            let shadowee_span = self.tcx.def_span(shadowee.def_id);
+            let supertrait = self.tcx.item_name(shadowee.trait_container(self.tcx).unwrap());
+            SupertraitItemShadowee::Labeled { span: shadowee_span, supertrait }
+        } else {
+            let (traits, spans): (Vec<_>, Vec<_>) = pick
+                .shadowed_candidates
+                .iter()
+                .map(|item| {
+                    (
+                        self.tcx.item_name(item.trait_container(self.tcx).unwrap()),
+                        self.tcx.def_span(item.def_id),
+                    )
+                })
+                .unzip();
+            SupertraitItemShadowee::Several { traits: traits.into(), spans: spans.into() }
+        };
+
+        self.tcx.emit_node_span_lint(
+            SUPERTRAIT_ITEM_SHADOWING_USAGE,
+            segment.hir_id,
+            segment.ident.span,
+            SupertraitItemShadowing { shadower, shadowee, item: segment.ident.name, subtrait },
+        );
+    }
+
     fn upcast(
         &mut self,
         source_trait_ref: ty::PolyTraitRef<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 9394fcafd76..b3e48fd5bb5 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -3,6 +3,7 @@ use std::cmp::max;
 use std::ops::Deref;
 
 use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sso::SsoHashSet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::HirId;
@@ -33,6 +34,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{
     CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult,
 };
 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
+use rustc_type_ir::elaborate::supertrait_def_ids;
 use smallvec::{SmallVec, smallvec};
 use tracing::{debug, instrument};
 
@@ -224,6 +226,9 @@ pub(crate) struct Pick<'tcx> {
     /// to identify this method. Used only for deshadowing errors.
     /// Only applies for inherent impls.
     pub receiver_steps: Option<usize>,
+
+    /// Candidates that were shadowed by supertraits.
+    pub shadowed_candidates: Vec<ty::AssocItem>,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -1634,6 +1639,17 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
 
         if applicable_candidates.len() > 1 {
+            // We collapse to a subtrait pick *after* filtering unstable candidates
+            // to make sure we don't prefer a unstable subtrait method over a stable
+            // supertrait method.
+            if self.tcx.features().supertrait_item_shadowing() {
+                if let Some(pick) =
+                    self.collapse_candidates_to_subtrait_pick(self_ty, &applicable_candidates)
+                {
+                    return Some(Ok(pick));
+                }
+            }
+
             let sources = candidates.iter().map(|p| self.candidate_source(p, self_ty)).collect();
             return Some(Err(MethodError::Ambiguity(sources)));
         }
@@ -1672,6 +1688,7 @@ impl<'tcx> Pick<'tcx> {
             self_ty,
             unstable_candidates: _,
             receiver_steps: _,
+            shadowed_candidates: _,
         } = *self;
         self_ty != other.self_ty || def_id != other.item.def_id
     }
@@ -2081,6 +2098,83 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             self_ty,
             unstable_candidates: vec![],
             receiver_steps: None,
+            shadowed_candidates: vec![],
+        })
+    }
+
+    /// Much like `collapse_candidates_to_trait_pick`, this method allows us to collapse
+    /// multiple conflicting picks if there is one pick whose trait container is a subtrait
+    /// of the trait containers of all of the other picks.
+    ///
+    /// This implements RFC #3624.
+    fn collapse_candidates_to_subtrait_pick(
+        &self,
+        self_ty: Ty<'tcx>,
+        probes: &[(&Candidate<'tcx>, ProbeResult)],
+    ) -> Option<Pick<'tcx>> {
+        let mut child_candidate = probes[0].0;
+        let mut child_trait = child_candidate.item.trait_container(self.tcx)?;
+        let mut supertraits: SsoHashSet<_> = supertrait_def_ids(self.tcx, child_trait).collect();
+
+        let mut remaining_candidates: Vec<_> = probes[1..].iter().map(|&(p, _)| p).collect();
+        while !remaining_candidates.is_empty() {
+            let mut made_progress = false;
+            let mut next_round = vec![];
+
+            for remaining_candidate in remaining_candidates {
+                let remaining_trait = remaining_candidate.item.trait_container(self.tcx)?;
+                if supertraits.contains(&remaining_trait) {
+                    made_progress = true;
+                    continue;
+                }
+
+                // This pick is not a supertrait of the `child_pick`.
+                // Check if it's a subtrait of the `child_pick`, instead.
+                // If it is, then it must have been a subtrait of every
+                // other pick we've eliminated at this point. It will
+                // take over at this point.
+                let remaining_trait_supertraits: SsoHashSet<_> =
+                    supertrait_def_ids(self.tcx, remaining_trait).collect();
+                if remaining_trait_supertraits.contains(&child_trait) {
+                    child_candidate = remaining_candidate;
+                    child_trait = remaining_trait;
+                    supertraits = remaining_trait_supertraits;
+                    made_progress = true;
+                    continue;
+                }
+
+                // `child_pick` is not a supertrait of this pick.
+                // Don't bail here, since we may be comparing two supertraits
+                // of a common subtrait. These two supertraits won't be related
+                // at all, but we will pick them up next round when we find their
+                // child as we continue iterating in this round.
+                next_round.push(remaining_candidate);
+            }
+
+            if made_progress {
+                // If we've made progress, iterate again.
+                remaining_candidates = next_round;
+            } else {
+                // Otherwise, we must have at least two candidates which
+                // are not related to each other at all.
+                return None;
+            }
+        }
+
+        Some(Pick {
+            item: child_candidate.item,
+            kind: TraitPick,
+            import_ids: child_candidate.import_ids.clone(),
+            autoderefs: 0,
+            autoref_or_ptr_adjustment: None,
+            self_ty,
+            unstable_candidates: vec![],
+            shadowed_candidates: probes
+                .iter()
+                .map(|(c, _)| c.item)
+                .filter(|item| item.def_id != child_candidate.item.def_id)
+                .collect(),
+            receiver_steps: None,
         })
     }
 
@@ -2378,6 +2472,7 @@ impl<'tcx> Candidate<'tcx> {
                 InherentImplCandidate { receiver_steps, .. } => Some(receiver_steps),
                 _ => None,
             },
+            shadowed_candidates: vec![],
         }
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index dacbadbcd00..b54e430a9d9 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -1991,17 +1991,18 @@ struct InferBorrowKind<'tcx> {
 impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
     fn fake_read(
         &mut self,
-        place: &PlaceWithHirId<'tcx>,
+        place_with_id: &PlaceWithHirId<'tcx>,
         cause: FakeReadCause,
         diag_expr_id: HirId,
     ) {
-        let PlaceBase::Upvar(_) = place.place.base else { return };
+        let PlaceBase::Upvar(_) = place_with_id.place.base else { return };
 
         // We need to restrict Fake Read precision to avoid fake reading unsafe code,
         // such as deref of a raw pointer.
         let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::Immutable);
 
-        let (place, _) = restrict_capture_precision(place.place.clone(), dummy_capture_kind);
+        let (place, _) =
+            restrict_capture_precision(place_with_id.place.clone(), dummy_capture_kind);
 
         let (place, _) = restrict_repr_packed_field_ref_capture(place, dummy_capture_kind);
         self.fake_reads.push((place, cause, diag_expr_id));
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 9561b3de5f8..10bf4ec77ed 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -101,6 +101,8 @@ declare_lint_pass! {
         SINGLE_USE_LIFETIMES,
         SOFT_UNSTABLE,
         STABLE_FEATURES,
+        SUPERTRAIT_ITEM_SHADOWING_DEFINITION,
+        SUPERTRAIT_ITEM_SHADOWING_USAGE,
         TAIL_EXPR_DROP_ORDER,
         TEST_UNSTABLE_LINT,
         TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
@@ -4917,6 +4919,87 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `supertrait_item_shadowing_usage` lint detects when the
+    /// usage of an item that is provided by both a subtrait and supertrait
+    /// is shadowed, preferring the subtrait.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![feature(supertrait_item_shadowing)]
+    /// #![deny(supertrait_item_shadowing_usage)]
+    ///
+    /// trait Upstream {
+    ///     fn hello(&self) {}
+    /// }
+    /// impl<T> Upstream for T {}
+    ///
+    /// trait Downstream: Upstream {
+    ///     fn hello(&self) {}
+    /// }
+    /// impl<T> Downstream for T {}
+    ///
+    /// struct MyType;
+    /// MyType.hello();
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// RFC 3624 specified a heuristic in which a supertrait item would be
+    /// shadowed by a subtrait item when ambiguity occurs during item
+    /// selection. In order to mitigate side-effects of this happening
+    /// silently, this lint detects these cases when users want to deny them
+    /// or fix the call sites.
+    pub SUPERTRAIT_ITEM_SHADOWING_USAGE,
+    // FIXME(supertrait_item_shadowing): It is not decided if this should
+    // warn by default at the call site.
+    Allow,
+    "detects when a supertrait item is shadowed by a subtrait item",
+    @feature_gate = supertrait_item_shadowing;
+}
+
+declare_lint! {
+    /// The `supertrait_item_shadowing_definition` lint detects when the
+    /// definition of an item that is provided by both a subtrait and
+    /// supertrait is shadowed, preferring the subtrait.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![feature(supertrait_item_shadowing)]
+    /// #![deny(supertrait_item_shadowing_definition)]
+    ///
+    /// trait Upstream {
+    ///     fn hello(&self) {}
+    /// }
+    /// impl<T> Upstream for T {}
+    ///
+    /// trait Downstream: Upstream {
+    ///     fn hello(&self) {}
+    /// }
+    /// impl<T> Downstream for T {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// RFC 3624 specified a heuristic in which a supertrait item would be
+    /// shadowed by a subtrait item when ambiguity occurs during item
+    /// selection. In order to mitigate side-effects of this happening
+    /// silently, this lint detects these cases when users want to deny them
+    /// or fix their trait definitions.
+    pub SUPERTRAIT_ITEM_SHADOWING_DEFINITION,
+    // FIXME(supertrait_item_shadowing): It is not decided if this should
+    // warn by default at the usage site.
+    Allow,
+    "detects when a supertrait item is shadowed by a subtrait item",
+    @feature_gate = supertrait_item_shadowing;
+}
+
+declare_lint! {
     /// The `ptr_to_integer_transmute_in_consts` lint detects pointer to integer
     /// transmute in const functions and associated constants.
     ///
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 81fb918c604..d8a7c32a299 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2272,10 +2272,7 @@ impl<D: Decoder> Decodable<D> for EncodedMetadata {
         let len = d.read_usize();
         let mmap = if len > 0 {
             let mut mmap = MmapMut::map_anon(len).unwrap();
-            for _ in 0..len {
-                (&mut mmap[..]).write_all(&[d.read_u8()]).unwrap();
-            }
-            mmap.flush().unwrap();
+            mmap.copy_from_slice(d.read_raw_bytes(len));
             Some(mmap.make_read_only().unwrap())
         } else {
             None
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 69b2f92f716..aef56ea46e9 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -90,6 +90,7 @@ macro_rules! arena_types {
             [] autodiff_item: rustc_ast::expand::autodiff_attrs::AutoDiffItem,
             [] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::Symbol>,
             [] pats: rustc_middle::ty::PatternKind<'tcx>,
+            [] valtree: rustc_middle::ty::ValTreeKind<'tcx>,
 
             // Note that this deliberately duplicates items in the `rustc_hir::arena`,
             // since we need to allocate this type on both the `rustc_hir` arena
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 63e20fb0d64..795cfcef2d3 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -49,7 +49,6 @@ pub mod generic_graphviz;
 pub mod graphviz;
 pub mod interpret;
 pub mod mono;
-pub mod patch;
 pub mod pretty;
 mod query;
 mod statement;
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 478ac19d199..cd81890598e 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -116,7 +116,7 @@ rustc_queries! {
     }
 
     query early_lint_checks(_: ()) {
-        desc { "perform lints prior to macro expansion" }
+        desc { "perform lints prior to AST lowering" }
     }
 
     query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt {
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 6b6e0ffc656..41958949836 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -146,6 +146,12 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Pattern<'tcx> {
     }
 }
 
+impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::ValTree<'tcx> {
+    fn encode(&self, e: &mut E) {
+        self.0.0.encode(e);
+    }
+}
+
 impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ConstAllocation<'tcx> {
     fn encode(&self, e: &mut E) {
         self.inner().encode(e)
@@ -355,12 +361,9 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Pattern<'tcx> {
     }
 }
 
-impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [ty::ValTree<'tcx>] {
-    fn decode(decoder: &mut D) -> &'tcx Self {
-        decoder
-            .interner()
-            .arena
-            .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::ValTree<'tcx> {
+    fn decode(decoder: &mut D) -> Self {
+        decoder.interner().intern_valtree(Decodable::decode(decoder))
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index d77fb1cc91e..d30520a0222 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -20,7 +20,7 @@ pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
 pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
 
 #[cfg(target_pointer_width = "64")]
-rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
+rustc_data_structures::static_assert_size!(ConstKind<'_>, 24);
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
 #[rustc_pass_by_value]
@@ -190,7 +190,7 @@ impl<'tcx> Const<'tcx> {
             .size;
         ty::Const::new_value(
             tcx,
-            ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()),
+            ty::ValTree::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap()),
             ty,
         )
     }
@@ -198,7 +198,7 @@ impl<'tcx> Const<'tcx> {
     #[inline]
     /// Creates an interned zst constant.
     pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
-        ty::Const::new_value(tcx, ty::ValTree::zst(), ty)
+        ty::Const::new_value(tcx, ty::ValTree::zst(tcx), ty)
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index 5905076c4d0..72263d84580 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -1,4 +1,8 @@
-use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
+use std::fmt;
+use std::ops::Deref;
+
+use rustc_data_structures::intern::Interned;
+use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 
 use super::ScalarInt;
 use crate::mir::interpret::Scalar;
@@ -16,9 +20,9 @@ use crate::ty::{self, Ty, TyCtxt};
 ///
 /// `ValTree` does not have this problem with representation, as it only contains integers or
 /// lists of (nested) `ValTree`.
-#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
+#[derive(Clone, Debug, Hash, Eq, PartialEq)]
 #[derive(HashStable, TyEncodable, TyDecodable)]
-pub enum ValTree<'tcx> {
+pub enum ValTreeKind<'tcx> {
     /// integers, `bool`, `char` are represented as scalars.
     /// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values
     /// of these types have the same representation.
@@ -33,50 +37,90 @@ pub enum ValTree<'tcx> {
     /// the fields of the variant.
     ///
     /// ZST types are represented as an empty slice.
-    Branch(&'tcx [ValTree<'tcx>]),
+    Branch(Box<[ValTree<'tcx>]>),
 }
 
-impl<'tcx> ValTree<'tcx> {
-    pub fn zst() -> Self {
-        Self::Branch(&[])
-    }
-
+impl<'tcx> ValTreeKind<'tcx> {
     #[inline]
-    pub fn unwrap_leaf(self) -> ScalarInt {
+    pub fn unwrap_leaf(&self) -> ScalarInt {
         match self {
-            Self::Leaf(s) => s,
+            Self::Leaf(s) => *s,
             _ => bug!("expected leaf, got {:?}", self),
         }
     }
 
     #[inline]
-    pub fn unwrap_branch(self) -> &'tcx [Self] {
+    pub fn unwrap_branch(&self) -> &[ValTree<'tcx>] {
         match self {
-            Self::Branch(branch) => branch,
+            Self::Branch(branch) => &**branch,
             _ => bug!("expected branch, got {:?}", self),
         }
     }
 
-    pub fn from_raw_bytes<'a>(tcx: TyCtxt<'tcx>, bytes: &'a [u8]) -> Self {
-        let branches = bytes.iter().map(|b| Self::Leaf(ScalarInt::from(*b)));
-        let interned = tcx.arena.alloc_from_iter(branches);
+    pub fn try_to_scalar(&self) -> Option<Scalar> {
+        self.try_to_scalar_int().map(Scalar::Int)
+    }
 
-        Self::Branch(interned)
+    pub fn try_to_scalar_int(&self) -> Option<ScalarInt> {
+        match self {
+            Self::Leaf(s) => Some(*s),
+            Self::Branch(_) => None,
+        }
     }
 
-    pub fn from_scalar_int(i: ScalarInt) -> Self {
-        Self::Leaf(i)
+    pub fn try_to_branch(&self) -> Option<&[ValTree<'tcx>]> {
+        match self {
+            Self::Branch(branch) => Some(&**branch),
+            Self::Leaf(_) => None,
+        }
     }
+}
 
-    pub fn try_to_scalar(self) -> Option<Scalar> {
-        self.try_to_scalar_int().map(Scalar::Int)
+/// An interned valtree. Use this rather than `ValTreeKind`, whenever possible.
+///
+/// See the docs of [`ValTreeKind`] or the [dev guide] for an explanation of this type.
+///
+/// [dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html#valtrees
+#[derive(Copy, Clone, Hash, Eq, PartialEq)]
+#[derive(HashStable)]
+pub struct ValTree<'tcx>(pub(crate) Interned<'tcx, ValTreeKind<'tcx>>);
+
+impl<'tcx> ValTree<'tcx> {
+    /// Returns the zero-sized valtree: `Branch([])`.
+    pub fn zst(tcx: TyCtxt<'tcx>) -> Self {
+        tcx.consts.valtree_zst
     }
 
-    pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
-        match self {
-            Self::Leaf(s) => Some(s),
-            Self::Branch(_) => None,
-        }
+    pub fn is_zst(self) -> bool {
+        matches!(*self, ValTreeKind::Branch(box []))
+    }
+
+    pub fn from_raw_bytes(tcx: TyCtxt<'tcx>, bytes: &[u8]) -> Self {
+        let branches = bytes.iter().map(|&b| Self::from_scalar_int(tcx, b.into()));
+        Self::from_branches(tcx, branches)
+    }
+
+    pub fn from_branches(tcx: TyCtxt<'tcx>, branches: impl IntoIterator<Item = Self>) -> Self {
+        tcx.intern_valtree(ValTreeKind::Branch(branches.into_iter().collect()))
+    }
+
+    pub fn from_scalar_int(tcx: TyCtxt<'tcx>, i: ScalarInt) -> Self {
+        tcx.intern_valtree(ValTreeKind::Leaf(i))
+    }
+}
+
+impl<'tcx> Deref for ValTree<'tcx> {
+    type Target = &'tcx ValTreeKind<'tcx>;
+
+    #[inline]
+    fn deref(&self) -> &&'tcx ValTreeKind<'tcx> {
+        &self.0.0
+    }
+}
+
+impl fmt::Debug for ValTree<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        (**self).fmt(f)
     }
 }
 
@@ -84,7 +128,7 @@ impl<'tcx> ValTree<'tcx> {
 ///
 /// Represents a typed, fully evaluated constant.
 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
-#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
+#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable, Lift)]
 pub struct Value<'tcx> {
     pub ty: Ty<'tcx>,
     pub valtree: ValTree<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 9c07981a027..cb8dc692148 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -80,7 +80,7 @@ use crate::ty::{
     GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst, ParamTy,
     Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind,
     PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid,
-    Visibility,
+    ValTree, ValTreeKind, Visibility,
 };
 
 #[allow(rustc::usage_of_ty_tykind)]
@@ -807,6 +807,7 @@ pub struct CtxtInterners<'tcx> {
     local_def_ids: InternedSet<'tcx, List<LocalDefId>>,
     captures: InternedSet<'tcx, List<&'tcx ty::CapturedPlace<'tcx>>>,
     offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>,
+    valtree: InternedSet<'tcx, ty::ValTreeKind<'tcx>>,
 }
 
 impl<'tcx> CtxtInterners<'tcx> {
@@ -836,6 +837,7 @@ impl<'tcx> CtxtInterners<'tcx> {
             local_def_ids: Default::default(),
             captures: Default::default(),
             offset_of: Default::default(),
+            valtree: Default::default(),
         }
     }
 
@@ -1027,6 +1029,8 @@ pub struct CommonConsts<'tcx> {
     pub unit: Const<'tcx>,
     pub true_: Const<'tcx>,
     pub false_: Const<'tcx>,
+    /// Use [`ty::ValTree::zst`] instead.
+    pub(crate) valtree_zst: ValTree<'tcx>,
 }
 
 impl<'tcx> CommonTypes<'tcx> {
@@ -1130,19 +1134,30 @@ impl<'tcx> CommonConsts<'tcx> {
             )
         };
 
+        let mk_valtree = |v| {
+            ty::ValTree(Interned::new_unchecked(
+                interners.valtree.intern(v, |v| InternedInSet(interners.arena.alloc(v))).0,
+            ))
+        };
+
+        let valtree_zst = mk_valtree(ty::ValTreeKind::Branch(Box::default()));
+        let valtree_true = mk_valtree(ty::ValTreeKind::Leaf(ty::ScalarInt::TRUE));
+        let valtree_false = mk_valtree(ty::ValTreeKind::Leaf(ty::ScalarInt::FALSE));
+
         CommonConsts {
             unit: mk_const(ty::ConstKind::Value(ty::Value {
                 ty: types.unit,
-                valtree: ty::ValTree::zst(),
+                valtree: valtree_zst,
             })),
             true_: mk_const(ty::ConstKind::Value(ty::Value {
                 ty: types.bool,
-                valtree: ty::ValTree::Leaf(ty::ScalarInt::TRUE),
+                valtree: valtree_true,
             })),
             false_: mk_const(ty::ConstKind::Value(ty::Value {
                 ty: types.bool,
-                valtree: ty::ValTree::Leaf(ty::ScalarInt::FALSE),
+                valtree: valtree_false,
             })),
+            valtree_zst,
         }
     }
 }
@@ -2260,6 +2275,7 @@ nop_lift! { const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx> }
 nop_lift! { predicate; Predicate<'a> => Predicate<'tcx> }
 nop_lift! { predicate; Clause<'a> => Clause<'tcx> }
 nop_lift! { layout; Layout<'a> => Layout<'tcx> }
+nop_lift! { valtree; ValTree<'a> => ValTree<'tcx> }
 
 nop_list_lift! { type_lists; Ty<'a> => Ty<'tcx> }
 nop_list_lift! {
@@ -2270,26 +2286,6 @@ nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariabl
 // This is the impl for `&'a GenericArgs<'a>`.
 nop_list_lift! { args; GenericArg<'a> => GenericArg<'tcx> }
 
-macro_rules! nop_slice_lift {
-    ($ty:ty => $lifted:ty) => {
-        impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a [$ty] {
-            type Lifted = &'tcx [$lifted];
-            fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-                if self.is_empty() {
-                    return Some(&[]);
-                }
-                tcx.interners
-                    .arena
-                    .dropless
-                    .contains_slice(self)
-                    .then(|| unsafe { mem::transmute(self) })
-            }
-        }
-    };
-}
-
-nop_slice_lift! { ty::ValTree<'a> => ty::ValTree<'tcx> }
-
 macro_rules! sty_debug_print {
     ($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
         // Curious inner module to allow variant names to be used as
@@ -2534,6 +2530,7 @@ macro_rules! direct_interners {
 // crate only, and have a corresponding `mk_` function.
 direct_interners! {
     region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
+    valtree: pub(crate) intern_valtree(ValTreeKind<'tcx>): ValTree -> ValTree<'tcx>,
     pat: pub mk_pat(PatternKind<'tcx>): Pattern -> Pattern<'tcx>,
     const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
     layout: pub mk_layout(LayoutData<FieldIdx, VariantIdx>): Layout -> Layout<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 6fe1502c66d..52cb8f57a88 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -60,7 +60,8 @@ pub use self::closure::{
     place_to_string_for_capture,
 };
 pub use self::consts::{
-    Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, Value,
+    Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, ValTreeKind,
+    Value,
 };
 pub use self::context::{
     CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 2c1adc2bcad..7166c284c3d 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1639,14 +1639,12 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         match ty.kind() {
             // Byte strings (&[u8; N])
             ty::Ref(_, inner, _) => {
-                if let ty::Array(elem, len) = inner.kind()
+                if let ty::Array(elem, ct_len) = inner.kind()
                     && let ty::Uint(ty::UintTy::U8) = elem.kind()
-                    && let ty::ConstKind::Value(cv) = len.kind()
-                    && let ty::ValTree::Leaf(int) = cv.valtree
+                    && let Some(len) = ct_len.try_to_target_usize(self.tcx())
                 {
                     match self.tcx().try_get_global_alloc(prov.alloc_id()) {
                         Some(GlobalAlloc::Memory(alloc)) => {
-                            let len = int.to_bits(self.tcx().data_layout.pointer_size);
                             let range = AllocRange { start: offset, size: Size::from_bytes(len) };
                             if let Ok(byte_str) =
                                 alloc.inner().get_bytes_strip_provenance(&self.tcx(), range)
@@ -1800,8 +1798,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         }
 
         let u8_type = self.tcx().types.u8;
-        match (cv.valtree, *cv.ty.kind()) {
-            (ty::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) => match inner_ty.kind() {
+        match (*cv.valtree, *cv.ty.kind()) {
+            (ty::ValTreeKind::Branch(_), ty::Ref(_, inner_ty, _)) => match inner_ty.kind() {
                 ty::Slice(t) if *t == u8_type => {
                     let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
                         bug!(
@@ -1826,7 +1824,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     return Ok(());
                 }
             },
-            (ty::ValTree::Branch(_), ty::Array(t, _)) if t == u8_type => {
+            (ty::ValTreeKind::Branch(_), ty::Array(t, _)) if t == u8_type => {
                 let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
                     bug!("expected to convert valtree to raw bytes for type {:?}", t)
                 });
@@ -1835,7 +1833,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 return Ok(());
             }
             // Aggregates, printed as array/tuple/struct/variant construction syntax.
-            (ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
+            (ty::ValTreeKind::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
                 let contents = self.tcx().destructure_const(ty::Const::new_value(
                     self.tcx(),
                     cv.valtree,
@@ -1891,12 +1889,12 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 }
                 return Ok(());
             }
-            (ty::ValTree::Leaf(leaf), ty::Ref(_, inner_ty, _)) => {
+            (ty::ValTreeKind::Leaf(leaf), ty::Ref(_, inner_ty, _)) => {
                 p!(write("&"));
-                return self.pretty_print_const_scalar_int(leaf, inner_ty, print_ty);
+                return self.pretty_print_const_scalar_int(*leaf, inner_ty, print_ty);
             }
-            (ty::ValTree::Leaf(leaf), _) => {
-                return self.pretty_print_const_scalar_int(leaf, cv.ty, print_ty);
+            (ty::ValTreeKind::Leaf(leaf), _) => {
+                return self.pretty_print_const_scalar_int(*leaf, cv.ty, print_ty);
             }
             (_, ty::FnDef(def_id, args)) => {
                 // Never allowed today, but we still encounter them in invalid const args.
@@ -1909,7 +1907,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         }
 
         // fallback
-        if cv.valtree == ty::ValTree::zst() {
+        if cv.valtree.is_zst() {
             p!(write("<ZST>"));
         } else {
             p!(write("{:?}", cv.valtree));
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index c33f952fc86..6c15e033bb0 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -165,13 +165,9 @@ impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> {
 impl<'tcx> fmt::Debug for ty::Const<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // If this is a value, we spend some effort to make it look nice.
-        if let ConstKind::Value(_) = self.kind() {
+        if let ConstKind::Value(cv) = self.kind() {
             return ty::tls::with(move |tcx| {
-                // ValTrees aren't interned, so we lift the entire constant.
-                let lifted = tcx.lift(*self).unwrap();
-                let ConstKind::Value(cv) = lifted.kind() else {
-                    bug!("we checked that this is a valtree")
-                };
+                let cv = tcx.lift(cv).unwrap();
                 let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
                 cx.pretty_print_const_valtree(cv, /*print_ty*/ true)?;
                 f.write_str(&cx.into_buffer())
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index f303053390c..b3210813703 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -48,7 +48,7 @@ pub(crate) fn lit_to_const<'tcx>(
             ty::ValTree::from_raw_bytes(tcx, bytes)
         }
         (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
-            ty::ValTree::from_scalar_int((*n).into())
+            ty::ValTree::from_scalar_int(tcx, (*n).into())
         }
         (ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
         {
@@ -57,23 +57,23 @@ pub(crate) fn lit_to_const<'tcx>(
         }
         (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => {
             let scalar_int = trunc(n.get(), *ui);
-            ty::ValTree::from_scalar_int(scalar_int)
+            ty::ValTree::from_scalar_int(tcx, scalar_int)
         }
         (ast::LitKind::Int(n, _), ty::Int(i)) => {
             let scalar_int = trunc(
                 if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() },
                 i.to_unsigned(),
             );
-            ty::ValTree::from_scalar_int(scalar_int)
+            ty::ValTree::from_scalar_int(tcx, scalar_int)
         }
-        (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()),
+        (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int(tcx, (*b).into()),
         (ast::LitKind::Float(n, _), ty::Float(fty)) => {
             let bits = parse_float_into_scalar(*n, *fty, neg).unwrap_or_else(|| {
                 tcx.dcx().bug(format!("couldn't parse float literal: {:?}", lit_input.lit))
             });
-            ty::ValTree::from_scalar_int(bits)
+            ty::ValTree::from_scalar_int(tcx, bits)
         }
-        (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()),
+        (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int(tcx, (*c).into()),
         (ast::LitKind::Err(guar), _) => return ty::Const::new_error(tcx, *guar),
         _ => return ty::Const::new_misc_error(tcx),
     };
diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
index e5cddd0e5e4..496a342cf4c 100644
--- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
+++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
@@ -3,7 +3,26 @@ use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind};
 use tracing::debug;
 
 use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex};
-use crate::elaborate_drops::DropFlagState;
+
+/// The value of an inserted drop flag.
+#[derive(Debug, PartialEq, Eq, Copy, Clone)]
+pub enum DropFlagState {
+    /// The tracked value is initialized and needs to be dropped when leaving its scope.
+    Present,
+
+    /// The tracked value is uninitialized or was moved out of and does not need to be dropped when
+    /// leaving its scope.
+    Absent,
+}
+
+impl DropFlagState {
+    pub fn value(self) -> bool {
+        match self {
+            DropFlagState::Present => true,
+            DropFlagState::Absent => false,
+        }
+    }
+}
 
 pub fn move_path_children_matching<'tcx, F>(
     move_data: &MoveData<'tcx>,
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index 760f94af52d..3be450a0b3f 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -9,7 +9,7 @@ use rustc_middle::ty::util::Discr;
 use rustc_middle::ty::{self, TyCtxt};
 use tracing::{debug, instrument};
 
-use crate::elaborate_drops::DropFlagState;
+use crate::drop_flag_effects::DropFlagState;
 use crate::framework::SwitchIntTarget;
 use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
 use crate::{
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 0cc79b0c939..a8a56baa1ff 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty;
 // Please change the public `use` directives cautiously, as they might be used by external tools.
 // See issue #120130.
 pub use self::drop_flag_effects::{
-    drop_flag_effects_for_function_entry, drop_flag_effects_for_location,
+    DropFlagState, drop_flag_effects_for_function_entry, drop_flag_effects_for_location,
     move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
 };
 pub use self::framework::{
@@ -26,7 +26,6 @@ use self::move_paths::MoveData;
 
 pub mod debuginfo;
 mod drop_flag_effects;
-pub mod elaborate_drops;
 mod errors;
 mod framework;
 pub mod impls;
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 8716fd1c098..b33326cb873 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
@@ -1,8 +1,8 @@
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
 use tracing::debug;
 
+use crate::patch::MirPatch;
 use crate::util;
 
 /// This pass moves values being dropped that are within a packed
diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
index e41f47db545..b5cd4133459 100644
--- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
+++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
@@ -1,8 +1,9 @@
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::MutVisitor;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
+use crate::patch::MirPatch;
+
 pub(super) struct Subtyper;
 
 struct SubTypeChecker<'a, 'tcx> {
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index a9bdbeb9cb8..afc49c5cc54 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -1061,9 +1061,8 @@ fn insert_switch<'tcx>(
 }
 
 fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    use rustc_middle::mir::patch::MirPatch;
-    use rustc_mir_dataflow::elaborate_drops::{Unwind, elaborate_drop};
-
+    use crate::elaborate_drop::{Unwind, elaborate_drop};
+    use crate::patch::MirPatch;
     use crate::shim::DropShimElaborator;
 
     // Note that `elaborate_drops` only drops the upvars of a coroutine, and
diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs
index 6f9984d5d0a..039f346495b 100644
--- a/compiler/rustc_mir_transform/src/coverage/counters.rs
+++ b/compiler/rustc_mir_transform/src/coverage/counters.rs
@@ -114,12 +114,8 @@ pub(crate) fn transcribe_counters(
         let mut new_counters_for_sites = |sites: Vec<BasicCoverageBlock>| {
             sites.into_iter().map(|node| new.ensure_phys_counter(node)).collect::<Vec<_>>()
         };
-        let mut pos = new_counters_for_sites(pos);
-        let mut neg = new_counters_for_sites(neg);
-
-        // These sorts are also not strictly necessary; see above.
-        pos.sort();
-        neg.sort();
+        let pos = new_counters_for_sites(pos);
+        let neg = new_counters_for_sites(neg);
 
         let pos_counter = new.make_sum(&pos).unwrap_or(CovTerm::Zero);
         let new_counter = new.make_subtracted_sum(pos_counter, &neg);
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index cd89fbe772d..ef86358b205 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -123,11 +123,20 @@ fn coverage_ids_info<'tcx>(
         }
     }
 
-    // FIXME(Zalathar): It should be possible to sort `priority_list[1..]` by
-    // `!bcbs_seen.contains(bcb)` to simplify the mappings even further, at the
-    // expense of some churn in the tests. When doing so, also consider removing
-    // the sorts in `transcribe_counters`.
-    let node_counters = make_node_counters(&fn_cov_info.node_flow_data, &fn_cov_info.priority_list);
+    // Clone the priority list so that we can re-sort it.
+    let mut priority_list = fn_cov_info.priority_list.clone();
+    // The first ID in the priority list represents the synthetic "sink" node,
+    // and must remain first so that it _never_ gets a physical counter.
+    debug_assert_eq!(priority_list[0], priority_list.iter().copied().max().unwrap());
+    assert!(!bcbs_seen.contains(priority_list[0]));
+    // Partition the priority list, so that unreachable nodes (removed by MIR opts)
+    // are sorted later and therefore are _more_ likely to get a physical counter.
+    // This is counter-intuitive, but it means that `transcribe_counters` can
+    // easily skip those unused physical counters and replace them with zero.
+    // (The original ordering remains in effect within both partitions.)
+    priority_list[1..].sort_by_key(|&bcb| !bcbs_seen.contains(bcb));
+
+    let node_counters = make_node_counters(&fn_cov_info.node_flow_data, &priority_list);
     let coverage_counters = transcribe_counters(&node_counters, &bcb_needs_counter, &bcbs_seen);
 
     let CoverageCounters {
diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs
index a54bdaa4075..bc914ea6564 100644
--- a/compiler/rustc_mir_transform/src/deref_separator.rs
+++ b/compiler/rustc_mir_transform/src/deref_separator.rs
@@ -1,9 +1,10 @@
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
+use crate::patch::MirPatch;
+
 pub(super) struct Derefer;
 
 struct DerefChecker<'a, 'tcx> {
diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
index eb335a1e4a7..57f7893be1b 100644
--- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
+++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
@@ -1,11 +1,11 @@
 use std::fmt::Debug;
 
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{Ty, TyCtxt};
 use tracing::trace;
 
 use super::simplify::simplify_cfg;
+use crate::patch::MirPatch;
 
 /// This pass optimizes something like
 /// ```ignore (syntax-highlighting-only)
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 6d3b5d9851b..5c344a80688 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -4,12 +4,13 @@
 
 use rustc_abi::FieldIdx;
 use rustc_hir::def_id::DefId;
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::MutVisitor;
 use rustc_middle::mir::*;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{Ty, TyCtxt};
 
+use crate::patch::MirPatch;
+
 /// Constructs the types used when accessing a Box's pointer
 fn build_ptr_tys<'tcx>(
     tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs
index c1c47ecccf3..ed4903017f3 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs
@@ -3,7 +3,6 @@ use std::{fmt, iter, mem};
 use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
 use rustc_hir::lang_items::LangItem;
 use rustc_index::Idx;
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::span_bug;
 use rustc_middle::ty::adjustment::PointerCoercion;
@@ -13,29 +12,11 @@ use rustc_span::DUMMY_SP;
 use rustc_span::source_map::Spanned;
 use tracing::{debug, instrument};
 
-/// The value of an inserted drop flag.
-#[derive(Debug, PartialEq, Eq, Copy, Clone)]
-pub enum DropFlagState {
-    /// The tracked value is initialized and needs to be dropped when leaving its scope.
-    Present,
-
-    /// The tracked value is uninitialized or was moved out of and does not need to be dropped when
-    /// leaving its scope.
-    Absent,
-}
-
-impl DropFlagState {
-    pub fn value(self) -> bool {
-        match self {
-            DropFlagState::Present => true,
-            DropFlagState::Absent => false,
-        }
-    }
-}
+use crate::patch::MirPatch;
 
 /// Describes how/if a value should be dropped.
 #[derive(Debug)]
-pub enum DropStyle {
+pub(crate) enum DropStyle {
     /// The value is already dead at the drop location, no drop will be executed.
     Dead,
 
@@ -56,7 +37,7 @@ pub enum DropStyle {
 
 /// Which drop flags to affect/check with an operation.
 #[derive(Debug)]
-pub enum DropFlagMode {
+pub(crate) enum DropFlagMode {
     /// Only affect the top-level drop flag, not that of any contained fields.
     Shallow,
     /// Affect all nested drop flags in addition to the top-level one.
@@ -65,7 +46,7 @@ pub enum DropFlagMode {
 
 /// Describes if unwinding is necessary and where to unwind to if a panic occurs.
 #[derive(Copy, Clone, Debug)]
-pub enum Unwind {
+pub(crate) enum Unwind {
     /// Unwind to this block.
     To(BasicBlock),
     /// Already in an unwind path, any panic will cause an abort.
@@ -98,7 +79,7 @@ impl Unwind {
     }
 }
 
-pub trait DropElaborator<'a, 'tcx>: fmt::Debug {
+pub(crate) trait DropElaborator<'a, 'tcx>: fmt::Debug {
     /// The type representing paths that can be moved out of.
     ///
     /// Users can move out of individual fields of a struct, such as `a.b.c`. This type is used to
@@ -177,7 +158,7 @@ where
 /// value.
 ///
 /// When this returns, the MIR patch in the `elaborator` contains the necessary changes.
-pub fn elaborate_drop<'b, 'tcx, D>(
+pub(crate) fn elaborate_drop<'b, 'tcx, D>(
     elaborator: &mut D,
     source_info: SourceInfo,
     place: Place<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index cb869160c80..2d74fcff415 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -3,21 +3,20 @@ use std::fmt;
 use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_index::IndexVec;
 use rustc_index::bit_set::DenseBitSet;
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_mir_dataflow::elaborate_drops::{
-    DropElaborator, DropFlagMode, DropFlagState, DropStyle, Unwind, elaborate_drop,
-};
 use rustc_mir_dataflow::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
 use rustc_mir_dataflow::{
-    Analysis, MoveDataTypingEnv, ResultsCursor, on_all_children_bits, on_lookup_result_bits,
+    Analysis, DropFlagState, MoveDataTypingEnv, ResultsCursor, on_all_children_bits,
+    on_lookup_result_bits,
 };
 use rustc_span::Span;
 use tracing::{debug, instrument};
 
 use crate::deref_separator::deref_finder;
+use crate::elaborate_drop::{DropElaborator, DropFlagMode, DropStyle, Unwind, elaborate_drop};
+use crate::patch::MirPatch;
 
 /// 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
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index ab617e2ce6f..1f8392b2118 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -49,8 +49,7 @@ impl<'tcx> crate::MirPass<'tcx> for Inline {
         match sess.mir_opt_level() {
             0 | 1 => false,
             2 => {
-                (sess.opts.optimize == OptLevel::Default
-                    || sess.opts.optimize == OptLevel::Aggressive)
+                (sess.opts.optimize == OptLevel::More || sess.opts.optimize == OptLevel::Aggressive)
                     && sess.opts.incremental == None
             }
             _ => true,
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 397d21a857f..46abdcb2a87 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -49,10 +49,12 @@ mod check_pointers;
 mod cost_checker;
 mod cross_crate_inline;
 mod deduce_param_attrs;
+mod elaborate_drop;
 mod errors;
 mod ffi_unwind_calls;
 mod lint;
 mod lint_tail_expr_drop_order;
+mod patch;
 mod shim;
 mod ssa;
 
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 500116580d5..9db37bf5a07 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -2,7 +2,6 @@ use std::iter;
 
 use rustc_abi::Integer;
 use rustc_index::IndexSlice;
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
 use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
@@ -10,6 +9,7 @@ use rustc_type_ir::TyKind::*;
 use tracing::instrument;
 
 use super::simplify::simplify_cfg;
+use crate::patch::MirPatch;
 
 pub(super) struct MatchBranchSimplification;
 
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_mir_transform/src/patch.rs
index 748797fbb8d..72cd9c224f6 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_mir_transform/src/patch.rs
@@ -1,11 +1,13 @@
+use rustc_index::{Idx, IndexVec};
+use rustc_middle::mir::*;
+use rustc_middle::ty::Ty;
+use rustc_span::Span;
 use tracing::debug;
 
-use crate::mir::*;
-
 /// This struct represents a patch to MIR, which can add
 /// new statements and basic blocks and patch over block
 /// terminators.
-pub struct MirPatch<'tcx> {
+pub(crate) struct MirPatch<'tcx> {
     patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>,
     new_blocks: Vec<BasicBlockData<'tcx>>,
     new_statements: Vec<(Location, StatementKind<'tcx>)>,
@@ -22,7 +24,7 @@ pub struct MirPatch<'tcx> {
 }
 
 impl<'tcx> MirPatch<'tcx> {
-    pub fn new(body: &Body<'tcx>) -> Self {
+    pub(crate) fn new(body: &Body<'tcx>) -> Self {
         let mut result = MirPatch {
             patch_map: IndexVec::from_elem(None, &body.basic_blocks),
             new_blocks: vec![],
@@ -69,7 +71,7 @@ impl<'tcx> MirPatch<'tcx> {
         result
     }
 
-    pub fn resume_block(&mut self) -> BasicBlock {
+    pub(crate) fn resume_block(&mut self) -> BasicBlock {
         if let Some(bb) = self.resume_block {
             return bb;
         }
@@ -86,7 +88,7 @@ impl<'tcx> MirPatch<'tcx> {
         bb
     }
 
-    pub fn unreachable_cleanup_block(&mut self) -> BasicBlock {
+    pub(crate) fn unreachable_cleanup_block(&mut self) -> BasicBlock {
         if let Some(bb) = self.unreachable_cleanup_block {
             return bb;
         }
@@ -103,7 +105,7 @@ impl<'tcx> MirPatch<'tcx> {
         bb
     }
 
-    pub fn unreachable_no_cleanup_block(&mut self) -> BasicBlock {
+    pub(crate) fn unreachable_no_cleanup_block(&mut self) -> BasicBlock {
         if let Some(bb) = self.unreachable_no_cleanup_block {
             return bb;
         }
@@ -120,7 +122,7 @@ impl<'tcx> MirPatch<'tcx> {
         bb
     }
 
-    pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock {
+    pub(crate) fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock {
         if let Some((cached_bb, cached_reason)) = self.terminate_block
             && reason == cached_reason
         {
@@ -139,19 +141,11 @@ impl<'tcx> MirPatch<'tcx> {
         bb
     }
 
-    pub fn is_patched(&self, bb: BasicBlock) -> bool {
+    pub(crate) fn is_patched(&self, bb: BasicBlock) -> bool {
         self.patch_map[bb].is_some()
     }
 
-    pub fn terminator_loc(&self, body: &Body<'tcx>, bb: BasicBlock) -> Location {
-        let offset = match bb.index().checked_sub(body.basic_blocks.len()) {
-            Some(index) => self.new_blocks[index].statements.len(),
-            None => body[bb].statements.len(),
-        };
-        Location { block: bb, statement_index: offset }
-    }
-
-    pub fn new_local_with_info(
+    pub(crate) fn new_local_with_info(
         &mut self,
         ty: Ty<'tcx>,
         span: Span,
@@ -165,14 +159,14 @@ impl<'tcx> MirPatch<'tcx> {
         Local::new(index)
     }
 
-    pub fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
+    pub(crate) fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
         let index = self.next_local;
         self.next_local += 1;
         self.new_locals.push(LocalDecl::new(ty, span));
         Local::new(index)
     }
 
-    pub fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
+    pub(crate) fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
         let block = BasicBlock::new(self.patch_map.len());
         debug!("MirPatch: new_block: {:?}: {:?}", block, data);
         self.new_blocks.push(data);
@@ -180,22 +174,22 @@ impl<'tcx> MirPatch<'tcx> {
         block
     }
 
-    pub fn patch_terminator(&mut self, block: BasicBlock, new: TerminatorKind<'tcx>) {
+    pub(crate) fn patch_terminator(&mut self, block: BasicBlock, new: TerminatorKind<'tcx>) {
         assert!(self.patch_map[block].is_none());
         debug!("MirPatch: patch_terminator({:?}, {:?})", block, new);
         self.patch_map[block] = Some(new);
     }
 
-    pub fn add_statement(&mut self, loc: Location, stmt: StatementKind<'tcx>) {
+    pub(crate) fn add_statement(&mut self, loc: Location, stmt: StatementKind<'tcx>) {
         debug!("MirPatch: add_statement({:?}, {:?})", loc, stmt);
         self.new_statements.push((loc, stmt));
     }
 
-    pub fn add_assign(&mut self, loc: Location, place: Place<'tcx>, rv: Rvalue<'tcx>) {
+    pub(crate) fn add_assign(&mut self, loc: Location, place: Place<'tcx>, rv: Rvalue<'tcx>) {
         self.add_statement(loc, StatementKind::Assign(Box::new((place, rv))));
     }
 
-    pub fn apply(self, body: &mut Body<'tcx>) {
+    pub(crate) fn apply(self, body: &mut Body<'tcx>) {
         debug!(
             "MirPatch: {:?} new temps, starting from index {}: {:?}",
             self.new_locals.len(),
@@ -241,14 +235,14 @@ impl<'tcx> MirPatch<'tcx> {
         }
     }
 
-    pub fn source_info_for_index(data: &BasicBlockData<'_>, loc: Location) -> SourceInfo {
+    fn source_info_for_index(data: &BasicBlockData<'_>, loc: Location) -> SourceInfo {
         match data.statements.get(loc.statement_index) {
             Some(stmt) => stmt.source_info,
             None => data.terminator().source_info,
         }
     }
 
-    pub fn source_info_for_location(&self, body: &Body<'tcx>, loc: Location) -> SourceInfo {
+    pub(crate) fn source_info_for_location(&self, body: &Body<'tcx>, loc: Location) -> SourceInfo {
         let data = match loc.block.index().checked_sub(body.basic_blocks.len()) {
             Some(new) => &self.new_blocks[new],
             None => &body[loc.block],
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 9cdd52bec7b..1dd34005d66 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -1,10 +1,11 @@
 use rustc_index::bit_set::DenseBitSet;
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use rustc_target::spec::PanicStrategy;
 use tracing::debug;
 
+use crate::patch::MirPatch;
+
 /// A pass that removes noop landing pads and replaces jumps to them with
 /// `UnwindAction::Continue`. This is important because otherwise LLVM generates
 /// terrible code for these.
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index f7ec0f740d3..e8d86bad987 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -6,7 +6,6 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::{Idx, IndexVec};
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::adjustment::PointerCoercion;
@@ -14,11 +13,12 @@ use rustc_middle::ty::{
     self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, GenericArgs, Ty, TyCtxt,
 };
 use rustc_middle::{bug, span_bug};
-use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle};
 use rustc_span::source_map::Spanned;
 use rustc_span::{DUMMY_SP, Span};
 use tracing::{debug, instrument};
 
+use crate::elaborate_drop::{DropElaborator, DropFlagMode, DropStyle, Unwind, elaborate_drop};
+use crate::patch::MirPatch;
 use crate::{
     abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator, inline,
     instsimplify, mentioned_items, pass_manager as pm, remove_noop_landing_pads, simplify,
@@ -283,13 +283,13 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
                 DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, typing_env };
             let dropee = tcx.mk_place_deref(dropee_ptr);
             let resume_block = elaborator.patch.resume_block();
-            elaborate_drops::elaborate_drop(
+            elaborate_drop(
                 &mut elaborator,
                 source_info,
                 dropee,
                 (),
                 return_block,
-                elaborate_drops::Unwind::To(resume_block),
+                Unwind::To(resume_block),
                 START_BLOCK,
             );
             elaborator.patch
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 92e5c8a9ca4..28de99f9193 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -4,13 +4,14 @@ use rustc_hir::LangItem;
 use rustc_index::IndexVec;
 use rustc_index::bit_set::{DenseBitSet, GrowableBitSet};
 use rustc_middle::bug;
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields};
 use tracing::{debug, instrument};
 
+use crate::patch::MirPatch;
+
 pub(super) struct ScalarReplacementOfAggregates;
 
 impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 1ff7043ed14..6ccec5b6f21 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -3,7 +3,6 @@
 use rustc_abi::Variants;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::bug;
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::{
     BasicBlock, BasicBlockData, BasicBlocks, Body, Local, Operand, Rvalue, StatementKind,
     TerminatorKind,
@@ -12,6 +11,8 @@ use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::{Ty, TyCtxt};
 use tracing::trace;
 
+use crate::patch::MirPatch;
+
 pub(super) struct UnreachableEnumBranching;
 
 fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option<Local> {
diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index 1e5d9469c03..13fb5b3e56f 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -6,10 +6,11 @@ use rustc_abi::Size;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
 
+use crate::patch::MirPatch;
+
 pub(super) struct UnreachablePropagation;
 
 impl crate::MirPass<'_> for UnreachablePropagation {
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index ae31ed59391..e4a733fcbce 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1509,6 +1509,13 @@ impl<'v> RootCollector<'_, 'v> {
                         }
                         _ => unreachable!(),
                     };
+                    let Ok(instance) = self.tcx.try_normalize_erasing_regions(
+                        ty::TypingEnv::fully_monomorphized(),
+                        instance,
+                    ) else {
+                        // Don't ICE on an impossible-to-normalize closure.
+                        return;
+                    };
                     let mono_item = create_fn_mono_item(self.tcx, instance, DUMMY_SP);
                     if mono_item.node.is_instantiable(self.tcx) {
                         self.output.push(mono_item);
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index a3274fb4011..b0f59ed1474 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -6,7 +6,6 @@ use derive_where::derive_where;
 use rustc_type_ir::fold::TypeFoldable;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
-use rustc_type_ir::solve::inspect;
 use rustc_type_ir::visit::TypeVisitableExt as _;
 use rustc_type_ir::{self as ty, Interner, TypingMode, Upcast as _, elaborate};
 use tracing::{debug, instrument};
@@ -297,25 +296,6 @@ where
         let Ok(normalized_self_ty) =
             self.structurally_normalize_ty(goal.param_env, goal.predicate.self_ty())
         else {
-            // FIXME: We register a fake candidate when normalization fails so that
-            // we can point at the reason for *why*. I'm tempted to say that this
-            // is the wrong way to do this, though.
-            let result =
-                self.probe(|&result| inspect::ProbeKind::RigidAlias { result }).enter(|this| {
-                    let normalized_ty = this.next_ty_infer();
-                    let alias_relate_goal = Goal::new(
-                        this.cx(),
-                        goal.param_env,
-                        ty::PredicateKind::AliasRelate(
-                            goal.predicate.self_ty().into(),
-                            normalized_ty.into(),
-                            ty::AliasRelationDirection::Equate,
-                        ),
-                    );
-                    this.add_goal(GoalSource::AliasWellFormed, alias_relate_goal);
-                    this.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
-                });
-            assert_eq!(result, Err(NoSolution));
             return vec![];
         };
 
@@ -797,11 +777,12 @@ where
     /// treat the alias as rigid.
     ///
     /// See trait-system-refactor-initiative#124 for more details.
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "debug", skip(self, inject_normalize_to_rigid_candidate), ret)]
     pub(super) fn merge_candidates(
         &mut self,
         proven_via: Option<TraitGoalProvenVia>,
         candidates: Vec<Candidate<I>>,
+        inject_normalize_to_rigid_candidate: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
     ) -> QueryResult<I> {
         let Some(proven_via) = proven_via else {
             // We don't care about overflow. If proving the trait goal overflowed, then
@@ -818,13 +799,27 @@ where
             // FIXME(const_trait_impl): should this behavior also be used by
             // constness checking. Doing so is *at least theoretically* breaking,
             // see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
-            TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => candidates
-                .iter()
-                .filter(|c| {
-                    matches!(c.source, CandidateSource::AliasBound | CandidateSource::ParamEnv(_))
-                })
-                .map(|c| c.result)
-                .collect(),
+            TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
+                let mut candidates_from_env: Vec<_> = candidates
+                    .iter()
+                    .filter(|c| {
+                        matches!(
+                            c.source,
+                            CandidateSource::AliasBound | CandidateSource::ParamEnv(_)
+                        )
+                    })
+                    .map(|c| c.result)
+                    .collect();
+
+                // If the trait goal has been proven by using the environment, we want to treat
+                // aliases as rigid if there are no applicable projection bounds in the environment.
+                if candidates_from_env.is_empty() {
+                    if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
+                        candidates_from_env.push(response);
+                    }
+                }
+                candidates_from_env
+            }
             TraitGoalProvenVia::Misc => candidates.iter().map(|c| c.result).collect(),
         };
 
diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
index eb398e8724d..0b61c368d8e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
@@ -405,6 +405,6 @@ where
                 goal.with(ecx.cx(), goal.predicate.trait_ref);
             ecx.compute_trait_goal(trait_goal)
         })?;
-        self.merge_candidates(proven_via, candidates)
+        self.merge_candidates(proven_via, candidates, |_ecx| Err(NoSolution))
     }
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index 1d0ec7b45ca..88002e1a88a 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -30,75 +30,26 @@ where
     ) -> QueryResult<I> {
         self.set_is_normalizes_to_goal();
         debug_assert!(self.term_is_fully_unconstrained(goal));
-        let normalize_result = self
-            .probe(|&result| ProbeKind::TryNormalizeNonRigid { result })
-            .enter(|this| this.normalize_at_least_one_step(goal));
-
-        match normalize_result {
-            Ok(res) => Ok(res),
-            Err(NoSolution) => {
-                self.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| {
-                    let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal;
-                    this.add_rigid_constraints(param_env, alias)?;
-                    this.relate_rigid_alias_non_alias(param_env, alias, ty::Invariant, term)?;
-                    this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-                })
-            }
-        }
-    }
-
-    /// Register any obligations that are used to validate that an alias should be
-    /// treated as rigid.
-    ///
-    /// An alias may be considered rigid if it fails normalization, but we also don't
-    /// want to consider aliases that are not well-formed to be rigid simply because
-    /// they fail normalization.
-    ///
-    /// For example, some `<T as Trait>::Assoc` where `T: Trait` does not hold, or an
-    /// opaque type whose hidden type doesn't actually satisfy the opaque item bounds.
-    fn add_rigid_constraints(
-        &mut self,
-        param_env: I::ParamEnv,
-        rigid_alias: ty::AliasTerm<I>,
-    ) -> Result<(), NoSolution> {
-        let cx = self.cx();
-        match rigid_alias.kind(cx) {
-            // Projections are rigid only if their trait ref holds,
-            // and the GAT where-clauses hold.
-            ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
-                let trait_ref = rigid_alias.trait_ref(cx);
-                self.add_goal(GoalSource::AliasWellFormed, Goal::new(cx, param_env, trait_ref));
-                Ok(())
-            }
-            ty::AliasTermKind::OpaqueTy => {
-                if self.opaque_type_is_rigid(rigid_alias.def_id) {
-                    Ok(())
-                } else {
-                    Err(NoSolution)
-                }
-            }
-            // FIXME(generic_const_exprs): we would need to support generic consts here
-            ty::AliasTermKind::UnevaluatedConst => Err(NoSolution),
-            // Inherent and weak types are never rigid. This type must not be well-formed.
-            ty::AliasTermKind::WeakTy | ty::AliasTermKind::InherentTy => Err(NoSolution),
-        }
-    }
-
-    /// Normalize the given alias by at least one step. If the alias is rigid, this
-    /// returns `NoSolution`.
-    #[instrument(level = "trace", skip(self), ret)]
-    fn normalize_at_least_one_step(&mut self, goal: Goal<I, NormalizesTo<I>>) -> QueryResult<I> {
         let cx = self.cx();
         match goal.predicate.alias.kind(cx) {
             ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
                 let candidates = self.assemble_and_evaluate_candidates(goal);
+                let trait_ref = goal.predicate.alias.trait_ref(cx);
                 let (_, proven_via) =
                     self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
-                        let trait_goal: Goal<I, ty::TraitPredicate<I>> =
-                            goal.with(cx, goal.predicate.alias.trait_ref(cx));
+                        let trait_goal: Goal<I, ty::TraitPredicate<I>> = goal.with(cx, trait_ref);
                         ecx.compute_trait_goal(trait_goal)
                     })?;
-                self.merge_candidates(proven_via, candidates)
+                self.merge_candidates(proven_via, candidates, |ecx| {
+                    ecx.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| {
+                        this.structurally_instantiate_normalizes_to_term(
+                            goal,
+                            goal.predicate.alias,
+                        );
+                        this.add_goal(GoalSource::AliasWellFormed, goal.with(cx, trait_ref));
+                        this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+                    })
+                })
             }
             ty::AliasTermKind::InherentTy => self.normalize_inherent_associated_type(goal),
             ty::AliasTermKind::OpaqueTy => self.normalize_opaque_type(goal),
@@ -120,6 +71,17 @@ where
         self.eq(goal.param_env, goal.predicate.term, term)
             .expect("expected goal term to be fully unconstrained");
     }
+
+    /// Unlike `instantiate_normalizes_to_term` this instantiates the expected term
+    /// with a rigid alias. Using this is pretty much always wrong.
+    pub fn structurally_instantiate_normalizes_to_term(
+        &mut self,
+        goal: Goal<I, NormalizesTo<I>>,
+        term: ty::AliasTerm<I>,
+    ) {
+        self.relate_rigid_alias_non_alias(goal.param_env, term, ty::Invariant, goal.predicate.term)
+            .expect("expected goal term to be fully unconstrained");
+    }
 }
 
 impl<D, I> assembly::GoalKind<D> for NormalizesTo<I>
@@ -576,80 +538,92 @@ where
         let cx = ecx.cx();
         let metadata_def_id = cx.require_lang_item(TraitSolverLangItem::Metadata);
         assert_eq!(metadata_def_id, goal.predicate.def_id());
-        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
-            let metadata_ty = match goal.predicate.self_ty().kind() {
-                ty::Bool
-                | ty::Char
-                | ty::Int(..)
-                | ty::Uint(..)
-                | ty::Float(..)
-                | ty::Array(..)
-                | ty::Pat(..)
-                | ty::RawPtr(..)
-                | ty::Ref(..)
-                | ty::FnDef(..)
-                | ty::FnPtr(..)
-                | ty::Closure(..)
-                | ty::CoroutineClosure(..)
-                | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
-                | ty::Coroutine(..)
-                | ty::CoroutineWitness(..)
-                | ty::Never
-                | ty::Foreign(..)
-                | ty::Dynamic(_, _, ty::DynStar) => Ty::new_unit(cx),
-
-                ty::Error(e) => Ty::new_error(cx, e),
-
-                ty::Str | ty::Slice(_) => Ty::new_usize(cx),
-
-                ty::Dynamic(_, _, ty::Dyn) => {
-                    let dyn_metadata = cx.require_lang_item(TraitSolverLangItem::DynMetadata);
-                    cx.type_of(dyn_metadata)
-                        .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
-                }
+        let metadata_ty = match goal.predicate.self_ty().kind() {
+            ty::Bool
+            | ty::Char
+            | ty::Int(..)
+            | ty::Uint(..)
+            | ty::Float(..)
+            | ty::Array(..)
+            | ty::Pat(..)
+            | ty::RawPtr(..)
+            | ty::Ref(..)
+            | ty::FnDef(..)
+            | ty::FnPtr(..)
+            | ty::Closure(..)
+            | ty::CoroutineClosure(..)
+            | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
+            | ty::Never
+            | ty::Foreign(..)
+            | ty::Dynamic(_, _, ty::DynStar) => Ty::new_unit(cx),
 
-                ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
-                    // This is the "fallback impl" for type parameters, unnormalizable projections
-                    // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
-                    // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
-                    // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
-                    let sized_predicate = ty::TraitRef::new(
-                        cx,
-                        cx.require_lang_item(TraitSolverLangItem::Sized),
-                        [I::GenericArg::from(goal.predicate.self_ty())],
-                    );
-                    // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
-                    ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate));
-                    Ty::new_unit(cx)
-                }
+            ty::Error(e) => Ty::new_error(cx, e),
 
-                ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) {
-                    None => Ty::new_unit(cx),
-                    Some(tail_ty) => {
-                        Ty::new_projection(cx, metadata_def_id, [tail_ty.instantiate(cx, args)])
-                    }
-                },
-                ty::Adt(_, _) => Ty::new_unit(cx),
+            ty::Str | ty::Slice(_) => Ty::new_usize(cx),
 
-                ty::Tuple(elements) => match elements.last() {
-                    None => Ty::new_unit(cx),
-                    Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]),
-                },
+            ty::Dynamic(_, _, ty::Dyn) => {
+                let dyn_metadata = cx.require_lang_item(TraitSolverLangItem::DynMetadata);
+                cx.type_of(dyn_metadata)
+                    .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
+            }
+
+            ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
+                // This is the "fallback impl" for type parameters, unnormalizable projections
+                // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
+                // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
+                // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
+                let alias_bound_result =
+                    ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
+                        let sized_predicate = ty::TraitRef::new(
+                            cx,
+                            cx.require_lang_item(TraitSolverLangItem::Sized),
+                            [I::GenericArg::from(goal.predicate.self_ty())],
+                        );
+                        ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate));
+                        ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into());
+                        ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+                    });
+                // In case the dummy alias-bound candidate does not apply, we instead treat this projection
+                // as rigid.
+                return alias_bound_result.or_else(|NoSolution| {
+                    ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| {
+                        this.structurally_instantiate_normalizes_to_term(
+                            goal,
+                            goal.predicate.alias,
+                        );
+                        this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+                    })
+                });
+            }
 
-                ty::UnsafeBinder(_) => {
-                    // FIXME(unsafe_binder): Figure out how to handle pointee for unsafe binders.
-                    todo!()
+            ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) {
+                None => Ty::new_unit(cx),
+                Some(tail_ty) => {
+                    Ty::new_projection(cx, metadata_def_id, [tail_ty.instantiate(cx, args)])
                 }
+            },
+            ty::Adt(_, _) => Ty::new_unit(cx),
 
-                ty::Infer(
-                    ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
-                )
-                | ty::Bound(..) => panic!(
-                    "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
-                    goal.predicate.self_ty()
-                ),
-            };
+            ty::Tuple(elements) => match elements.last() {
+                None => Ty::new_unit(cx),
+                Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]),
+            },
 
+            ty::UnsafeBinder(_) => {
+                // FIXME(unsafe_binder): Figure out how to handle pointee for unsafe binders.
+                todo!()
+            }
+
+            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
+            | ty::Bound(..) => panic!(
+                "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
+                goal.predicate.self_ty()
+            ),
+        };
+
+        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
             ecx.instantiate_normalizes_to_term(goal, metadata_ty.into());
             ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         })
@@ -850,12 +824,14 @@ where
                 todo!("discr subgoal...")
             }
 
-            // We do not call `Ty::discriminant_ty` on alias, param, or placeholder
-            // types, which return `<self_ty as DiscriminantKind>::Discriminant`
-            // (or ICE in the case of placeholders). Projecting a type to itself
-            // is never really productive.
+            // Given an alias, parameter, or placeholder we add an impl candidate normalizing to a rigid
+            // alias. In case there's a where-bound further constraining this alias it is preferred over
+            // this impl candidate anyways. It's still a bit scuffed.
             ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
-                return Err(NoSolution);
+                return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
+                    ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
+                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+                });
             }
 
             ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
@@ -902,12 +878,14 @@ where
                 todo!()
             }
 
-            // We do not call `Ty::async_destructor_ty` on alias, param, or placeholder
-            // types, which return `<self_ty as AsyncDestruct>::AsyncDestructor`
-            // (or ICE in the case of placeholders). Projecting a type to itself
-            // is never really productive.
+            // Given an alias, parameter, or placeholder we add an impl candidate normalizing to a rigid
+            // alias. In case there's a where-bound further constraining this alias it is preferred over
+            // this impl candidate anyways. It's still a bit scuffed.
             ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
-                return Err(NoSolution);
+                return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
+                    ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
+                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+                });
             }
 
             ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
index 26a8a22d77e..60c20762a30 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
@@ -35,14 +35,15 @@ where
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
             }
             TypingMode::Analysis { defining_opaque_types } => {
-                let Some(def_id) = opaque_ty.def_id.as_local() else {
-                    return Err(NoSolution);
+                let Some(def_id) = opaque_ty
+                    .def_id
+                    .as_local()
+                    .filter(|&def_id| defining_opaque_types.contains(&def_id))
+                else {
+                    self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
+                    return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
                 };
 
-                if !defining_opaque_types.contains(&def_id) {
-                    return Err(NoSolution);
-                }
-
                 // FIXME: This may have issues when the args contain aliases...
                 match uses_unique_placeholders_ignoring_regions(self.cx(), opaque_ty.args) {
                     Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => {
@@ -97,15 +98,16 @@ where
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
             TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
-                let Some(def_id) = opaque_ty.def_id.as_local() else {
-                    return Err(NoSolution);
+                let Some(def_id) = opaque_ty
+                    .def_id
+                    .as_local()
+                    .filter(|&def_id| defined_opaque_types.contains(&def_id))
+                else {
+                    self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
+                    return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
                 };
 
-                if !defined_opaque_types.contains(&def_id) {
-                    return Err(NoSolution);
-                }
-
-                let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);
+                let actual = cx.type_of(def_id.into()).instantiate(cx, opaque_ty.args);
                 // FIXME: Actually use a proper binder here instead of relying on `ReErased`.
                 //
                 // This is also probably unsound or sth :shrug:
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 7988afd3e13..5e6bee1dbd5 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -4,14 +4,14 @@ use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
 use std::sync::Arc;
-use std::sync::atomic::Ordering;
+use std::sync::atomic::{AtomicU32, Ordering};
 
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
 use rustc_data_structures::sharded::{self, Sharded};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock};
+use rustc_data_structures::sync::{AtomicU64, Lock};
 use rustc_data_structures::unord::UnordMap;
 use rustc_index::IndexVec;
 use rustc_macros::{Decodable, Encodable};
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index a80b68d9773..0962865e7f1 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2347,9 +2347,14 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     // try to give a suggestion for this pattern: `name = blah`, which is common in other languages
     // suggest `let name = blah` to introduce a new binding
     fn let_binding_suggestion(&mut self, err: &mut Diag<'_>, ident_span: Span) -> bool {
+        if ident_span.from_expansion() {
+            return false;
+        }
+
+        // only suggest when the code is a assignment without prefix code
         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()
+            && self.r.tcx.sess.source_map().is_line_before_span_empty(ident_span)
         {
             let (span, text) = match path.segments.first() {
                 Some(seg) if let Some(name) = seg.ident.as_str().strip_prefix("let") => {
@@ -2368,6 +2373,22 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             );
             return true;
         }
+
+        // a special case for #133713
+        // '=' maybe a typo of `:`, which is a type annotation instead of assignment
+        if err.code == Some(E0423)
+            && let Some((let_span, None, Some(val_span))) = self.diag_metadata.current_let_binding
+            && val_span.contains(ident_span)
+            && val_span.lo() == ident_span.lo()
+        {
+            err.span_suggestion_verbose(
+                let_span.shrink_to_hi().to(val_span.shrink_to_lo()),
+                "you might have meant to use `:` for type annotation",
+                ": ",
+                Applicability::MaybeIncorrect,
+            );
+            return true;
+        }
         false
     }
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 2fb4b27b889..7d473b86ff5 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -86,12 +86,18 @@ pub enum CFProtection {
 
 #[derive(Clone, Copy, Debug, PartialEq, Hash, HashStable_Generic)]
 pub enum OptLevel {
-    No,         // -O0
-    Less,       // -O1
-    Default,    // -O2
-    Aggressive, // -O3
-    Size,       // -Os
-    SizeMin,    // -Oz
+    /// `-Copt-level=0`
+    No,
+    /// `-Copt-level=1`
+    Less,
+    /// `-Copt-level=2`
+    More,
+    /// `-Copt-level=3` / `-O`
+    Aggressive,
+    /// `-Copt-level=s`
+    Size,
+    /// `-Copt-level=z`
+    SizeMin,
 }
 
 /// This is what the `LtoCli` values get mapped to after resolving defaults and
@@ -1253,7 +1259,7 @@ impl Options {
             Some(setting) => setting,
             None => match self.optimize {
                 OptLevel::No | OptLevel::Less | OptLevel::Size | OptLevel::SizeMin => true,
-                OptLevel::Default | OptLevel::Aggressive => false,
+                OptLevel::More | OptLevel::Aggressive => false,
             },
         }
     }
@@ -1572,7 +1578,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
              stack-protector-strategies|link-args|deployment-target]",
         ),
         opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""),
-        opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=2", ""),
+        opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""),
         opt(Stable, Opt, "o", "", "Write output to <filename>", "FILENAME"),
         opt(Stable, Opt, "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
         opt(
@@ -2127,12 +2133,12 @@ fn parse_opt_level(
         })
         .max();
     if max_o > max_c {
-        OptLevel::Default
+        OptLevel::Aggressive
     } else {
         match cg.opt_level.as_ref() {
             "0" => OptLevel::No,
             "1" => OptLevel::Less,
-            "2" => OptLevel::Default,
+            "2" => OptLevel::More,
             "3" => OptLevel::Aggressive,
             "s" => OptLevel::Size,
             "z" => OptLevel::SizeMin,
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index cdc56782a26..71e7b9c04ca 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -494,7 +494,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| {
             Error::new(format!("Value overflow: cannot convert `{value}` to `{ty}`."))
         })?;
-        Ok(ty::Const::new_value(tables.tcx, ValTree::from_scalar_int(scalar), ty)
+        Ok(ty::Const::new_value(tcx, ValTree::from_scalar_int(tcx, scalar), ty)
             .stable(&mut *tables))
     }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
index 4a03ff4beae..fb2e838cdc9 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
@@ -105,7 +105,6 @@ impl<'tcx> Stable<'tcx> for callconv::Conv {
             Conv::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall,
             Conv::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry,
             Conv::Msp430Intr => CallConvention::Msp430Intr,
-            Conv::PtxKernel => CallConvention::PtxKernel,
             Conv::X86Fastcall => CallConvention::X86Fastcall,
             Conv::X86Intr => CallConvention::X86Intr,
             Conv::X86Stdcall => CallConvention::X86Stdcall,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index e93a722ccc0..62723e385cf 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -250,6 +250,7 @@ symbols! {
         Into,
         IntoFuture,
         IntoIterator,
+        IoBufRead,
         IoLines,
         IoRead,
         IoSeek,
@@ -880,6 +881,7 @@ symbols! {
         extern_crate_self,
         extern_in_paths,
         extern_prelude,
+        extern_system_varargs,
         extern_types,
         external,
         external_doc,
@@ -1995,6 +1997,7 @@ symbols! {
         sub_assign,
         sub_with_overflow,
         suggestion,
+        supertrait_item_shadowing,
         surface_async_drop_in_place,
         sym,
         sync,
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index b49dd258869..2bde1055622 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -542,8 +542,6 @@ pub enum Conv {
 
     Msp430Intr,
 
-    PtxKernel,
-
     GpuKernel,
 
     X86Fastcall,
@@ -689,7 +687,8 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             "sparc" => sparc::compute_abi_info(cx, self),
             "sparc64" => sparc64::compute_abi_info(cx, self),
             "nvptx64" => {
-                if cx.target_spec().adjust_abi(abi, self.c_variadic) == ExternAbi::PtxKernel {
+                let abi = cx.target_spec().adjust_abi(abi, self.c_variadic);
+                if abi == ExternAbi::PtxKernel || abi == ExternAbi::GpuKernel {
                     nvptx64::compute_ptx_kernel_abi_info(cx, self)
                 } else {
                     nvptx64::compute_abi_info(self)
@@ -841,7 +840,6 @@ impl FromStr for Conv {
             "CCmseNonSecureCall" => Ok(Conv::CCmseNonSecureCall),
             "CCmseNonSecureEntry" => Ok(Conv::CCmseNonSecureEntry),
             "Msp430Intr" => Ok(Conv::Msp430Intr),
-            "PtxKernel" => Ok(Conv::PtxKernel),
             "X86Fastcall" => Ok(Conv::X86Fastcall),
             "X86Intr" => Ok(Conv::X86Intr),
             "X86Stdcall" => Ok(Conv::X86Stdcall),
diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs
index 15cf7e195db..8d6f8f4c6f6 100644
--- a/compiler/rustc_target/src/json.rs
+++ b/compiler/rustc_target/src/json.rs
@@ -105,7 +105,6 @@ impl ToJson for crate::callconv::Conv {
             Self::CCmseNonSecureCall => "CCmseNonSecureCall",
             Self::CCmseNonSecureEntry => "CCmseNonSecureEntry",
             Self::Msp430Intr => "Msp430Intr",
-            Self::PtxKernel => "PtxKernel",
             Self::X86Fastcall => "X86Fastcall",
             Self::X86Intr => "X86Intr",
             Self::X86Stdcall => "X86Stdcall",
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index 497994a5998..1b56143545f 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -2,8 +2,8 @@ use std::borrow::Cow;
 use std::env;
 
 use crate::spec::{
-    Cc, DebuginfoKind, FloatAbi, FramePointer, LinkerFlavor, Lld, SplitDebuginfo, StackProbeType,
-    StaticCow, TargetOptions, cvs,
+    Cc, DebuginfoKind, FloatAbi, FramePointer, LinkerFlavor, Lld, RustcAbi, SplitDebuginfo,
+    StackProbeType, StaticCow, TargetOptions, cvs,
 };
 
 #[cfg(test)]
@@ -103,7 +103,7 @@ pub(crate) fn base(
     arch: Arch,
     abi: TargetAbi,
 ) -> (TargetOptions, StaticCow<str>, StaticCow<str>) {
-    let opts = TargetOptions {
+    let mut opts = TargetOptions {
         abi: abi.target_abi().into(),
         llvm_floatabi: Some(FloatAbi::Hard),
         os: os.into(),
@@ -154,6 +154,10 @@ pub(crate) fn base(
 
         ..Default::default()
     };
+    if matches!(arch, Arch::I386 | Arch::I686) {
+        // All Apple x86-32 targets have SSE2.
+        opts.rustc_abi = Some(RustcAbi::X86Sse2);
+    }
     (opts, unversioned_llvm_target(os, arch, abi), arch.target_arch())
 }
 
diff --git a/compiler/rustc_target/src/spec/base/cygwin.rs b/compiler/rustc_target/src/spec/base/cygwin.rs
new file mode 100644
index 00000000000..fe3efb3f46b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/base/cygwin.rs
@@ -0,0 +1,46 @@
+use std::borrow::Cow;
+
+use crate::spec::{Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions, cvs};
+
+pub(crate) fn opts() -> TargetOptions {
+    let mut pre_link_args = TargetOptions::link_args(
+        LinkerFlavor::Gnu(Cc::No, Lld::No),
+        &["--disable-dynamicbase", "--enable-auto-image-base"],
+    );
+    crate::spec::add_link_args(
+        &mut pre_link_args,
+        LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+        &["-Wl,--disable-dynamicbase", "-Wl,--enable-auto-image-base"],
+    );
+    let cygwin_libs = &["-lcygwin", "-lgcc", "-lcygwin", "-luser32", "-lkernel32", "-lgcc_s"];
+    let mut late_link_args =
+        TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), cygwin_libs);
+    crate::spec::add_link_args(
+        &mut late_link_args,
+        LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+        cygwin_libs,
+    );
+    TargetOptions {
+        os: "cygwin".into(),
+        vendor: "pc".into(),
+        // FIXME(#13846) this should be enabled for cygwin
+        function_sections: false,
+        linker: Some("gcc".into()),
+        dynamic_linking: true,
+        dll_prefix: "".into(),
+        dll_suffix: ".dll".into(),
+        exe_suffix: ".exe".into(),
+        families: cvs!["unix"],
+        is_like_windows: true,
+        allows_weak_linkage: false,
+        pre_link_args,
+        late_link_args,
+        abi_return_struct_as_int: true,
+        emit_debug_gdb_scripts: false,
+        requires_uwtable: true,
+        eh_frame_header: false,
+        debuginfo_kind: DebuginfoKind::Dwarf,
+        supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
+        ..Default::default()
+    }
+}
diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs
index 28d10dcf2ff..b9139c8452c 100644
--- a/compiler/rustc_target/src/spec/base/mod.rs
+++ b/compiler/rustc_target/src/spec/base/mod.rs
@@ -3,6 +3,7 @@ pub(crate) mod android;
 pub(crate) mod apple;
 pub(crate) mod avr_gnu;
 pub(crate) mod bpf;
+pub(crate) mod cygwin;
 pub(crate) mod dragonfly;
 pub(crate) mod freebsd;
 pub(crate) mod fuchsia;
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 7e84127c93a..794d6457cb7 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1109,6 +1109,8 @@ impl ToJson for FloatAbi {
 /// The Rustc-specific variant of the ABI used for this target.
 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum RustcAbi {
+    /// On x86-32 only: make use of SSE and SSE2 for ABI purposes.
+    X86Sse2,
     /// On x86-32/64 only: do not use any FPU or SIMD registers for the ABI.
     X86Softfloat,
 }
@@ -1118,6 +1120,7 @@ impl FromStr for RustcAbi {
 
     fn from_str(s: &str) -> Result<RustcAbi, ()> {
         Ok(match s {
+            "x86-sse2" => RustcAbi::X86Sse2,
             "x86-softfloat" => RustcAbi::X86Softfloat,
             _ => return Err(()),
         })
@@ -1127,6 +1130,7 @@ impl FromStr for RustcAbi {
 impl ToJson for RustcAbi {
     fn to_json(&self) -> Json {
         match *self {
+            RustcAbi::X86Sse2 => "x86-sse2",
             RustcAbi::X86Softfloat => "x86-softfloat",
         }
         .to_json()
@@ -2013,6 +2017,7 @@ supported_targets! {
     ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
     ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
 
+    ("x86_64-pc-cygwin", x86_64_pc_cygwin),
 }
 
 /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
@@ -2994,8 +2999,8 @@ impl Target {
         );
         check_eq!(
             self.is_like_windows,
-            self.os == "windows" || self.os == "uefi",
-            "`is_like_windows` must be set if and only if `os` is `windows` or `uefi`"
+            self.os == "windows" || self.os == "uefi" || self.os == "cygwin",
+            "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
         );
         check_eq!(
             self.is_like_wasm,
@@ -3263,6 +3268,11 @@ impl Target {
         // Check consistency of Rust ABI declaration.
         if let Some(rust_abi) = self.rustc_abi {
             match rust_abi {
+                RustcAbi::X86Sse2 => check_matches!(
+                    &*self.arch,
+                    "x86",
+                    "`x86-sse2` ABI is only valid for x86-32 targets"
+                ),
                 RustcAbi::X86Softfloat => check_matches!(
                     &*self.arch,
                     "x86" | "x86_64",
diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
index fa21cfbab8a..6a98a763b36 100644
--- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::nto_qnx;
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{RustcAbi, StackProbeType, Target, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut meta = nto_qnx::meta();
@@ -14,6 +14,7 @@ pub(crate) fn target() -> Target {
             .into(),
         arch: "x86".into(),
         options: TargetOptions {
+            rustc_abi: Some(RustcAbi::X86Sse2),
             cpu: "pentium4".into(),
             max_atomic_width: Some(64),
             pre_link_args: nto_qnx::pre_link_args(
diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs
index e481e967ebf..f04e3c2c2a5 100644
--- a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs
@@ -2,6 +2,7 @@ use crate::spec::Target;
 
 pub(crate) fn target() -> Target {
     let mut base = super::i686_unknown_linux_gnu::target();
+    base.rustc_abi = None; // overwrite the SSE2 ABI set by the base target
     base.cpu = "pentium".into();
     base.llvm_target = "i586-unknown-linux-gnu".into();
     base
diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs
index 8ad93496f3a..42babb90da7 100644
--- a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs
@@ -2,6 +2,7 @@ use crate::spec::Target;
 
 pub(crate) fn target() -> Target {
     let mut base = super::i686_unknown_linux_musl::target();
+    base.rustc_abi = None; // overwrite the SSE2 ABI set by the base target
     base.cpu = "pentium".into();
     base.llvm_target = "i586-unknown-linux-musl".into();
     // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
diff --git a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
index 1b8f4c1be2d..7d61d5ca257 100644
--- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
@@ -1,4 +1,4 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{RustcAbi, SanitizerSet, StackProbeType, Target, TargetOptions, base};
 
 // See https://developer.android.com/ndk/guides/abis.html#x86
 // for target ABI requirements.
@@ -8,6 +8,7 @@ pub(crate) fn target() -> Target {
 
     base.max_atomic_width = Some(64);
 
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     // https://developer.android.com/ndk/guides/abis.html#x86
     base.cpu = "pentium4".into();
     base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".into();
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
index 208fe50912c..06dbf1e3a16 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnu::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
index 5df8dce1aa3..05d848e0393 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnullvm::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
index 180750bc7a8..e0e47113087 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
@@ -1,7 +1,8 @@
-use crate::spec::{LinkerFlavor, Lld, SanitizerSet, Target, base};
+use crate::spec::{LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.supported_sanitizers = SanitizerSet::ADDRESS;
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
index 85ab87cc07f..71c26041a50 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::freebsd::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-znotext"]);
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
index 1ab493c787c..464ac46b07c 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::haiku::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
index c95cb308d7f..fe699dbcb51 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
@@ -1,7 +1,19 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, SanitizerSet, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
+    // Dear distribution packager, if you are changing the base CPU model with the goal of removing
+    // the SSE2 requirement, make sure to also set the `rustc_abi` to `None` above or else the compiler
+    // will complain that the chosen ABI cannot be realized with the given CPU features.
+    // Also note that x86 without SSE2 is *not* considered a Tier 1 target by the Rust project, and
+    // it has some known floating-point correctness issues mostly caused by a lack of people caring
+    // for LLVM's x87 support (double-rounding, value truncation; see
+    // <https://github.com/rust-lang/rust/issues/114479> for details). This can lead to incorrect
+    // math (Rust generally promises exact math, so this can break code in unexpected ways) and it
+    // can lead to memory safety violations if floating-point values are used e.g. to access an
+    // array. If users run into such issues and report bugs upstream and then it turns out that the
+    // bugs are caused by distribution patches, that leads to confusion and frustration.
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.supported_sanitizers = SanitizerSet::ADDRESS;
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
index 6ba87c732b7..3d25c951e81 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
@@ -1,7 +1,10 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
+    // If you want to change the base CPU, please see `i686_unknown_linux_gnu.rs`
+    // for an important comment.
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-melf_i386"]);
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
index 092ba5c7baa..4bc6eee1ac2 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::netbsd::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
index 7ae9189e233..a3bdf66a14d 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::openbsd::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-fuse-ld=lld"]);
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
index 6e3733538ed..0e1b65ef598 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_uwp_gnu::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
index e0de9b9af45..44cf9b1adda 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Target, base};
+use crate::spec::{RustcAbi, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_uwp_msvc::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
 
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
index 1d084c0729c..e9100da14cb 100644
--- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
@@ -1,8 +1,9 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnu::opts();
     base.vendor = "win7".into();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
index 7efba3aa986..94284a2fe72 100644
--- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
@@ -1,8 +1,9 @@
-use crate::spec::{LinkerFlavor, Lld, SanitizerSet, Target, base};
+use crate::spec::{LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
     base.vendor = "win7".into();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.supported_sanitizers = SanitizerSet::ADDRESS;
diff --git a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
index dfffa6e138f..4e801955d0c 100644
--- a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::vxworks::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs
new file mode 100644
index 00000000000..8da4fe6b8b1
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs
@@ -0,0 +1,24 @@
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, base};
+
+pub(crate) fn target() -> Target {
+    let mut base = base::cygwin::opts();
+    base.cpu = "x86-64".into();
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &["-m", "i386pep"]);
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+    base.max_atomic_width = Some(64);
+    base.linker = Some("x86_64-pc-cygwin-gcc".into());
+    Target {
+        llvm_target: "x86_64-pc-cygwin".into(),
+        pointer_width: 64,
+        data_layout:
+            "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
+        arch: "x86_64".into(),
+        options: base,
+        metadata: crate::spec::TargetMetadata {
+            description: Some("64-bit x86 Cygwin".into()),
+            tier: Some(3),
+            host_tools: Some(false),
+            std: None,
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 1ba8defedae..bb41d03e87f 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -790,6 +790,13 @@ impl Target {
                         // x87 must be enabled, soft-float must be disabled.
                         FeatureConstraints { required: &["x87"], incompatible: &["soft-float"] }
                     }
+                    Some(RustcAbi::X86Sse2) => {
+                        // Extended hardfloat ABI. x87 and SSE2 must be enabled, soft-float must be disabled.
+                        FeatureConstraints {
+                            required: &["x87", "sse2"],
+                            incompatible: &["soft-float"],
+                        }
+                    }
                     Some(RustcAbi::X86Softfloat) => {
                         // Softfloat ABI, requires corresponding target feature. That feature trumps
                         // `x87` and all other FPU features so those do not matter.
@@ -817,6 +824,7 @@ impl Target {
                         // LLVM handles the rest.
                         FeatureConstraints { required: &["soft-float"], incompatible: &[] }
                     }
+                    Some(r) => panic!("invalid Rust ABI for x86_64: {r:?}"),
                 }
             }
             "arm" => {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 1b43820bac0..49fa21e50c0 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -585,6 +585,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {
                         let ty = self.resolve_vars_if_possible(ty);
                         if self.next_trait_solver() {
+                            if let Err(guar) = ty.error_reported() {
+                                return guar;
+                            }
+
                             // FIXME: we'll need a better message which takes into account
                             // which bounds actually failed to hold.
                             self.dcx().struct_span_err(
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
index 658fb4009d5..e4f250ca4f5 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -172,8 +172,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             {
                 1
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => 3,
             ty::PredicateKind::Coerce(_) => 2,
+            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => 3,
             _ => 0,
         });
 
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index 7364b4aa343..982782bc57c 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -7,7 +7,7 @@ use rustc_infer::traits::{
     PredicateObligation, SelectionError,
 };
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _};
 use rustc_type_ir::solve::{Goal, NoSolution};
@@ -139,6 +139,7 @@ pub(super) fn fulfillment_error_for_overflow<'tcx>(
     }
 }
 
+#[instrument(level = "debug", skip(infcx), ret)]
 fn find_best_leaf_obligation<'tcx>(
     infcx: &InferCtxt<'tcx>,
     obligation: &PredicateObligation<'tcx>,
@@ -197,6 +198,9 @@ impl<'tcx> BestObligation<'tcx> {
                 candidates.retain(|candidate| candidate.result().is_ok());
             }
             false => {
+                // We always handle rigid alias candidates separately as we may not add them for
+                // aliases whose trait bound doesn't hold.
+                candidates.retain(|c| !matches!(c.kind(), inspect::ProbeKind::RigidAlias { .. }));
                 // If we have >1 candidate, one may still be due to "boring" reasons, like
                 // an alias-relate that failed to hold when deeply evaluated. We really
                 // don't care about reasons like this.
@@ -211,23 +215,12 @@ impl<'tcx> BestObligation<'tcx> {
                                             | GoalSource::AliasBoundConstCondition
                                             | GoalSource::InstantiateHigherRanked
                                             | GoalSource::AliasWellFormed
-                                    ) && match (self.consider_ambiguities, nested_goal.result()) {
-                                        (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity)))
-                                        | (false, Err(_)) => true,
-                                        _ => false,
-                                    }
+                                    ) && nested_goal.result().is_err()
                                 },
                             )
                         })
                     });
                 }
-
-                // Prefer a non-rigid candidate if there is one.
-                if candidates.len() > 1 {
-                    candidates.retain(|candidate| {
-                        !matches!(candidate.kind(), inspect::ProbeKind::RigidAlias { .. })
-                    });
-                }
             }
         }
 
@@ -266,6 +259,90 @@ impl<'tcx> BestObligation<'tcx> {
 
         ControlFlow::Break(self.obligation.clone())
     }
+
+    /// If a normalization of an associated item or a trait goal fails without trying any
+    /// candidates it's likely that normalizing its self type failed. We manually detect
+    /// such cases here.
+    fn detect_error_in_self_ty_normalization(
+        &mut self,
+        goal: &inspect::InspectGoal<'_, 'tcx>,
+        self_ty: Ty<'tcx>,
+    ) -> ControlFlow<PredicateObligation<'tcx>> {
+        assert!(!self.consider_ambiguities);
+        let tcx = goal.infcx().tcx;
+        if let ty::Alias(..) = self_ty.kind() {
+            let infer_term = goal.infcx().next_ty_var(self.obligation.cause.span);
+            let pred = ty::PredicateKind::AliasRelate(
+                self_ty.into(),
+                infer_term.into(),
+                ty::AliasRelationDirection::Equate,
+            );
+            let obligation =
+                Obligation::new(tcx, self.obligation.cause.clone(), goal.goal().param_env, pred);
+            self.with_derived_obligation(obligation, |this| {
+                goal.infcx().visit_proof_tree_at_depth(
+                    goal.goal().with(tcx, pred),
+                    goal.depth() + 1,
+                    this,
+                )
+            })
+        } else {
+            ControlFlow::Continue(())
+        }
+    }
+
+    /// It is likely that `NormalizesTo` failed without any applicable candidates
+    /// because the alias is not well-formed.
+    ///
+    /// As we only enter `RigidAlias` candidates if the trait bound of the associated type
+    /// holds, we discard these candidates in `non_trivial_candidates` and always manually
+    /// check this here.
+    fn detect_non_well_formed_assoc_item(
+        &mut self,
+        goal: &inspect::InspectGoal<'_, 'tcx>,
+        alias: ty::AliasTerm<'tcx>,
+    ) -> ControlFlow<PredicateObligation<'tcx>> {
+        let tcx = goal.infcx().tcx;
+        let obligation = Obligation::new(
+            tcx,
+            self.obligation.cause.clone(),
+            goal.goal().param_env,
+            alias.trait_ref(tcx),
+        );
+        self.with_derived_obligation(obligation, |this| {
+            goal.infcx().visit_proof_tree_at_depth(
+                goal.goal().with(tcx, alias.trait_ref(tcx)),
+                goal.depth() + 1,
+                this,
+            )
+        })
+    }
+
+    /// If we have no candidates, then it's likely that there is a
+    /// non-well-formed alias in the goal.
+    fn detect_error_from_empty_candidates(
+        &mut self,
+        goal: &inspect::InspectGoal<'_, 'tcx>,
+    ) -> ControlFlow<PredicateObligation<'tcx>> {
+        let tcx = goal.infcx().tcx;
+        let pred_kind = goal.goal().predicate.kind();
+
+        match pred_kind.no_bound_vars() {
+            Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))) => {
+                self.detect_error_in_self_ty_normalization(goal, pred.self_ty())?;
+            }
+            Some(ty::PredicateKind::NormalizesTo(pred))
+                if let ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst =
+                    pred.alias.kind(tcx) =>
+            {
+                self.detect_error_in_self_ty_normalization(goal, pred.alias.self_ty())?;
+                self.detect_non_well_formed_assoc_item(goal, pred.alias)?;
+            }
+            Some(_) | None => {}
+        }
+
+        ControlFlow::Break(self.obligation.clone())
+    }
 }
 
 impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
@@ -277,11 +354,19 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
 
     #[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))]
     fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
-        let candidates = self.non_trivial_candidates(goal);
-        trace!(candidates = ?candidates.iter().map(|c| c.kind()).collect::<Vec<_>>());
+        let tcx = goal.infcx().tcx;
+        // Skip goals that aren't the *reason* for our goal's failure.
+        match (self.consider_ambiguities, goal.result()) {
+            (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {}
+            _ => return ControlFlow::Continue(()),
+        }
+        let pred_kind = goal.goal().predicate.kind();
 
-        let [candidate] = candidates.as_slice() else {
-            return ControlFlow::Break(self.obligation.clone());
+        let candidates = self.non_trivial_candidates(goal);
+        let candidate = match candidates.as_slice() {
+            [candidate] => candidate,
+            [] => return self.detect_error_from_empty_candidates(goal),
+            _ => return ControlFlow::Break(self.obligation.clone()),
         };
 
         // Don't walk into impls that have `do_not_recommend`.
@@ -291,13 +376,12 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
         } = candidate.kind()
             && goal.infcx().tcx.do_not_recommend_impl(impl_def_id)
         {
+            trace!("#[do_not_recommend] -> exit");
             return ControlFlow::Break(self.obligation.clone());
         }
 
-        let tcx = goal.infcx().tcx;
         // FIXME: Also, what about considering >1 layer up the stack? May be necessary
         // for normalizes-to.
-        let pred_kind = goal.goal().predicate.kind();
         let child_mode = match pred_kind.skip_binder() {
             ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
                 ChildMode::Trait(pred_kind.rebind(pred))
@@ -390,12 +474,6 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
                 }
             }
 
-            // Skip nested goals that aren't the *reason* for our goal's failure.
-            match (self.consider_ambiguities, nested_goal.result()) {
-                (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {}
-                _ => continue,
-            }
-
             self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
         }
 
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 9f4ee54bd4c..9fbc1d64d74 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -300,7 +300,6 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
                         inspect::ProbeKind::NormalizedSelfTyAssembly
                         | inspect::ProbeKind::UnsizeAssembly
                         | inspect::ProbeKind::Root { .. }
-                        | inspect::ProbeKind::TryNormalizeNonRigid { .. }
                         | inspect::ProbeKind::TraitCandidate { .. }
                         | inspect::ProbeKind::OpaqueTypeStorageLookup { .. }
                         | inspect::ProbeKind::RigidAlias { .. } => {
@@ -325,7 +324,6 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
             // We add a candidate even for the root evaluation if there
             // is only one way to prove a given goal, e.g. for `WellFormed`.
             inspect::ProbeKind::Root { result }
-            | inspect::ProbeKind::TryNormalizeNonRigid { result }
             | inspect::ProbeKind::TraitCandidate { source: _, result }
             | inspect::ProbeKind::OpaqueTypeStorageLookup { result }
             | inspect::ProbeKind::RigidAlias { result } => {
diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs
index b0b6274907d..4437fc5b029 100644
--- a/compiler/rustc_trait_selection/src/solve/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/select.rs
@@ -175,8 +175,7 @@ fn to_selection<'tcx>(
                 span_bug!(span, "didn't expect to select an unknowable candidate")
             }
         },
-        ProbeKind::TryNormalizeNonRigid { result: _ }
-        | ProbeKind::NormalizedSelfTyAssembly
+        ProbeKind::NormalizedSelfTyAssembly
         | ProbeKind::UnsizeAssembly
         | ProbeKind::UpcastProjectionCompatibility
         | ProbeKind::OpaqueTypeStorageLookup { result: _ }
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index d30363ec158..15f5cf916a4 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -47,11 +47,11 @@ pub fn expand_trait_aliases<'tcx>(
                     queue.extend(
                         tcx.explicit_super_predicates_of(trait_pred.def_id())
                             .iter_identity_copied()
-                            .map(|(clause, span)| {
+                            .map(|(super_clause, span)| {
                                 let mut spans = spans.clone();
                                 spans.push(span);
                                 (
-                                    clause.instantiate_supertrait(
+                                    super_clause.instantiate_supertrait(
                                         tcx,
                                         clause.kind().rebind(trait_pred.trait_ref),
                                     ),
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index df30872c437..c5d2d0afbfa 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -290,7 +290,7 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv
         Aapcs { .. } => Conv::ArmAapcs,
         CCmseNonSecureCall => Conv::CCmseNonSecureCall,
         CCmseNonSecureEntry => Conv::CCmseNonSecureEntry,
-        PtxKernel => Conv::PtxKernel,
+        PtxKernel => Conv::GpuKernel,
         Msp430Interrupt => Conv::Msp430Intr,
         X86Interrupt => Conv::X86Intr,
         GpuKernel => Conv::GpuKernel,
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index cbe49d000b7..ece796b3c71 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -26,10 +26,7 @@ fn destructure_const<'tcx>(
         bug!("cannot destructure constant {:?}", const_)
     };
 
-    let branches = match cv.valtree {
-        ty::ValTree::Branch(b) => b,
-        _ => bug!("cannot destructure constant {:?}", const_),
-    };
+    let branches = cv.valtree.unwrap_branch();
 
     let (fields, variant) = match cv.ty.kind() {
         ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
@@ -126,13 +123,10 @@ fn recurse_build<'tcx>(
             tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg })
         }
         &ExprKind::NonHirLiteral { lit, user_ty: _ } => {
-            let val = ty::ValTree::from_scalar_int(lit);
-            ty::Const::new_value(tcx, val, node.ty)
-        }
-        &ExprKind::ZstLiteral { user_ty: _ } => {
-            let val = ty::ValTree::zst();
+            let val = ty::ValTree::from_scalar_int(tcx, lit);
             ty::Const::new_value(tcx, val, node.ty)
         }
+        &ExprKind::ZstLiteral { user_ty: _ } => ty::Const::zero_sized(tcx, node.ty),
         &ExprKind::NamedConst { def_id, args, user_ty: _ } => {
             let uneval = ty::UnevaluatedConst::new(def_id, args);
             ty::Const::new_unevaluated(tcx, uneval)
diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs
index d0e618dc6f9..18fb71dd290 100644
--- a/compiler/rustc_type_ir/src/solve/inspect.rs
+++ b/compiler/rustc_type_ir/src/solve/inspect.rs
@@ -111,8 +111,6 @@ pub enum ProbeStep<I: Interner> {
 pub enum ProbeKind<I: Interner> {
     /// The root inference context while proving a goal.
     Root { result: QueryResult<I> },
-    /// Trying to normalize an alias by at least one step in `NormalizesTo`.
-    TryNormalizeNonRigid { result: QueryResult<I> },
     /// Probe entered when normalizing the self ty during candidate assembly
     NormalizedSelfTyAssembly,
     /// A candidate for proving a trait or alias-relate goal.