about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-02-15 00:30:50 +0000
committerbors <bors@rust-lang.org>2025-02-15 00:30:50 +0000
commit54a0f387ea8c7bcb79b8e40c074a484d31b51990 (patch)
treebd5bfdfaa0b9785d57db609764e8f6d867f6f932
parentfc147b4a81bea997e544afa8f8f05af73c759231 (diff)
parent9d659fc2bec22a991a1a728ec3f995c51386ff6e (diff)
downloadrust-54a0f387ea8c7bcb79b8e40c074a484d31b51990.tar.gz
rust-54a0f387ea8c7bcb79b8e40c074a484d31b51990.zip
Auto merge of #137046 - workingjubilee:rollup-u56aw1m, r=workingjubilee
Rollup of 10 pull requests

Successful merges:

 - #133312 (triagebot: automatically add more rustdoc related labels)
 - #134016 (Stabilize `const_is_char_boundary` and `const_str_split_at`.)
 - #136971 (Add a new check-pass UI test for returning `impl Fn(T) -> impl Trait`)
 - #136983 (Prepare standard library for Rust 2024 migration)
 - #137002 (Fix early lint check desc in query)
 - #137006 (borrowck diagnostics cleanup: remove an unused and a barely-used field)
 - #137032 (Decode metadata buffer in one go)
 - #137035 (Normalize closure instance before eagerly monomorphizing it)
 - #137037 (add x86-sse2 (32bit) ABI that requires SSE2 target feature)
 - #137038 (llvm: Tolerate captures in tests)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs40
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs5
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs7
-rw-r--r--compiler/rustc_target/src/spec/base/apple/mod.rs10
-rw-r--r--compiler/rustc_target/src/spec/mod.rs9
-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/target_features.rs8
-rw-r--r--library/Cargo.lock71
-rw-r--r--library/alloc/Cargo.toml4
-rw-r--r--library/alloc/benches/btree/map.rs24
-rw-r--r--library/alloc/benches/btree/set.rs8
-rw-r--r--library/alloc/benches/slice.rs24
-rw-r--r--library/alloc/src/boxed.rs6
-rw-r--r--library/alloc/src/vec/mod.rs2
-rw-r--r--library/alloc/tests/sort/patterns.rs8
-rw-r--r--library/alloc/tests/sort/zipf.rs4
-rw-r--r--library/core/src/mem/maybe_uninit.rs2
-rw-r--r--library/core/src/str/mod.rs10
-rw-r--r--library/coretests/Cargo.toml6
-rw-r--r--library/coretests/benches/num/int_log/mod.rs8
-rw-r--r--library/coretests/benches/num/int_pow/mod.rs4
-rw-r--r--library/coretests/benches/num/int_sqrt/mod.rs9
-rw-r--r--library/coretests/benches/slice.rs8
-rw-r--r--library/coretests/tests/io/borrowed_buf.rs4
-rw-r--r--library/coretests/tests/num/flt2dec/random.rs6
-rw-r--r--library/coretests/tests/pin.rs4
-rw-r--r--library/coretests/tests/slice.rs9
-rw-r--r--library/std/Cargo.toml4
-rw-r--r--library/std/src/env.rs2
-rw-r--r--library/std/src/keyword_docs.rs6
-rw-r--r--library/std/src/panic.rs4
-rw-r--r--library/std/src/process/tests.rs8
-rw-r--r--library/std/src/sys/alloc/sgx.rs6
-rw-r--r--library/std/src/sys/alloc/xous.rs2
-rw-r--r--library/std/src/sys/pal/hermit/mod.rs4
-rw-r--r--library/std/src/sys/pal/sgx/abi/mod.rs6
-rw-r--r--library/std/src/sys/pal/sgx/abi/tls/mod.rs4
-rw-r--r--library/std/src/sys/pal/sgx/args.rs2
-rw-r--r--library/std/src/sys/pal/sgx/libunwind_integration.rs6
-rw-r--r--library/std/src/sys/pal/sgx/mod.rs2
-rw-r--r--library/std/src/sys/pal/sgx/os.rs4
-rw-r--r--library/std/src/sys/pal/sgx/stdio.rs2
-rw-r--r--library/std/src/sys/pal/sgx/thread.rs2
-rw-r--r--library/std/src/sys/pal/uefi/mod.rs2
-rw-r--r--library/std/src/sys/pal/uefi/process.rs8
-rw-r--r--library/std/src/sys/pal/unix/linux/pidfd/tests.rs4
-rw-r--r--library/std/src/sys/pal/wasi/fs.rs4
-rw-r--r--library/std/src/sys/pal/wasip2/cabi_realloc.rs2
-rw-r--r--library/std/src/sys/pal/windows/process/tests.rs6
-rw-r--r--library/std/src/sys/pal/xous/os.rs6
-rw-r--r--library/std/src/sys/thread_local/key/xous.rs4
-rw-r--r--library/std/tests/env_modify.rs86
-rw-r--r--library/std/tests/sync/rwlock.rs2
-rw-r--r--library/test/src/term/terminfo/searcher/tests.rs8
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr5
-rw-r--r--src/tools/tidy/src/deps.rs6
-rw-r--r--tests/codegen/common_prim_int_ptr.rs2
-rw-r--r--tests/ui/closures/eager-mono-with-normalizable-upvars.rs19
-rw-r--r--tests/ui/impl-trait/impl-fn-rpit-opaque-107883.rs37
-rw-r--r--tests/ui/sse-abi-checks.rs2
-rw-r--r--tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs12
-rw-r--r--tests/ui/target-feature/target-cpu-lacks-required-target-feature.stderr7
-rw-r--r--triagebot.toml37
81 files changed, 471 insertions, 217 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 552d9d1d3f9..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>,
@@ -471,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) => {
@@ -680,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 =
@@ -762,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());
 
@@ -789,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_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/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_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_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/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 8b20152d3bf..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()
@@ -3264,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/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/library/Cargo.lock b/library/Cargo.lock
index 930db2ecd57..0be2f9a1549 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -216,6 +216,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "proc-macro2"
+version = "1.0.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
 name = "proc_macro"
 version = "0.0.0"
 dependencies = [
@@ -231,6 +240,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "quote"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
 name = "r-efi"
 version = "4.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -253,24 +271,28 @@ dependencies = [
 
 [[package]]
 name = "rand"
-version = "0.8.5"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
 dependencies = [
  "rand_core",
+ "zerocopy",
 ]
 
 [[package]]
 name = "rand_core"
-version = "0.6.4"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff"
+dependencies = [
+ "zerocopy",
+]
 
 [[package]]
 name = "rand_xorshift"
-version = "0.3.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
+checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
 dependencies = [
  "rand_core",
 ]
@@ -353,6 +375,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "syn"
+version = "2.0.98"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
 name = "sysroot"
 version = "0.0.0"
 dependencies = [
@@ -373,6 +406,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "unicode-ident"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
+
+[[package]]
 name = "unicode-width"
 version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -492,3 +531,23 @@ name = "windows_x86_64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "zerocopy"
+version = "0.8.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 6b0b5761391..c1d7f324f17 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -13,8 +13,8 @@ core = { path = "../core" }
 compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] }
 
 [dev-dependencies]
-rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
-rand_xorshift = "0.3.0"
+rand = { version = "0.9.0", default-features = false, features = ["alloc"] }
+rand_xorshift = "0.4.0"
 
 [[test]]
 name = "alloctests"
diff --git a/library/alloc/benches/btree/map.rs b/library/alloc/benches/btree/map.rs
index 5b15aaeddbc..20f02dc3a96 100644
--- a/library/alloc/benches/btree/map.rs
+++ b/library/alloc/benches/btree/map.rs
@@ -9,19 +9,19 @@ macro_rules! map_insert_rand_bench {
     ($name: ident, $n: expr, $map: ident) => {
         #[bench]
         pub fn $name(b: &mut Bencher) {
-            let n: usize = $n;
+            let n: u32 = $n;
             let mut map = $map::new();
             // setup
             let mut rng = crate::bench_rng();
 
             for _ in 0..n {
-                let i = rng.gen::<usize>() % n;
+                let i = rng.random::<u32>() % n;
                 map.insert(i, i);
             }
 
             // measure
             b.iter(|| {
-                let k = rng.gen::<usize>() % n;
+                let k = rng.random::<u32>() % n;
                 map.insert(k, k);
                 map.remove(&k);
             });
@@ -57,13 +57,13 @@ macro_rules! map_from_iter_rand_bench {
     ($name: ident, $n: expr, $map: ident) => {
         #[bench]
         pub fn $name(b: &mut Bencher) {
-            let n: usize = $n;
+            let n: u32 = $n;
             // setup
             let mut rng = crate::bench_rng();
-            let mut vec = Vec::with_capacity(n);
+            let mut vec = Vec::with_capacity(n as usize);
 
             for _ in 0..n {
-                let i = rng.gen::<usize>() % n;
+                let i = rng.random::<u32>() % n;
                 vec.push((i, i));
             }
 
@@ -102,11 +102,11 @@ macro_rules! map_find_rand_bench {
         #[bench]
         pub fn $name(b: &mut Bencher) {
             let mut map = $map::new();
-            let n: usize = $n;
+            let n: u32 = $n;
 
             // setup
             let mut rng = crate::bench_rng();
-            let mut keys: Vec<_> = (0..n).map(|_| rng.gen::<usize>() % n).collect();
+            let mut keys: Vec<_> = (0..n).map(|_| rng.random::<u32>() % n).collect();
 
             for &k in &keys {
                 map.insert(k, k);
@@ -115,9 +115,9 @@ macro_rules! map_find_rand_bench {
             keys.shuffle(&mut rng);
 
             // measure
-            let mut i = 0;
+            let mut i = 0u32;
             b.iter(|| {
-                let t = map.get(&keys[i]);
+                let t = map.get(&keys[i as usize]);
                 i = (i + 1) % n;
                 black_box(t);
             })
@@ -171,7 +171,7 @@ fn bench_iteration(b: &mut Bencher, size: i32) {
     let mut rng = crate::bench_rng();
 
     for _ in 0..size {
-        map.insert(rng.gen(), rng.gen());
+        map.insert(rng.random(), rng.random());
     }
 
     b.iter(|| {
@@ -201,7 +201,7 @@ fn bench_iteration_mut(b: &mut Bencher, size: i32) {
     let mut rng = crate::bench_rng();
 
     for _ in 0..size {
-        map.insert(rng.gen(), rng.gen());
+        map.insert(rng.random(), rng.random());
     }
 
     b.iter(|| {
diff --git a/library/alloc/benches/btree/set.rs b/library/alloc/benches/btree/set.rs
index 09d72c72064..5aa395b4d52 100644
--- a/library/alloc/benches/btree/set.rs
+++ b/library/alloc/benches/btree/set.rs
@@ -3,13 +3,13 @@ use std::collections::BTreeSet;
 use rand::Rng;
 use test::Bencher;
 
-fn random(n: usize) -> BTreeSet<usize> {
+fn random(n: u32) -> BTreeSet<u32> {
     let mut rng = crate::bench_rng();
     let mut set = BTreeSet::new();
-    while set.len() < n {
-        set.insert(rng.gen());
+    while set.len() < n as usize {
+        set.insert(rng.random());
     }
-    assert_eq!(set.len(), n);
+    assert_eq!(set.len(), n as usize);
     set
 }
 
diff --git a/library/alloc/benches/slice.rs b/library/alloc/benches/slice.rs
index c45c3722712..c6b46e6a2a1 100644
--- a/library/alloc/benches/slice.rs
+++ b/library/alloc/benches/slice.rs
@@ -1,7 +1,7 @@
 use std::{mem, ptr};
 
 use rand::Rng;
-use rand::distributions::{Alphanumeric, DistString, Standard};
+use rand::distr::{Alphanumeric, SampleString, StandardUniform};
 use test::{Bencher, black_box};
 
 #[bench]
@@ -156,7 +156,7 @@ fn random_inserts(b: &mut Bencher) {
         let mut v = vec![(0, 0); 30];
         for _ in 0..100 {
             let l = v.len();
-            v.insert(rng.gen::<usize>() % (l + 1), (1, 1));
+            v.insert(rng.random::<u32>() as usize % (l + 1), (1, 1));
         }
     })
 }
@@ -168,7 +168,7 @@ fn random_removes(b: &mut Bencher) {
         let mut v = vec![(0, 0); 130];
         for _ in 0..100 {
             let l = v.len();
-            v.remove(rng.gen::<usize>() % l);
+            v.remove(rng.random::<u32>() as usize % l);
         }
     })
 }
@@ -183,20 +183,20 @@ fn gen_descending(len: usize) -> Vec<u64> {
 
 fn gen_random(len: usize) -> Vec<u64> {
     let mut rng = crate::bench_rng();
-    (&mut rng).sample_iter(&Standard).take(len).collect()
+    (&mut rng).sample_iter(&StandardUniform).take(len).collect()
 }
 
 fn gen_random_bytes(len: usize) -> Vec<u8> {
     let mut rng = crate::bench_rng();
-    (&mut rng).sample_iter(&Standard).take(len).collect()
+    (&mut rng).sample_iter(&StandardUniform).take(len).collect()
 }
 
 fn gen_mostly_ascending(len: usize) -> Vec<u64> {
     let mut rng = crate::bench_rng();
     let mut v = gen_ascending(len);
     for _ in (0usize..).take_while(|x| x * x <= len) {
-        let x = rng.gen::<usize>() % len;
-        let y = rng.gen::<usize>() % len;
+        let x = rng.random::<u32>() as usize % len;
+        let y = rng.random::<u32>() as usize % len;
         v.swap(x, y);
     }
     v
@@ -206,8 +206,8 @@ fn gen_mostly_descending(len: usize) -> Vec<u64> {
     let mut rng = crate::bench_rng();
     let mut v = gen_descending(len);
     for _ in (0usize..).take_while(|x| x * x <= len) {
-        let x = rng.gen::<usize>() % len;
-        let y = rng.gen::<usize>() % len;
+        let x = rng.random::<u32>() as usize % len;
+        let y = rng.random::<u32>() as usize % len;
         v.swap(x, y);
     }
     v
@@ -217,15 +217,15 @@ fn gen_strings(len: usize) -> Vec<String> {
     let mut rng = crate::bench_rng();
     let mut v = vec![];
     for _ in 0..len {
-        let n = rng.gen::<usize>() % 20 + 1;
-        v.push(Alphanumeric.sample_string(&mut rng, n));
+        let n = rng.random::<u32>() % 20 + 1;
+        v.push(Alphanumeric.sample_string(&mut rng, n as usize));
     }
     v
 }
 
 fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
     let mut rng = crate::bench_rng();
-    (&mut rng).sample_iter(&Standard).map(|x| [x; 16]).take(len).collect()
+    (&mut rng).sample_iter(&StandardUniform).map(|x| [x; 16]).take(len).collect()
 }
 
 macro_rules! sort {
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 60e46dc7a09..1ea7b731461 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -24,7 +24,7 @@
 //! Creating a recursive data structure:
 //!
 //! ```
-//! ##[allow(dead_code)]
+//! # #[allow(dead_code)]
 //! #[derive(Debug)]
 //! enum List<T> {
 //!     Cons(T, Box<List<T>>),
@@ -97,12 +97,12 @@
 //! #[repr(C)]
 //! pub struct Foo;
 //!
-//! #[no_mangle]
+//! #[unsafe(no_mangle)]
 //! pub extern "C" fn foo_new() -> Box<Foo> {
 //!     Box::new(Foo)
 //! }
 //!
-//! #[no_mangle]
+//! #[unsafe(no_mangle)]
 //! pub extern "C" fn foo_delete(_: Option<Box<Foo>>) {}
 //! ```
 //!
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 55cd0569538..7d02a15ed7a 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1837,7 +1837,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// # // don't use this as a starting point for a real library.
     /// # pub struct StreamWrapper { strm: *mut std::ffi::c_void }
     /// # const Z_OK: i32 = 0;
-    /// # extern "C" {
+    /// # unsafe extern "C" {
     /// #     fn deflateGetDictionary(
     /// #         strm: *mut std::ffi::c_void,
     /// #         dictionary: *mut u8,
diff --git a/library/alloc/tests/sort/patterns.rs b/library/alloc/tests/sort/patterns.rs
index e5d31d868b2..0f1ec664d3d 100644
--- a/library/alloc/tests/sort/patterns.rs
+++ b/library/alloc/tests/sort/patterns.rs
@@ -1,8 +1,8 @@
 use std::env;
-use std::hash::Hash;
 use std::str::FromStr;
 use std::sync::OnceLock;
 
+use rand::distr::Uniform;
 use rand::prelude::*;
 use rand_xorshift::XorShiftRng;
 
@@ -23,14 +23,14 @@ pub fn random(len: usize) -> Vec<i32> {
 
 pub fn random_uniform<R>(len: usize, range: R) -> Vec<i32>
 where
-    R: Into<rand::distributions::Uniform<i32>> + Hash,
+    Uniform<i32>: TryFrom<R, Error: std::fmt::Debug>,
 {
     // :.:.:.::
 
     let mut rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed());
 
     // Abstracting over ranges in Rust :(
-    let dist: rand::distributions::Uniform<i32> = range.into();
+    let dist = Uniform::try_from(range).unwrap();
     (0..len).map(|_| dist.sample(&mut rng)).collect()
 }
 
@@ -207,5 +207,5 @@ fn rand_root_seed() -> u64 {
 
 fn random_vec(len: usize) -> Vec<i32> {
     let mut rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed());
-    (0..len).map(|_| rng.gen::<i32>()).collect()
+    (0..len).map(|_| rng.random::<i32>()).collect()
 }
diff --git a/library/alloc/tests/sort/zipf.rs b/library/alloc/tests/sort/zipf.rs
index cc774ee5c43..3dad2db521f 100644
--- a/library/alloc/tests/sort/zipf.rs
+++ b/library/alloc/tests/sort/zipf.rs
@@ -80,7 +80,7 @@ impl ZipfDistribution {
 
         loop {
             use std::cmp;
-            let u: f64 = hnum + rng.gen::<f64>() * (self.h_integral_x1 - hnum);
+            let u: f64 = hnum + rng.random::<f64>() * (self.h_integral_x1 - hnum);
             // u is uniformly distributed in (h_integral_x1, h_integral_num_elements]
 
             let x: f64 = ZipfDistribution::h_integral_inv(u, self.exponent);
@@ -145,7 +145,7 @@ impl ZipfDistribution {
     }
 }
 
-impl rand::distributions::Distribution<usize> for ZipfDistribution {
+impl rand::distr::Distribution<usize> for ZipfDistribution {
     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
         self.next(rng)
     }
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 0d8c3ef906b..2c7f1d86341 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -345,7 +345,7 @@ impl<T> MaybeUninit<T> {
     ///
     /// use std::mem::MaybeUninit;
     ///
-    /// extern "C" {
+    /// unsafe extern "C" {
     ///     fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize;
     /// }
     ///
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 5b258a7c844..05c16791ce7 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -361,7 +361,7 @@ impl str {
     /// ```
     #[must_use]
     #[stable(feature = "is_char_boundary", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_is_char_boundary", issue = "131516")]
+    #[rustc_const_stable(feature = "const_is_char_boundary", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn is_char_boundary(&self, index: usize) -> bool {
         // 0 is always ok.
@@ -818,7 +818,7 @@ impl str {
     #[inline]
     #[must_use]
     #[stable(feature = "str_split_at", since = "1.4.0")]
-    #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")]
+    #[rustc_const_stable(feature = "const_str_split_at", since = "CURRENT_RUSTC_VERSION")]
     pub const fn split_at(&self, mid: usize) -> (&str, &str) {
         match self.split_at_checked(mid) {
             None => slice_error_fail(self, 0, mid),
@@ -859,7 +859,7 @@ impl str {
     #[inline]
     #[must_use]
     #[stable(feature = "str_split_at", since = "1.4.0")]
-    #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")]
+    #[rustc_const_stable(feature = "const_str_split_at", since = "CURRENT_RUSTC_VERSION")]
     pub const fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
@@ -899,7 +899,7 @@ impl str {
     #[inline]
     #[must_use]
     #[stable(feature = "split_at_checked", since = "1.80.0")]
-    #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")]
+    #[rustc_const_stable(feature = "const_str_split_at", since = "CURRENT_RUSTC_VERSION")]
     pub const fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
@@ -940,7 +940,7 @@ impl str {
     #[inline]
     #[must_use]
     #[stable(feature = "split_at_checked", since = "1.80.0")]
-    #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")]
+    #[rustc_const_stable(feature = "const_str_split_at", since = "CURRENT_RUSTC_VERSION")]
     pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str)> {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
diff --git a/library/coretests/Cargo.toml b/library/coretests/Cargo.toml
index ec940abea11..e44f01d347b 100644
--- a/library/coretests/Cargo.toml
+++ b/library/coretests/Cargo.toml
@@ -6,7 +6,7 @@ repository = "https://github.com/rust-lang/rust.git"
 description = "Tests for the Rust Core Library"
 autotests = false
 autobenches = false
-edition = "2021"
+edition = "2024"
 
 [lib]
 path = "lib.rs"
@@ -23,5 +23,5 @@ path = "benches/lib.rs"
 test = true
 
 [dev-dependencies]
-rand = { version = "0.8.5", default-features = false }
-rand_xorshift = { version = "0.3.0", default-features = false }
+rand = { version = "0.9.0", default-features = false }
+rand_xorshift = { version = "0.4.0", default-features = false }
diff --git a/library/coretests/benches/num/int_log/mod.rs b/library/coretests/benches/num/int_log/mod.rs
index e5874ddf03b..171d7e31cdb 100644
--- a/library/coretests/benches/num/int_log/mod.rs
+++ b/library/coretests/benches/num/int_log/mod.rs
@@ -21,7 +21,7 @@ macro_rules! int_log10_bench {
             /* Exponentially distributed random numbers from the whole range of the type.  */
             let numbers: Vec<$t> = (0..256)
                 .map(|_| {
-                    let x = rng.gen::<$t>() >> rng.gen_range(0..<$t>::BITS);
+                    let x = rng.random::<$t>() >> rng.random_range(0..<$t>::BITS);
                     if x != 0 { x } else { 1 }
                 })
                 .collect();
@@ -38,7 +38,7 @@ macro_rules! int_log10_bench {
             /* Exponentially distributed random numbers from the range 0..256.  */
             let numbers: Vec<$t> = (0..256)
                 .map(|_| {
-                    let x = (rng.gen::<u8>() >> rng.gen_range(0..u8::BITS)) as $t;
+                    let x = (rng.random::<u8>() >> rng.random_range(0..u8::BITS)) as $t;
                     if x != 0 { x } else { 1 }
                 })
                 .collect();
@@ -65,7 +65,7 @@ macro_rules! int_log_bench {
             /* Exponentially distributed random numbers from the whole range of the type.  */
             let numbers: Vec<$t> = (0..256)
                 .map(|_| {
-                    let x = rng.gen::<$t>() >> rng.gen_range(0..<$t>::BITS);
+                    let x = rng.random::<$t>() >> rng.random_range(0..<$t>::BITS);
                     if x >= 2 { x } else { 2 }
                 })
                 .collect();
@@ -84,7 +84,7 @@ macro_rules! int_log_bench {
             /* Exponentially distributed random numbers from the range 0..256.  */
             let numbers: Vec<$t> = (0..256)
                 .map(|_| {
-                    let x = (rng.gen::<u8>() >> rng.gen_range(0..u8::BITS)) as $t;
+                    let x = (rng.random::<u8>() >> rng.random_range(0..u8::BITS)) as $t;
                     if x >= 2 { x } else { 2 }
                 })
                 .collect();
diff --git a/library/coretests/benches/num/int_pow/mod.rs b/library/coretests/benches/num/int_pow/mod.rs
index 46f47028d56..6b603d2f7b3 100644
--- a/library/coretests/benches/num/int_pow/mod.rs
+++ b/library/coretests/benches/num/int_pow/mod.rs
@@ -15,9 +15,9 @@ macro_rules! pow_bench_template {
             // reference through black_box outside of the loop.
             let mut rng = crate::bench_rng();
             let base_array: [IntType; ITERATIONS] =
-                core::array::from_fn(|_| rng.gen_range((-MAX_BASE..=MAX_BASE)));
+                core::array::from_fn(|_| rng.random_range((-MAX_BASE..=MAX_BASE)));
             let exp_array: [u32; ITERATIONS] =
-                core::array::from_fn(|_| rng.gen_range((0..=EXPONENT_MAX)));
+                core::array::from_fn(|_| rng.random_range((0..=EXPONENT_MAX)));
 
             bench.iter(|| {
                 #[allow(unused, unused_mut)]
diff --git a/library/coretests/benches/num/int_sqrt/mod.rs b/library/coretests/benches/num/int_sqrt/mod.rs
index e47b92e866e..05cb3c5383b 100644
--- a/library/coretests/benches/num/int_sqrt/mod.rs
+++ b/library/coretests/benches/num/int_sqrt/mod.rs
@@ -20,7 +20,7 @@ macro_rules! int_sqrt_bench {
             let mut rng = crate::bench_rng();
             /* Exponentially distributed random numbers from the whole range of the type.  */
             let numbers: Vec<$t> =
-                (0..256).map(|_| rng.gen::<$t>() >> rng.gen_range(0..<$t>::BITS)).collect();
+                (0..256).map(|_| rng.random::<$t>() >> rng.random_range(0..<$t>::BITS)).collect();
             bench.iter(|| {
                 for x in &numbers {
                     black_box(black_box(x).isqrt());
@@ -32,8 +32,9 @@ macro_rules! int_sqrt_bench {
         fn $random_small(bench: &mut Bencher) {
             let mut rng = crate::bench_rng();
             /* Exponentially distributed random numbers from the range 0..256.  */
-            let numbers: Vec<$t> =
-                (0..256).map(|_| (rng.gen::<u8>() >> rng.gen_range(0..u8::BITS)) as $t).collect();
+            let numbers: Vec<$t> = (0..256)
+                .map(|_| (rng.random::<u8>() >> rng.random_range(0..u8::BITS)) as $t)
+                .collect();
             bench.iter(|| {
                 for x in &numbers {
                     black_box(black_box(x).isqrt());
@@ -45,7 +46,7 @@ macro_rules! int_sqrt_bench {
         fn $random_uniform(bench: &mut Bencher) {
             let mut rng = crate::bench_rng();
             /* Exponentially distributed random numbers from the whole range of the type.  */
-            let numbers: Vec<$t> = (0..256).map(|_| rng.gen::<$t>()).collect();
+            let numbers: Vec<$t> = (0..256).map(|_| rng.random::<$t>()).collect();
             bench.iter(|| {
                 for x in &numbers {
                     black_box(black_box(x).isqrt());
diff --git a/library/coretests/benches/slice.rs b/library/coretests/benches/slice.rs
index 29a66b62199..71027981d94 100644
--- a/library/coretests/benches/slice.rs
+++ b/library/coretests/benches/slice.rs
@@ -94,7 +94,7 @@ fn binary_search_l3_worst_case(b: &mut Bencher) {
 struct Rgb(#[allow(dead_code)] u8, #[allow(dead_code)] u8, #[allow(dead_code)] u8);
 
 impl Rgb {
-    fn gen(i: usize) -> Self {
+    fn new(i: usize) -> Self {
         Rgb(i as u8, (i as u8).wrapping_add(7), (i as u8).wrapping_add(42))
     }
 }
@@ -115,7 +115,7 @@ macro_rules! rotate {
 }
 
 rotate!(rotate_u8, 32, |i| i as u8);
-rotate!(rotate_rgb, 32, Rgb::gen);
+rotate!(rotate_rgb, 32, Rgb::new);
 rotate!(rotate_usize, 32, |i| i);
 rotate!(rotate_16_usize_4, 16, |i| [i; 4]);
 rotate!(rotate_16_usize_5, 16, |i| [i; 5]);
@@ -142,8 +142,8 @@ macro_rules! swap_with_slice {
 
 swap_with_slice!(swap_with_slice_u8_30, 30, |i| i as u8);
 swap_with_slice!(swap_with_slice_u8_3000, 3000, |i| i as u8);
-swap_with_slice!(swap_with_slice_rgb_30, 30, Rgb::gen);
-swap_with_slice!(swap_with_slice_rgb_3000, 3000, Rgb::gen);
+swap_with_slice!(swap_with_slice_rgb_30, 30, Rgb::new);
+swap_with_slice!(swap_with_slice_rgb_3000, 3000, Rgb::new);
 swap_with_slice!(swap_with_slice_usize_30, 30, |i| i);
 swap_with_slice!(swap_with_slice_usize_3000, 3000, |i| i);
 swap_with_slice!(swap_with_slice_4x_usize_30, 30, |i| [i; 4]);
diff --git a/library/coretests/tests/io/borrowed_buf.rs b/library/coretests/tests/io/borrowed_buf.rs
index a5dd4e52577..fbd3864dcac 100644
--- a/library/coretests/tests/io/borrowed_buf.rs
+++ b/library/coretests/tests/io/borrowed_buf.rs
@@ -145,7 +145,7 @@ fn cursor_set_init() {
     assert_eq!(rbuf.unfilled().init_ref().len(), 8);
     assert_eq!(rbuf.unfilled().init_mut().len(), 8);
     assert_eq!(rbuf.unfilled().uninit_mut().len(), 8);
-    assert_eq!(unsafe { rbuf.unfilled().as_mut() }.len(), 16);
+    assert_eq!(unsafe { rbuf.unfilled().as_mut().len() }, 16);
 
     rbuf.unfilled().advance(4);
 
@@ -163,5 +163,5 @@ fn cursor_set_init() {
     assert_eq!(rbuf.unfilled().init_ref().len(), 8);
     assert_eq!(rbuf.unfilled().init_mut().len(), 8);
     assert_eq!(rbuf.unfilled().uninit_mut().len(), 4);
-    assert_eq!(unsafe { rbuf.unfilled().as_mut() }.len(), 12);
+    assert_eq!(unsafe { rbuf.unfilled().as_mut().len() }, 12);
 }
diff --git a/library/coretests/tests/num/flt2dec/random.rs b/library/coretests/tests/num/flt2dec/random.rs
index 90042ae03bf..586b49df7d9 100644
--- a/library/coretests/tests/num/flt2dec/random.rs
+++ b/library/coretests/tests/num/flt2dec/random.rs
@@ -5,7 +5,7 @@ use core::num::flt2dec::{DecodableFloat, Decoded, FullDecoded, MAX_SIG_DIGITS, d
 use std::mem::MaybeUninit;
 use std::str;
 
-use rand::distributions::{Distribution, Uniform};
+use rand::distr::{Distribution, Uniform};
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
@@ -85,7 +85,7 @@ where
     G: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
 {
     let mut rng = crate::test_rng();
-    let f32_range = Uniform::new(0x0000_0001u32, 0x7f80_0000);
+    let f32_range = Uniform::new(0x0000_0001u32, 0x7f80_0000).unwrap();
     iterate("f32_random_equivalence_test", k, n, f, g, |_| {
         let x = f32::from_bits(f32_range.sample(&mut rng));
         decode_finite(x)
@@ -98,7 +98,7 @@ where
     G: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
 {
     let mut rng = crate::test_rng();
-    let f64_range = Uniform::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000);
+    let f64_range = Uniform::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000).unwrap();
     iterate("f64_random_equivalence_test", k, n, f, g, |_| {
         let x = f64::from_bits(f64_range.sample(&mut rng));
         decode_finite(x)
diff --git a/library/coretests/tests/pin.rs b/library/coretests/tests/pin.rs
index 026d2ca8de2..b3fb06e710d 100644
--- a/library/coretests/tests/pin.rs
+++ b/library/coretests/tests/pin.rs
@@ -28,7 +28,9 @@ fn pin_const() {
     const fn pin_mut_const() {
         let _ = Pin::new(&mut 2).into_ref();
         let _ = Pin::new(&mut 2).get_mut();
-        let _ = unsafe { Pin::new(&mut 2).get_unchecked_mut() };
+        unsafe {
+            let _ = Pin::new(&mut 2).get_unchecked_mut();
+        }
     }
 
     pin_mut_const();
diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs
index caffb66767d..1c5c8a9ebf2 100644
--- a/library/coretests/tests/slice.rs
+++ b/library/coretests/tests/slice.rs
@@ -5,6 +5,8 @@ use core::num::NonZero;
 use core::ops::{Range, RangeInclusive};
 use core::slice;
 
+use rand::seq::IndexedRandom;
+
 #[test]
 fn test_position() {
     let b = [1, 2, 3, 5, 5];
@@ -1291,7 +1293,7 @@ fn test_iter_ref_consistency() {
     fn test<T: Copy + Debug + PartialEq>(x: T) {
         let v: &[T] = &[x, x, x];
         let v_ptrs: [*const T; 3] = match v {
-            [ref v1, ref v2, ref v3] => [v1 as *const _, v2 as *const _, v3 as *const _],
+            [v1, v2, v3] => [v1 as *const _, v2 as *const _, v3 as *const _],
             _ => unreachable!(),
         };
         let len = v.len();
@@ -1346,7 +1348,7 @@ fn test_iter_ref_consistency() {
     fn test_mut<T: Copy + Debug + PartialEq>(x: T) {
         let v: &mut [T] = &mut [x, x, x];
         let v_ptrs: [*mut T; 3] = match v {
-            [ref v1, ref v2, ref v3] => {
+            &mut [ref v1, ref v2, ref v3] => {
                 [v1 as *const _ as *mut _, v2 as *const _ as *mut _, v3 as *const _ as *mut _]
             }
             _ => unreachable!(),
@@ -1808,7 +1810,6 @@ fn select_nth_unstable() {
     use core::cmp::Ordering::{Equal, Greater, Less};
 
     use rand::Rng;
-    use rand::seq::SliceRandom;
 
     let mut rng = crate::test_rng();
 
@@ -1818,7 +1819,7 @@ fn select_nth_unstable() {
         for &modulus in &[5, 10, 1000] {
             for _ in 0..10 {
                 for i in 0..len {
-                    orig[i] = rng.gen::<i32>() % modulus;
+                    orig[i] = rng.random::<i32>() % modulus;
                 }
 
                 let v_sorted = {
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index add5a20d179..36a0a59d939 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -61,8 +61,8 @@ object = { version = "0.36.0", default-features = false, optional = true, featur
 path = "../windows_targets"
 
 [dev-dependencies]
-rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
-rand_xorshift = "0.3.0"
+rand = { version = "0.9.0", default-features = false, features = ["alloc"] }
+rand_xorshift = "0.4.0"
 
 [target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
 dlmalloc = { version = "0.2.4", features = ['rustc-dep-of-std'] }
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index c665dfd3624..adbd6889624 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -568,7 +568,7 @@ pub struct JoinPathsError {
 ///         let mut paths = env::split_paths(&path).collect::<Vec<_>>();
 ///         paths.push(PathBuf::from("/home/xyz/bin"));
 ///         let new_path = env::join_paths(paths)?;
-///         env::set_var("PATH", &new_path);
+///         unsafe { env::set_var("PATH", &new_path); }
 ///     }
 ///
 ///     Ok(())
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 825a89fc7f2..bdd330611de 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -398,7 +398,7 @@ mod enum_keyword {}
 /// The mirror use case of FFI is also done via the `extern` keyword:
 ///
 /// ```rust
-/// #[no_mangle]
+/// #[unsafe(no_mangle)]
 /// pub extern "C" fn callable_from_c(x: i32) -> bool {
 ///     x % 3 == 0
 /// }
@@ -1428,7 +1428,7 @@ mod self_upper_keyword {}
 ///
 /// ```rust,no_run
 /// # #![allow(dead_code)]
-/// extern "C" {
+/// unsafe extern "C" {
 ///     static mut ERROR_MESSAGE: *mut std::os::raw::c_char;
 /// }
 /// ```
@@ -1925,7 +1925,7 @@ mod type_keyword {}
 ///
 /// unsafe fn unsafe_fn() {}
 ///
-/// extern "C" {
+/// unsafe extern "C" {
 ///     fn unsafe_extern_fn();
 ///     static BAR: *mut u32;
 /// }
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 153189b8b03..61801db072a 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -376,7 +376,9 @@ pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
 /// use std::panic;
 ///
 /// let result = panic::catch_unwind(|| {
-///     panic!("oh no!");
+///     if 1 != 2 {
+///         panic!("oh no!");
+///     }
 /// });
 ///
 /// if let Err(err) = result {
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 69273d863eb..5879914ca20 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -323,9 +323,13 @@ fn test_capture_env_at_spawn() {
 
     // This variable will not be present if the environment has already
     // been captured above.
-    env::set_var("RUN_TEST_NEW_ENV2", "456");
+    unsafe {
+        env::set_var("RUN_TEST_NEW_ENV2", "456");
+    }
     let result = cmd.output().unwrap();
-    env::remove_var("RUN_TEST_NEW_ENV2");
+    unsafe {
+        env::remove_var("RUN_TEST_NEW_ENV2");
+    }
 
     let output = String::from_utf8_lossy(&result.stdout).to_string();
 
diff --git a/library/std/src/sys/alloc/sgx.rs b/library/std/src/sys/alloc/sgx.rs
index fca9d087e5b..f5c27688fbc 100644
--- a/library/std/src/sys/alloc/sgx.rs
+++ b/library/std/src/sys/alloc/sgx.rs
@@ -11,7 +11,7 @@ use crate::sys::pal::waitqueue::SpinMutex;
 // in the rust-lang/rust repository as a submodule. The crate is a port of
 // dlmalloc.c from C to Rust.
 #[cfg_attr(test, linkage = "available_externally")]
-#[export_name = "_ZN16__rust_internals3std3sys3sgx5alloc8DLMALLOCE"]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx5alloc8DLMALLOCE")]
 static DLMALLOC: SpinMutex<dlmalloc::Dlmalloc<Sgx>> =
     SpinMutex::new(dlmalloc::Dlmalloc::new_with_allocator(Sgx {}));
 
@@ -85,13 +85,13 @@ unsafe impl GlobalAlloc for System {
 // The following functions are needed by libunwind. These symbols are named
 // in pre-link args for the target specification, so keep that in sync.
 #[cfg(not(test))]
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
     unsafe { crate::alloc::alloc(Layout::from_size_align_unchecked(size, align)) }
 }
 
 #[cfg(not(test))]
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
     unsafe { crate::alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align)) }
 }
diff --git a/library/std/src/sys/alloc/xous.rs b/library/std/src/sys/alloc/xous.rs
index 9d22e16fdf2..ccaa972c22d 100644
--- a/library/std/src/sys/alloc/xous.rs
+++ b/library/std/src/sys/alloc/xous.rs
@@ -4,7 +4,7 @@
 use crate::alloc::{GlobalAlloc, Layout, System};
 
 #[cfg(not(test))]
-#[export_name = "_ZN16__rust_internals3std3sys4xous5alloc8DLMALLOCE"]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys4xous5alloc8DLMALLOCE")]
 static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new();
 
 #[cfg(test)]
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index a746b853cbd..21cbac643bb 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -53,7 +53,7 @@ pub fn abort_internal() -> ! {
 // This function is needed by the panic runtime. The symbol is named in
 // pre-link args for the target specification, so keep that in sync.
 #[cfg(not(test))]
-#[no_mangle]
+#[unsafe(no_mangle)]
 // NB. used by both libunwind and libpanic_abort
 pub extern "C" fn __rust_abort() {
     abort_internal();
@@ -72,7 +72,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
 pub unsafe fn cleanup() {}
 
 #[cfg(not(test))]
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub unsafe extern "C" fn runtime_entry(
     argc: i32,
     argv: *const *const c_char,
diff --git a/library/std/src/sys/pal/sgx/abi/mod.rs b/library/std/src/sys/pal/sgx/abi/mod.rs
index f52acc41509..90981bd6a6a 100644
--- a/library/std/src/sys/pal/sgx/abi/mod.rs
+++ b/library/std/src/sys/pal/sgx/abi/mod.rs
@@ -23,7 +23,7 @@ global_asm!(include_str!("entry.S"), options(att_syntax));
 struct EntryReturn(u64, u64);
 
 #[cfg(not(test))]
-#[no_mangle]
+#[unsafe(no_mangle)]
 unsafe extern "C" fn tcs_init(secondary: bool) {
     // Be very careful when changing this code: it runs before the binary has been
     // relocated. Any indirect accesses to symbols will likely fail.
@@ -60,7 +60,7 @@ unsafe extern "C" fn tcs_init(secondary: bool) {
 // (main function exists). If this is a library, the crate author should be
 // able to specify this
 #[cfg(not(test))]
-#[no_mangle]
+#[unsafe(no_mangle)]
 extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> EntryReturn {
     // FIXME: how to support TLS in library mode?
     let tls = Box::new(tls::Tls::new());
@@ -103,7 +103,7 @@ pub(super) fn exit_with_code(code: isize) -> ! {
 }
 
 #[cfg(not(test))]
-#[no_mangle]
+#[unsafe(no_mangle)]
 extern "C" fn abort_reentry() -> ! {
     usercalls::exit(false)
 }
diff --git a/library/std/src/sys/pal/sgx/abi/tls/mod.rs b/library/std/src/sys/pal/sgx/abi/tls/mod.rs
index 7131797003b..8e2b271f1c9 100644
--- a/library/std/src/sys/pal/sgx/abi/tls/mod.rs
+++ b/library/std/src/sys/pal/sgx/abi/tls/mod.rs
@@ -12,14 +12,14 @@ const TLS_KEYS: usize = 128; // Same as POSIX minimum
 const TLS_KEYS_BITSET_SIZE: usize = (TLS_KEYS + (USIZE_BITS - 1)) / USIZE_BITS;
 
 #[cfg_attr(test, linkage = "available_externally")]
-#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_KEY_IN_USEE"]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_KEY_IN_USEE")]
 static TLS_KEY_IN_USE: SyncBitset = SYNC_BITSET_INIT;
 macro_rules! dup {
     ((* $($exp:tt)*) $($val:tt)*) => (dup!( ($($exp)*) $($val)* $($val)* ));
     (() $($val:tt)*) => ([$($val),*])
 }
 #[cfg_attr(test, linkage = "available_externally")]
-#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE"]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE")]
 static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) (AtomicUsize::new(0)));
 
 unsafe extern "C" {
diff --git a/library/std/src/sys/pal/sgx/args.rs b/library/std/src/sys/pal/sgx/args.rs
index a72a041da6c..e62bf383954 100644
--- a/library/std/src/sys/pal/sgx/args.rs
+++ b/library/std/src/sys/pal/sgx/args.rs
@@ -7,7 +7,7 @@ use crate::sys_common::FromInner;
 use crate::{fmt, slice};
 
 #[cfg_attr(test, linkage = "available_externally")]
-#[export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE"]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE")]
 static ARGS: AtomicUsize = AtomicUsize::new(0);
 type ArgsStore = Vec<OsString>;
 
diff --git a/library/std/src/sys/pal/sgx/libunwind_integration.rs b/library/std/src/sys/pal/sgx/libunwind_integration.rs
index debfd324c86..6d0d78d1eb9 100644
--- a/library/std/src/sys/pal/sgx/libunwind_integration.rs
+++ b/library/std/src/sys/pal/sgx/libunwind_integration.rs
@@ -15,7 +15,7 @@ const _: () = unsafe {
 
 const EINVAL: i32 = 22;
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RwLock) -> i32 {
     if p.is_null() {
         return EINVAL;
@@ -27,7 +27,7 @@ pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RwLock) -> i32 {
     return 0;
 }
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RwLock) -> i32 {
     if p.is_null() {
         return EINVAL;
@@ -36,7 +36,7 @@ pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RwLock) -> i32 {
     return 0;
 }
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RwLock) -> i32 {
     if p.is_null() {
         return EINVAL;
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index 9a04fa4b97e..37ca6b08c95 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -123,7 +123,7 @@ pub fn abort_internal() -> ! {
 // This function is needed by the panic runtime. The symbol is named in
 // pre-link args for the target specification, so keep that in sync.
 #[cfg(not(test))]
-#[no_mangle]
+#[unsafe(no_mangle)]
 // NB. used by both libunwind and libpanic_abort
 pub extern "C" fn __rust_abort() {
     abort_internal();
diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/pal/sgx/os.rs
index 46af710aa39..b1ec2afd764 100644
--- a/library/std/src/sys/pal/sgx/os.rs
+++ b/library/std/src/sys/pal/sgx/os.rs
@@ -74,10 +74,10 @@ pub fn current_exe() -> io::Result<PathBuf> {
 }
 
 #[cfg_attr(test, linkage = "available_externally")]
-#[export_name = "_ZN16__rust_internals3std3sys3sgx2os3ENVE"]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx2os3ENVE")]
 static ENV: AtomicUsize = AtomicUsize::new(0);
 #[cfg_attr(test, linkage = "available_externally")]
-#[export_name = "_ZN16__rust_internals3std3sys3sgx2os8ENV_INITE"]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx2os8ENV_INITE")]
 static ENV_INIT: Once = Once::new();
 type EnvStore = Mutex<HashMap<OsString, OsString>>;
 
diff --git a/library/std/src/sys/pal/sgx/stdio.rs b/library/std/src/sys/pal/sgx/stdio.rs
index e79a3d971c6..726a93acae4 100644
--- a/library/std/src/sys/pal/sgx/stdio.rs
+++ b/library/std/src/sys/pal/sgx/stdio.rs
@@ -76,7 +76,7 @@ pub fn panic_output() -> Option<impl io::Write> {
 // This function is needed by libunwind. The symbol is named in pre-link args
 // for the target specification, so keep that in sync.
 #[cfg(not(test))]
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
     if s < 0 {
         return;
diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs
index cecd53c352c..b6932df431f 100644
--- a/library/std/src/sys/pal/sgx/thread.rs
+++ b/library/std/src/sys/pal/sgx/thread.rs
@@ -46,7 +46,7 @@ mod task_queue {
     }
 
     #[cfg_attr(test, linkage = "available_externally")]
-    #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"]
+    #[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE")]
     static TASK_QUEUE: Mutex<Vec<Task>> = Mutex::new(Vec::new());
 
     pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index 4766e2ef0a9..8e6aea452f8 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -169,7 +169,7 @@ pub fn abort_internal() -> ! {
 // This function is needed by the panic runtime. The symbol is named in
 // pre-link args for the target specification, so keep that in sync.
 #[cfg(not(test))]
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub extern "C" fn __rust_abort() {
     abort_internal();
 }
diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/pal/uefi/process.rs
index 0757f1cb490..9efe9a314f2 100644
--- a/library/std/src/sys/pal/uefi/process.rs
+++ b/library/std/src/sys/pal/uefi/process.rs
@@ -154,8 +154,8 @@ impl Command {
         if let Some(e) = &env {
             for (k, (_, v)) in e {
                 match v {
-                    Some(v) => crate::env::set_var(k, v),
-                    None => crate::env::remove_var(k),
+                    Some(v) => unsafe { crate::env::set_var(k, v) },
+                    None => unsafe { crate::env::remove_var(k) },
                 }
             }
         }
@@ -166,8 +166,8 @@ impl Command {
         if let Some(e) = env {
             for (k, (v, _)) in e {
                 match v {
-                    Some(v) => crate::env::set_var(k, v),
-                    None => crate::env::remove_var(k),
+                    Some(v) => unsafe { crate::env::set_var(k, v) },
+                    None => unsafe { crate::env::remove_var(k) },
                 }
             }
         }
diff --git a/library/std/src/sys/pal/unix/linux/pidfd/tests.rs b/library/std/src/sys/pal/unix/linux/pidfd/tests.rs
index fb928c76fbd..17b06bea912 100644
--- a/library/std/src/sys/pal/unix/linux/pidfd/tests.rs
+++ b/library/std/src/sys/pal/unix/linux/pidfd/tests.rs
@@ -45,8 +45,8 @@ fn test_command_pidfd() {
         .expect_err("pidfd should not have been created");
 
     // exercise the fork/exec path since the earlier attempts may have used pidfd_spawnp()
-    let mut child =
-        unsafe { Command::new("false").pre_exec(|| Ok(())) }.create_pidfd(true).spawn().unwrap();
+    let mut cmd = Command::new("false");
+    let mut child = unsafe { cmd.pre_exec(|| Ok(())) }.create_pidfd(true).spawn().unwrap();
 
     assert!(child.id() > 0 && child.id() < -1i32 as u32);
 
diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs
index 7705e7f6b88..faf3edd5da6 100644
--- a/library/std/src/sys/pal/wasi/fs.rs
+++ b/library/std/src/sys/pal/wasi/fs.rs
@@ -183,7 +183,7 @@ impl Iterator for ReadDir {
 
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         match &mut self.state {
-            ReadDirState::FillBuffer { next_read_offset, ref mut buf } => {
+            ReadDirState::FillBuffer { next_read_offset, buf } => {
                 let result = self.inner.dir.fd.readdir(buf, *next_read_offset);
                 match result {
                     Ok(read_bytes) => {
@@ -207,7 +207,7 @@ impl Iterator for ReadDir {
                     }
                 }
             }
-            ReadDirState::ProcessEntry { ref mut buf, next_read_offset, offset } => {
+            ReadDirState::ProcessEntry { buf, next_read_offset, offset } => {
                 let contents = &buf[*offset..];
                 const DIRENT_SIZE: usize = crate::mem::size_of::<wasi::Dirent>();
                 if contents.len() >= DIRENT_SIZE {
diff --git a/library/std/src/sys/pal/wasip2/cabi_realloc.rs b/library/std/src/sys/pal/wasip2/cabi_realloc.rs
index 820063173d6..78adf9002fd 100644
--- a/library/std/src/sys/pal/wasip2/cabi_realloc.rs
+++ b/library/std/src/sys/pal/wasip2/cabi_realloc.rs
@@ -32,7 +32,7 @@ static FORCE_CODEGEN_OF_CABI_REALLOC: unsafe extern "C" fn(
 ) -> *mut u8 = cabi_realloc;
 
 #[linkage = "weak"]
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub unsafe extern "C" fn cabi_realloc(
     old_ptr: *mut u8,
     old_len: usize,
diff --git a/library/std/src/sys/pal/windows/process/tests.rs b/library/std/src/sys/pal/windows/process/tests.rs
index 90f1157d7c4..1377e12162f 100644
--- a/library/std/src/sys/pal/windows/process/tests.rs
+++ b/library/std/src/sys/pal/windows/process/tests.rs
@@ -138,8 +138,10 @@ fn windows_env_unicode_case() {
         let mut cmd = Command::new("cmd");
         cmd.env(a, "1");
         cmd.env(b, "2");
-        env::set_var(a, "1");
-        env::set_var(b, "2");
+        unsafe {
+            env::set_var(a, "1");
+            env::set_var(b, "2");
+        }
 
         for (key, value) in cmd.get_envs() {
             assert_eq!(
diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs
index 307623c0425..2c87e7d91f2 100644
--- a/library/std/src/sys/pal/xous/os.rs
+++ b/library/std/src/sys/pal/xous/os.rs
@@ -41,12 +41,12 @@ mod c_compat {
         fn main() -> u32;
     }
 
-    #[no_mangle]
+    #[unsafe(no_mangle)]
     pub extern "C" fn abort() {
         exit(1);
     }
 
-    #[no_mangle]
+    #[unsafe(no_mangle)]
     pub extern "C" fn _start(eh_frame: usize, params_address: usize) {
         #[cfg(feature = "panic_unwind")]
         {
@@ -67,7 +67,7 @@ mod c_compat {
 
     // This function is needed by the panic runtime. The symbol is named in
     // pre-link args for the target specification, so keep that in sync.
-    #[no_mangle]
+    #[unsafe(no_mangle)]
     // NB. used by both libunwind and libpanic_abort
     pub extern "C" fn __rust_abort() -> ! {
         exit(101);
diff --git a/library/std/src/sys/thread_local/key/xous.rs b/library/std/src/sys/thread_local/key/xous.rs
index 6c5e6447d19..55ac5b20e1a 100644
--- a/library/std/src/sys/thread_local/key/xous.rs
+++ b/library/std/src/sys/thread_local/key/xous.rs
@@ -51,11 +51,11 @@ const TLS_MEMORY_SIZE: usize = 4096;
 
 /// TLS keys start at `1`. Index `0` is unused
 #[cfg(not(test))]
-#[export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key13TLS_KEY_INDEXE"]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key13TLS_KEY_INDEXE")]
 static TLS_KEY_INDEX: AtomicUsize = AtomicUsize::new(1);
 
 #[cfg(not(test))]
-#[export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key9DTORSE"]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key9DTORSE")]
 static DTORS: AtomicPtr<Node> = AtomicPtr::new(ptr::null_mut());
 
 #[cfg(test)]
diff --git a/library/std/tests/env_modify.rs b/library/std/tests/env_modify.rs
index 60747447350..ba84978b35f 100644
--- a/library/std/tests/env_modify.rs
+++ b/library/std/tests/env_modify.rs
@@ -4,7 +4,7 @@
 use std::env::*;
 use std::ffi::{OsStr, OsString};
 
-use rand::distributions::{Alphanumeric, DistString};
+use rand::distr::{Alphanumeric, SampleString};
 
 mod common;
 use std::thread;
@@ -26,26 +26,32 @@ fn eq(a: Option<OsString>, b: Option<&str>) {
 #[test]
 fn test_set_var() {
     let n = make_rand_name();
-    set_var(&n, "VALUE");
+    unsafe {
+        set_var(&n, "VALUE");
+    }
     eq(var_os(&n), Some("VALUE"));
 }
 
 #[test]
 fn test_remove_var() {
     let n = make_rand_name();
-    set_var(&n, "VALUE");
-    remove_var(&n);
+    unsafe {
+        set_var(&n, "VALUE");
+        remove_var(&n);
+    }
     eq(var_os(&n), None);
 }
 
 #[test]
 fn test_set_var_overwrite() {
     let n = make_rand_name();
-    set_var(&n, "1");
-    set_var(&n, "2");
-    eq(var_os(&n), Some("2"));
-    set_var(&n, "");
-    eq(var_os(&n), Some(""));
+    unsafe {
+        set_var(&n, "1");
+        set_var(&n, "2");
+        eq(var_os(&n), Some("2"));
+        set_var(&n, "");
+        eq(var_os(&n), Some(""));
+    }
 }
 
 #[test]
@@ -58,7 +64,9 @@ fn test_var_big() {
         i += 1;
     }
     let n = make_rand_name();
-    set_var(&n, &s);
+    unsafe {
+        set_var(&n, &s);
+    }
     eq(var_os(&n), Some(&s));
 }
 
@@ -67,10 +75,12 @@ fn test_var_big() {
 fn test_env_set_get_huge() {
     let n = make_rand_name();
     let s = "x".repeat(10000);
-    set_var(&n, &s);
-    eq(var_os(&n), Some(&s));
-    remove_var(&n);
-    eq(var_os(&n), None);
+    unsafe {
+        set_var(&n, &s);
+        eq(var_os(&n), Some(&s));
+        remove_var(&n);
+        eq(var_os(&n), None);
+    }
 }
 
 #[test]
@@ -78,7 +88,9 @@ fn test_env_set_var() {
     let n = make_rand_name();
 
     let mut e = vars_os();
-    set_var(&n, "VALUE");
+    unsafe {
+        set_var(&n, "VALUE");
+    }
     assert!(!e.any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));
 
     assert!(vars_os().any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));
@@ -102,10 +114,12 @@ fn env_home_dir() {
         if #[cfg(unix)] {
             let oldhome = var_to_os_string(var("HOME"));
 
-            set_var("HOME", "/home/MountainView");
-            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
+            unsafe {
+                set_var("HOME", "/home/MountainView");
+                assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
 
-            remove_var("HOME");
+                remove_var("HOME");
+            }
             if cfg!(target_os = "android") {
                 assert!(home_dir().is_none());
             } else {
@@ -115,33 +129,35 @@ fn env_home_dir() {
                 assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView")));
             }
 
-            if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
+            if let Some(oldhome) = oldhome { unsafe { set_var("HOME", oldhome); } }
         } else if #[cfg(windows)] {
             let oldhome = var_to_os_string(var("HOME"));
             let olduserprofile = var_to_os_string(var("USERPROFILE"));
 
-            remove_var("HOME");
-            remove_var("USERPROFILE");
+            unsafe {
+                remove_var("HOME");
+                remove_var("USERPROFILE");
 
-            assert!(home_dir().is_some());
+                assert!(home_dir().is_some());
 
-            set_var("HOME", "/home/PaloAlto");
-            assert_ne!(home_dir(), Some(PathBuf::from("/home/PaloAlto")), "HOME must not be used");
+                set_var("HOME", "/home/PaloAlto");
+                assert_ne!(home_dir(), Some(PathBuf::from("/home/PaloAlto")), "HOME must not be used");
 
-            set_var("USERPROFILE", "/home/MountainView");
-            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
+                set_var("USERPROFILE", "/home/MountainView");
+                assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
 
-            remove_var("HOME");
+                remove_var("HOME");
 
-            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
+                assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
 
-            set_var("USERPROFILE", "");
-            assert_ne!(home_dir(), Some(PathBuf::from("")), "Empty USERPROFILE must be ignored");
+                set_var("USERPROFILE", "");
+                assert_ne!(home_dir(), Some(PathBuf::from("")), "Empty USERPROFILE must be ignored");
 
-            remove_var("USERPROFILE");
+                remove_var("USERPROFILE");
 
-            if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
-            if let Some(olduserprofile) = olduserprofile { set_var("USERPROFILE", olduserprofile); }
+                if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
+                if let Some(olduserprofile) = olduserprofile { set_var("USERPROFILE", olduserprofile); }
+            }
         }
     }
 }
@@ -157,7 +173,9 @@ fn test_env_get_set_multithreaded() {
 
     let setter = thread::spawn(|| {
         for _ in 0..100 {
-            set_var("foo", "bar");
+            unsafe {
+                set_var("foo", "bar");
+            }
         }
     });
 
diff --git a/library/std/tests/sync/rwlock.rs b/library/std/tests/sync/rwlock.rs
index bd4bc7a14bc..49f260648c6 100644
--- a/library/std/tests/sync/rwlock.rs
+++ b/library/std/tests/sync/rwlock.rs
@@ -59,7 +59,7 @@ fn frob() {
         thread::spawn(move || {
             let mut rng = crate::common::test_rng();
             for _ in 0..M {
-                if rng.gen_bool(1.0 / (N as f64)) {
+                if rng.random_bool(1.0 / (N as f64)) {
                     drop(r.write().unwrap());
                 } else {
                     drop(r.read().unwrap());
diff --git a/library/test/src/term/terminfo/searcher/tests.rs b/library/test/src/term/terminfo/searcher/tests.rs
index e1edd3b25cf..ff532a97d5e 100644
--- a/library/test/src/term/terminfo/searcher/tests.rs
+++ b/library/test/src/term/terminfo/searcher/tests.rs
@@ -11,7 +11,11 @@ fn test_get_dbpath_for_term() {
     }
     assert_eq!(x("screen"), PathBuf::from("/usr/share/terminfo/s/screen"));
     assert_eq!(get_dbpath_for_term(""), None);
-    env::set_var("TERMINFO_DIRS", ":");
+    unsafe {
+        env::set_var("TERMINFO_DIRS", ":");
+    }
     assert_eq!(x("screen"), PathBuf::from("/usr/share/terminfo/s/screen"));
-    env::remove_var("TERMINFO_DIRS");
+    unsafe {
+        env::remove_var("TERMINFO_DIRS");
+    }
 }
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr
new file mode 100644
index 00000000000..171bf0c82d5
--- /dev/null
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr
@@ -0,0 +1,5 @@
+warning: target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly
+   |
+   = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
+
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 5478ff4a6c6..d75a68d5973 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -476,6 +476,8 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[
     "memchr",
     "miniz_oxide",
     "object",
+    "proc-macro2",
+    "quote",
     "r-efi",
     "r-efi-alloc",
     "rand",
@@ -483,6 +485,8 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[
     "rand_xorshift",
     "rustc-demangle",
     "shlex",
+    "syn",
+    "unicode-ident",
     "unicode-width",
     "unwinding",
     "wasi",
@@ -496,6 +500,8 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[
     "windows_x86_64_gnu",
     "windows_x86_64_gnullvm",
     "windows_x86_64_msvc",
+    "zerocopy",
+    "zerocopy-derive",
     // tidy-alphabetical-end
 ];
 
diff --git a/tests/codegen/common_prim_int_ptr.rs b/tests/codegen/common_prim_int_ptr.rs
index 8eb05024174..a1d7a125f32 100644
--- a/tests/codegen/common_prim_int_ptr.rs
+++ b/tests/codegen/common_prim_int_ptr.rs
@@ -40,7 +40,7 @@ pub unsafe fn extract_int(x: Result<usize, Box<()>>) -> usize {
 }
 
 // CHECK-LABEL: @extract_box
-// CHECK-SAME: (i{{[0-9]+}} {{[^%]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]])
+// CHECK-SAME: (i{{[0-9]+}} {{[^%]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^%]+}} [[PAYLOAD:%[0-9]+]])
 #[no_mangle]
 pub unsafe fn extract_box(x: Result<usize, Box<i32>>) -> Box<i32> {
     // CHECK: ret ptr [[PAYLOAD]]
diff --git a/tests/ui/closures/eager-mono-with-normalizable-upvars.rs b/tests/ui/closures/eager-mono-with-normalizable-upvars.rs
new file mode 100644
index 00000000000..4d934f7a7a9
--- /dev/null
+++ b/tests/ui/closures/eager-mono-with-normalizable-upvars.rs
@@ -0,0 +1,19 @@
+//@ compile-flags: -Clink-dead-code -Csymbol-mangling-version=v0
+//@ build-pass
+
+// Ensure that when eagerly collecting `test::{closure#0}`, we don't try
+// collecting an unnormalized version of the closure (specifically its
+// upvars), since the closure captures the RPIT `opaque::{opaque#0}`.
+
+fn opaque() -> impl Sized {}
+
+fn test() -> impl FnOnce() {
+    let opaque = opaque();
+    move || {
+        let opaque = opaque;
+    }
+}
+
+fn main() {
+    test()();
+}
diff --git a/tests/ui/impl-trait/impl-fn-rpit-opaque-107883.rs b/tests/ui/impl-trait/impl-fn-rpit-opaque-107883.rs
new file mode 100644
index 00000000000..3655bff63eb
--- /dev/null
+++ b/tests/ui/impl-trait/impl-fn-rpit-opaque-107883.rs
@@ -0,0 +1,37 @@
+//@ check-pass
+// Regression test for <https;//github.com/rust-lang/rust/issues/107883>
+#![feature(impl_trait_in_fn_trait_return)]
+#![feature(unboxed_closures)] // only for `h`
+
+use std::fmt::Debug;
+
+fn f<T>() -> impl Fn(T) -> impl Debug {
+    |_x| 15
+}
+
+fn g<T>() -> impl MyFn<(T,), Out = impl Debug> {
+    |_x| 15
+}
+
+trait MyFn<T> {
+    type Out;
+}
+
+impl<T, U, F: Fn(T) -> U> MyFn<(T,)> for F {
+    type Out = U;
+}
+
+fn h<T>() -> impl Fn<(T,), Output = impl Debug> {
+    |_x| 15
+}
+
+fn f_<T>() -> impl Fn(T) -> impl Debug {
+    std::convert::identity(|_x| 15)
+}
+
+fn f__<T>() -> impl Fn(T) -> impl Debug {
+    let r = |_x| 15;
+    r
+}
+
+fn main() {}
diff --git a/tests/ui/sse-abi-checks.rs b/tests/ui/sse-abi-checks.rs
index c453e91d11b..d400e6eb698 100644
--- a/tests/ui/sse-abi-checks.rs
+++ b/tests/ui/sse-abi-checks.rs
@@ -1,6 +1,6 @@
 //! Ensure we trigger abi_unsupported_vector_types for target features that are usually enabled
 //! on a target, but disabled in this file via a `-C` flag.
-//@ compile-flags: --crate-type=rlib --target=i686-unknown-linux-gnu -C target-feature=-sse,-sse2
+//@ compile-flags: --crate-type=rlib --target=i586-unknown-linux-gnu -C target-feature=-sse,-sse2
 //@ build-pass
 //@ ignore-pass (test emits codegen-time warnings)
 //@ needs-llvm-components: x86
diff --git a/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs
new file mode 100644
index 00000000000..28d026c1a9a
--- /dev/null
+++ b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs
@@ -0,0 +1,12 @@
+//@ compile-flags: --target=i686-unknown-linux-gnu --crate-type=lib
+//@ needs-llvm-components: x86
+//@ compile-flags: -Ctarget-cpu=pentium
+// For now this is just a warning.
+//@ build-pass
+//@error-pattern: must be enabled
+
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
diff --git a/tests/ui/target-feature/target-cpu-lacks-required-target-feature.stderr b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.stderr
new file mode 100644
index 00000000000..7ec8b04cfce
--- /dev/null
+++ b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.stderr
@@ -0,0 +1,7 @@
+warning: target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly
+   |
+   = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
+
+warning: 1 warning emitted
+
diff --git a/triagebot.toml b/triagebot.toml
index 52355189419..512736b0e8f 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -227,6 +227,16 @@ exclude_labels = [
     "T-*",
 ]
 
+trigger_labels = [
+    "A-rustdoc-json",
+    "A-rustdoc-type-layout",
+    "A-rustdoc-scrape-examples",
+    "A-link-to-definition",
+    "A-cross-crate-reexports",
+    "A-intra-doc-links",
+    "A-doc-alias",
+]
+
 [autolabel."A-rustdoc-json"]
 trigger_files = [
     "src/librustdoc/json/",
@@ -245,6 +255,33 @@ trigger_files = [
     "compiler/rustc_attr_validation",
 ]
 
+[autolabel."T-rustdoc-frontend"]
+trigger_labels = [
+    "A-rustdoc-search",
+    "A-rustdoc-ui",
+    "A-rustdoc-js",
+]
+
+trigger_files = [
+    "src/librustdoc/html/",
+    "tests/rustdoc/",
+    "tests/rustdoc-gui/",
+    "tests/rustdoc-js/",
+    "tests/rustdoc-js-std/",
+    # note: tests/rustdoc-ui tests the CLI, not the web frontend
+]
+
+[autolabel."A-rustdoc-search"]
+trigger_files = [
+    "src/librustdoc/html/static/js/search.js",
+    "tests/rustdoc-js",
+    "tests/rustdoc-js-std",
+]
+
+trigger_labels = [
+    "A-type-based-search",
+]
+
 [autolabel."T-compiler"]
 trigger_files = [
     # Source code