about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/lib.rs7
-rw-r--r--library/std/src/net/display_buffer.rs (renamed from library/std/src/net/ip/display_buffer.rs)6
-rw-r--r--library/std/src/net/ip_addr.rs (renamed from library/std/src/net/ip.rs)10
-rw-r--r--library/std/src/net/ip_addr/tests.rs (renamed from library/std/src/net/ip/tests.rs)0
-rw-r--r--library/std/src/net/mod.rs11
-rw-r--r--library/std/src/net/socket_addr.rs (renamed from library/std/src/net/addr.rs)58
-rw-r--r--library/std/src/net/socket_addr/tests.rs (renamed from library/std/src/net/addr/tests.rs)69
-rw-r--r--library/std/src/os/unix/net/addr.rs16
-rw-r--r--library/std/src/panic.rs33
-rw-r--r--library/std/src/panicking.rs133
-rw-r--r--library/std/src/path.rs2
-rw-r--r--library/std/src/primitive_docs.rs23
-rw-r--r--library/std/src/sys/sgx/abi/thread.rs8
-rw-r--r--library/std/src/sys/sgx/abi/usercalls/alloc.rs28
-rw-r--r--library/std/src/sys/solid/os.rs4
-rw-r--r--library/std/src/sys/unix/locks/mod.rs6
-rw-r--r--library/std/src/sys/unix/os.rs8
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs4
-rw-r--r--library/std/src/sys/unsupported/locks/mod.rs2
-rw-r--r--library/std/src/sys/wasm/mod.rs2
-rw-r--r--library/std/src/sys/windows/c.rs6
-rw-r--r--library/std/src/sys/windows/locks/mod.rs2
-rw-r--r--library/std/src/sys/windows/rand.rs76
-rw-r--r--library/std/src/sys_common/rwlock.rs60
24 files changed, 266 insertions, 308 deletions
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index f13500de014..3131dd47269 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -145,8 +145,8 @@
 //! abstracting over differences in common platforms, most notably Windows and
 //! Unix derivatives.
 //!
-//! Common types of I/O, including [files], [TCP], [UDP], are defined in the
-//! [`io`], [`fs`], and [`net`] modules.
+//! Common types of I/O, including [files], [TCP], and [UDP], are defined in
+//! the [`io`], [`fs`], and [`net`] modules.
 //!
 //! The [`thread`] module contains Rust's threading abstractions. [`sync`]
 //! contains further primitive shared memory types, including [`atomic`] and
@@ -255,7 +255,7 @@
 #![cfg_attr(bootstrap, feature(label_break_value))]
 #![feature(lang_items)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(linkage)]
 #![feature(link_cfg)]
 #![feature(min_specialization)]
@@ -315,6 +315,7 @@
 #![feature(strict_provenance)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(const_maybe_uninit_uninit_array)]
+#![feature(const_waker)]
 //
 // Library features (alloc):
 #![feature(alloc_layout_extra)]
diff --git a/library/std/src/net/ip/display_buffer.rs b/library/std/src/net/display_buffer.rs
index bd852d5da8e..7aadf06e92f 100644
--- a/library/std/src/net/ip/display_buffer.rs
+++ b/library/std/src/net/display_buffer.rs
@@ -3,12 +3,12 @@ use crate::mem::MaybeUninit;
 use crate::str;
 
 /// Used for slow path in `Display` implementations when alignment is required.
-pub struct IpDisplayBuffer<const SIZE: usize> {
+pub struct DisplayBuffer<const SIZE: usize> {
     buf: [MaybeUninit<u8>; SIZE],
     len: usize,
 }
 
-impl<const SIZE: usize> IpDisplayBuffer<SIZE> {
+impl<const SIZE: usize> DisplayBuffer<SIZE> {
     #[inline]
     pub const fn new() -> Self {
         Self { buf: MaybeUninit::uninit_array(), len: 0 }
@@ -25,7 +25,7 @@ impl<const SIZE: usize> IpDisplayBuffer<SIZE> {
     }
 }
 
-impl<const SIZE: usize> fmt::Write for IpDisplayBuffer<SIZE> {
+impl<const SIZE: usize> fmt::Write for DisplayBuffer<SIZE> {
     fn write_str(&mut self, s: &str) -> fmt::Result {
         let bytes = s.as_bytes();
 
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip_addr.rs
index 6004810655e..4f14fc28038 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip_addr.rs
@@ -8,8 +8,7 @@ use crate::mem::transmute;
 use crate::sys::net::netc as c;
 use crate::sys_common::{FromInner, IntoInner};
 
-mod display_buffer;
-use display_buffer::IpDisplayBuffer;
+use super::display_buffer::DisplayBuffer;
 
 /// An IP address, either IPv4 or IPv6.
 ///
@@ -30,6 +29,7 @@ use display_buffer::IpDisplayBuffer;
 /// assert_eq!(localhost_v4.is_ipv6(), false);
 /// assert_eq!(localhost_v4.is_ipv4(), true);
 /// ```
+#[cfg_attr(not(test), rustc_diagnostic_item = "IpAddr")]
 #[stable(feature = "ip_addr", since = "1.7.0")]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
 pub enum IpAddr {
@@ -73,6 +73,7 @@ pub enum IpAddr {
 /// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
 /// ```
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Ipv4Addr")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Ipv4Addr {
     octets: [u8; 4],
@@ -155,6 +156,7 @@ pub struct Ipv4Addr {
 /// assert_eq!(localhost.is_loopback(), true);
 /// ```
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Ipv6Addr")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Ipv6Addr {
     octets: [u8; 16],
@@ -997,7 +999,7 @@ impl fmt::Display for Ipv4Addr {
         } else {
             const LONGEST_IPV4_ADDR: &str = "255.255.255.255";
 
-            let mut buf = IpDisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new();
+            let mut buf = DisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new();
             // Buffer is long enough for the longest possible IPv4 address, so this should never fail.
             write!(buf, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
 
@@ -1844,7 +1846,7 @@ impl fmt::Display for Ipv6Addr {
         } else {
             const LONGEST_IPV6_ADDR: &str = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
 
-            let mut buf = IpDisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new();
+            let mut buf = DisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new();
             // Buffer is long enough for the longest possible IPv6 address, so this should never fail.
             write!(buf, "{}", self).unwrap();
 
diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip_addr/tests.rs
index 7c3430b2b21..7c3430b2b21 100644
--- a/library/std/src/net/ip/tests.rs
+++ b/library/std/src/net/ip_addr/tests.rs
diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs
index 6f9743f3a0e..01e3db9de51 100644
--- a/library/std/src/net/mod.rs
+++ b/library/std/src/net/mod.rs
@@ -24,11 +24,11 @@
 use crate::io::{self, ErrorKind};
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
+pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::parser::AddrParseError;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::socket_addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
 #[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
 pub use self::tcp::IntoIncoming;
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -36,9 +36,10 @@ pub use self::tcp::{Incoming, TcpListener, TcpStream};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::udp::UdpSocket;
 
-mod addr;
-mod ip;
+mod display_buffer;
+mod ip_addr;
 mod parser;
+mod socket_addr;
 mod tcp;
 #[cfg(test)]
 pub(crate) mod test;
diff --git a/library/std/src/net/addr.rs b/library/std/src/net/socket_addr.rs
index 53fee952a7a..33b0dfa03e0 100644
--- a/library/std/src/net/addr.rs
+++ b/library/std/src/net/socket_addr.rs
@@ -2,9 +2,9 @@
 mod tests;
 
 use crate::cmp::Ordering;
-use crate::fmt;
+use crate::fmt::{self, Write};
 use crate::hash;
-use crate::io::{self, Write};
+use crate::io;
 use crate::iter;
 use crate::mem;
 use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
@@ -15,6 +15,8 @@ use crate::sys_common::net::LookupHost;
 use crate::sys_common::{FromInner, IntoInner};
 use crate::vec;
 
+use super::display_buffer::DisplayBuffer;
+
 /// An internet socket address, either IPv4 or IPv6.
 ///
 /// Internet socket addresses consist of an [IP address], a 16-bit port number, as well
@@ -616,25 +618,18 @@ impl fmt::Debug for SocketAddr {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for SocketAddrV4 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Fast path: if there's no alignment stuff, write to the output buffer
-        // directly
+        // If there are no alignment requirements, write the socket address directly to `f`.
+        // Otherwise, write it to a local buffer and then use `f.pad`.
         if f.precision().is_none() && f.width().is_none() {
             write!(f, "{}:{}", self.ip(), self.port())
         } else {
-            const IPV4_SOCKET_BUF_LEN: usize = (3 * 4)  // the segments
-                + 3  // the separators
-                + 1 + 5; // the port
-            let mut buf = [0; IPV4_SOCKET_BUF_LEN];
-            let mut buf_slice = &mut buf[..];
-
-            // Unwrap is fine because writing to a sufficiently-sized
-            // buffer is infallible
-            write!(buf_slice, "{}:{}", self.ip(), self.port()).unwrap();
-            let len = IPV4_SOCKET_BUF_LEN - buf_slice.len();
-
-            // This unsafe is OK because we know what is being written to the buffer
-            let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
-            f.pad(buf)
+            const LONGEST_IPV4_SOCKET_ADDR: &str = "255.255.255.255:65536";
+
+            let mut buf = DisplayBuffer::<{ LONGEST_IPV4_SOCKET_ADDR.len() }>::new();
+            // Buffer is long enough for the longest possible IPv4 socket address, so this should never fail.
+            write!(buf, "{}:{}", self.ip(), self.port()).unwrap();
+
+            f.pad(buf.as_str())
         }
     }
 }
@@ -649,35 +644,26 @@ impl fmt::Debug for SocketAddrV4 {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for SocketAddrV6 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Fast path: if there's no alignment stuff, write to the output
-        // buffer directly
+        // If there are no alignment requirements, write the socket address directly to `f`.
+        // Otherwise, write it to a local buffer and then use `f.pad`.
         if f.precision().is_none() && f.width().is_none() {
             match self.scope_id() {
                 0 => write!(f, "[{}]:{}", self.ip(), self.port()),
                 scope_id => write!(f, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
             }
         } else {
-            const IPV6_SOCKET_BUF_LEN: usize = (4 * 8)  // The address
-            + 7  // The colon separators
-            + 2  // The brackets
-            + 1 + 10 // The scope id
-            + 1 + 5; // The port
-
-            let mut buf = [0; IPV6_SOCKET_BUF_LEN];
-            let mut buf_slice = &mut buf[..];
+            const LONGEST_IPV6_SOCKET_ADDR: &str =
+                "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%4294967296]:65536";
 
+            let mut buf = DisplayBuffer::<{ LONGEST_IPV6_SOCKET_ADDR.len() }>::new();
             match self.scope_id() {
-                0 => write!(buf_slice, "[{}]:{}", self.ip(), self.port()),
-                scope_id => write!(buf_slice, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
+                0 => write!(buf, "[{}]:{}", self.ip(), self.port()),
+                scope_id => write!(buf, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
             }
-            // Unwrap is fine because writing to a sufficiently-sized
-            // buffer is infallible
+            // Buffer is long enough for the longest possible IPv6 socket address, so this should never fail.
             .unwrap();
-            let len = IPV6_SOCKET_BUF_LEN - buf_slice.len();
 
-            // This unsafe is OK because we know what is being written to the buffer
-            let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
-            f.pad(buf)
+            f.pad(buf.as_str())
         }
     }
 }
diff --git a/library/std/src/net/addr/tests.rs b/library/std/src/net/socket_addr/tests.rs
index 585a17451a0..15211f81981 100644
--- a/library/std/src/net/addr/tests.rs
+++ b/library/std/src/net/socket_addr/tests.rs
@@ -52,6 +52,75 @@ fn to_socket_addr_string() {
 }
 
 #[test]
+fn ipv4_socket_addr_to_string() {
+    // Shortest possible IPv4 length.
+    assert_eq!(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0).to_string(), "0.0.0.0:0");
+
+    // Longest possible IPv4 length.
+    assert_eq!(
+        SocketAddrV4::new(Ipv4Addr::new(255, 255, 255, 255), u16::MAX).to_string(),
+        "255.255.255.255:65535"
+    );
+
+    // Test padding.
+    assert_eq!(
+        &format!("{:16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
+        "1.1.1.1:53      "
+    );
+    assert_eq!(
+        &format!("{:>16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
+        "      1.1.1.1:53"
+    );
+}
+
+#[test]
+fn ipv6_socket_addr_to_string() {
+    // IPv4-mapped address.
+    assert_eq!(
+        SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280), 8080, 0, 0)
+            .to_string(),
+        "[::ffff:192.0.2.128]:8080"
+    );
+
+    // IPv4-compatible address.
+    assert_eq!(
+        SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280), 8080, 0, 0).to_string(),
+        "[::192.0.2.128]:8080"
+    );
+
+    // IPv6 address with no zero segments.
+    assert_eq!(
+        SocketAddrV6::new(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15), 80, 0, 0).to_string(),
+        "[8:9:a:b:c:d:e:f]:80"
+    );
+
+    // Shortest possible IPv6 length.
+    assert_eq!(SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0).to_string(), "[::]:0");
+
+    // Longest possible IPv6 length.
+    assert_eq!(
+        SocketAddrV6::new(
+            Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888),
+            u16::MAX,
+            u32::MAX,
+            u32::MAX,
+        )
+        .to_string(),
+        "[1111:2222:3333:4444:5555:6666:7777:8888%4294967295]:65535"
+    );
+
+    // Test padding.
+    assert_eq!(
+        &format!("{:22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
+        "[1:2:3:4:5:6:7:8]:9   "
+    );
+    assert_eq!(
+        &format!("{:>22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
+        "   [1:2:3:4:5:6:7:8]:9"
+    );
+}
+
+#[test]
 fn bind_udp_socket_bad() {
     // rust-lang/rust#53957: This is a regression test for a parsing problem
     // discovered as part of issue rust-lang/rust#23076, where we were
diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs
index bb313c7597b..094085e1942 100644
--- a/library/std/src/os/unix/net/addr.rs
+++ b/library/std/src/os/unix/net/addr.rs
@@ -2,7 +2,7 @@ use crate::ffi::OsStr;
 use crate::os::unix::ffi::OsStrExt;
 use crate::path::Path;
 use crate::sys::cvt;
-use crate::{ascii, fmt, io, mem, ptr};
+use crate::{fmt, io, mem, ptr};
 
 // FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here?
 #[cfg(not(unix))]
@@ -64,18 +64,6 @@ enum AddressKind<'a> {
     Abstract(&'a [u8]),
 }
 
-struct AsciiEscaped<'a>(&'a [u8]);
-
-impl<'a> fmt::Display for AsciiEscaped<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(fmt, "\"")?;
-        for byte in self.0.iter().cloned().flat_map(ascii::escape_default) {
-            write!(fmt, "{}", byte as char)?;
-        }
-        write!(fmt, "\"")
-    }
-}
-
 /// An address associated with a Unix socket.
 ///
 /// # Examples
@@ -343,7 +331,7 @@ impl fmt::Debug for SocketAddr {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.address() {
             AddressKind::Unnamed => write!(fmt, "(unnamed)"),
-            AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)),
+            AddressKind::Abstract(name) => write!(fmt, "\"{}\" (abstract)", name.escape_ascii()),
             AddressKind::Pathname(path) => write!(fmt, "{path:?} (pathname)"),
         }
     }
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 45bc56efb3b..c4f022de021 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -295,23 +295,22 @@ pub fn get_backtrace_style() -> Option<BacktraceStyle> {
         return Some(style);
     }
 
-    // Setting environment variables for Fuchsia components isn't a standard
-    // or easily supported workflow. For now, display backtraces by default.
-    let format = if cfg!(target_os = "fuchsia") {
-        BacktraceStyle::Full
-    } else {
-        crate::env::var_os("RUST_BACKTRACE")
-            .map(|x| {
-                if &x == "0" {
-                    BacktraceStyle::Off
-                } else if &x == "full" {
-                    BacktraceStyle::Full
-                } else {
-                    BacktraceStyle::Short
-                }
-            })
-            .unwrap_or(BacktraceStyle::Off)
-    };
+    let format = crate::env::var_os("RUST_BACKTRACE")
+        .map(|x| {
+            if &x == "0" {
+                BacktraceStyle::Off
+            } else if &x == "full" {
+                BacktraceStyle::Full
+            } else {
+                BacktraceStyle::Short
+            }
+        })
+        .unwrap_or(if cfg!(target_os = "fuchsia") {
+            // Fuchsia components default to full backtrace.
+            BacktraceStyle::Full
+        } else {
+            BacktraceStyle::Off
+        });
     set_backtrace_style(format);
     Some(format)
 }
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 25c9201f2ed..4b07b393a2f 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -18,9 +18,9 @@ use crate::intrinsics;
 use crate::mem::{self, ManuallyDrop};
 use crate::process;
 use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::{PoisonError, RwLock};
 use crate::sys::stdio::panic_output;
 use crate::sys_common::backtrace;
-use crate::sys_common::rwlock::StaticRwLock;
 use crate::sys_common::thread_info;
 use crate::thread;
 
@@ -71,20 +71,29 @@ extern "C" fn __rust_foreign_exception() -> ! {
     rtabort!("Rust cannot catch foreign exceptions");
 }
 
-#[derive(Copy, Clone)]
 enum Hook {
     Default,
-    Custom(*mut (dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send)),
+    Custom(Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>),
 }
 
 impl Hook {
-    fn custom(f: impl Fn(&PanicInfo<'_>) + 'static + Sync + Send) -> Self {
-        Self::Custom(Box::into_raw(Box::new(f)))
+    #[inline]
+    fn into_box(self) -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
+        match self {
+            Hook::Default => Box::new(default_hook),
+            Hook::Custom(hook) => hook,
+        }
     }
 }
 
-static HOOK_LOCK: StaticRwLock = StaticRwLock::new();
-static mut HOOK: Hook = Hook::Default;
+impl Default for Hook {
+    #[inline]
+    fn default() -> Hook {
+        Hook::Default
+    }
+}
+
+static HOOK: RwLock<Hook> = RwLock::new(Hook::Default);
 
 /// Registers a custom panic hook, replacing any that was previously registered.
 ///
@@ -125,24 +134,13 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
         panic!("cannot modify the panic hook from a panicking thread");
     }
 
-    // SAFETY:
-    //
-    // - `HOOK` can only be modified while holding write access to `HOOK_LOCK`.
-    // - The argument of `Box::from_raw` is always a valid pointer that was created using
-    // `Box::into_raw`.
-    unsafe {
-        let guard = HOOK_LOCK.write();
-        let old_hook = HOOK;
-        HOOK = Hook::Custom(Box::into_raw(hook));
-        drop(guard);
-
-        if let Hook::Custom(ptr) = old_hook {
-            #[allow(unused_must_use)]
-            {
-                Box::from_raw(ptr);
-            }
-        }
-    }
+    let new = Hook::Custom(hook);
+    let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner);
+    let old = mem::replace(&mut *hook, new);
+    drop(hook);
+    // Only drop the old hook after releasing the lock to avoid deadlocking
+    // if its destructor panics.
+    drop(old);
 }
 
 /// Unregisters the current panic hook, returning it.
@@ -179,22 +177,11 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
         panic!("cannot modify the panic hook from a panicking thread");
     }
 
-    // SAFETY:
-    //
-    // - `HOOK` can only be modified while holding write access to `HOOK_LOCK`.
-    // - The argument of `Box::from_raw` is always a valid pointer that was created using
-    // `Box::into_raw`.
-    unsafe {
-        let guard = HOOK_LOCK.write();
-        let hook = HOOK;
-        HOOK = Hook::Default;
-        drop(guard);
+    let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner);
+    let old_hook = mem::take(&mut *hook);
+    drop(hook);
 
-        match hook {
-            Hook::Default => Box::new(default_hook),
-            Hook::Custom(ptr) => Box::from_raw(ptr),
-        }
-    }
+    old_hook.into_box()
 }
 
 /// Atomic combination of [`take_hook`] and [`set_hook`]. Use this to replace the panic handler with
@@ -240,24 +227,9 @@ where
         panic!("cannot modify the panic hook from a panicking thread");
     }
 
-    // SAFETY:
-    //
-    // - `HOOK` can only be modified while holding write access to `HOOK_LOCK`.
-    // - The argument of `Box::from_raw` is always a valid pointer that was created using
-    // `Box::into_raw`.
-    unsafe {
-        let guard = HOOK_LOCK.write();
-        let old_hook = HOOK;
-        HOOK = Hook::Default;
-
-        let prev = match old_hook {
-            Hook::Default => Box::new(default_hook),
-            Hook::Custom(ptr) => Box::from_raw(ptr),
-        };
-
-        HOOK = Hook::custom(move |info| hook_fn(&prev, info));
-        drop(guard);
-    }
+    let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner);
+    let prev = mem::take(&mut *hook).into_box();
+    *hook = Hook::Custom(Box::new(move |info| hook_fn(&prev, info)));
 }
 
 fn default_hook(info: &PanicInfo<'_>) {
@@ -328,7 +300,7 @@ pub mod panic_count {
     thread_local! { static LOCAL_PANIC_COUNT: Cell<usize> = const { Cell::new(0) } }
 
     // Sum of panic counts from all threads. The purpose of this is to have
-    // a fast path in `is_zero` (which is used by `panicking`). In any particular
+    // a fast path in `count_is_zero` (which is used by `panicking`). In any particular
     // thread, if that thread currently views `GLOBAL_PANIC_COUNT` as being zero,
     // then `LOCAL_PANIC_COUNT` in that thread is zero. This invariant holds before
     // and after increase and decrease, but not necessarily during their execution.
@@ -397,7 +369,7 @@ pub mod panic_count {
     }
 
     // Slow path is in a separate function to reduce the amount of code
-    // inlined from `is_zero`.
+    // inlined from `count_is_zero`.
     #[inline(never)]
     #[cold]
     fn is_zero_slow_path() -> bool {
@@ -682,27 +654,26 @@ fn rust_panic_with_hook(
         crate::sys::abort_internal();
     }
 
-    unsafe {
-        let mut info = PanicInfo::internal_constructor(message, location, can_unwind);
-        let _guard = HOOK_LOCK.read();
-        match HOOK {
-            // Some platforms (like wasm) know that printing to stderr won't ever actually
-            // print anything, and if that's the case we can skip the default
-            // hook. Since string formatting happens lazily when calling `payload`
-            // methods, this means we avoid formatting the string at all!
-            // (The panic runtime might still call `payload.take_box()` though and trigger
-            // formatting.)
-            Hook::Default if panic_output().is_none() => {}
-            Hook::Default => {
-                info.set_payload(payload.get());
-                default_hook(&info);
-            }
-            Hook::Custom(ptr) => {
-                info.set_payload(payload.get());
-                (*ptr)(&info);
-            }
-        };
-    }
+    let mut info = PanicInfo::internal_constructor(message, location, can_unwind);
+    let hook = HOOK.read().unwrap_or_else(PoisonError::into_inner);
+    match *hook {
+        // Some platforms (like wasm) know that printing to stderr won't ever actually
+        // print anything, and if that's the case we can skip the default
+        // hook. Since string formatting happens lazily when calling `payload`
+        // methods, this means we avoid formatting the string at all!
+        // (The panic runtime might still call `payload.take_box()` though and trigger
+        // formatting.)
+        Hook::Default if panic_output().is_none() => {}
+        Hook::Default => {
+            info.set_payload(payload.get());
+            default_hook(&info);
+        }
+        Hook::Custom(ref hook) => {
+            info.set_payload(payload.get());
+            hook(&info);
+        }
+    };
+    drop(hook);
 
     if panics > 1 || !can_unwind {
         // If a thread panics while it's already unwinding then we
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 5dfeb517a19..4f9dff1ef03 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2401,7 +2401,7 @@ impl Path {
         self.file_name().map(split_file_at_dot).and_then(|(before, _after)| Some(before))
     }
 
-    /// Extracts the extension of [`self.file_name`], if possible.
+    /// Extracts the extension (without the leading dot) of [`self.file_name`], if possible.
     ///
     /// The extension is:
     ///
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 242f44ade8a..331714a993c 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -611,7 +611,19 @@ mod prim_pointer {}
 ///
 /// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
 /// an array. Indeed, this provides most of the API for working with arrays.
-/// Slices have a dynamic size and do not coerce to arrays.
+///
+/// Slices have a dynamic size and do not coerce to arrays. Instead, use
+/// `slice.try_into().unwrap()` or `<ArrayType>::try_from(slice).unwrap()`.
+///
+/// Array's `try_from(slice)` implementations (and the corresponding `slice.try_into()`
+/// array implementations) succeed if the input slice length is the same as the result
+/// array length. They optimize especially well when the optimizer can easily determine
+/// the slice length, e.g. `<[u8; 4]>::try_from(&slice[4..8]).unwrap()`. Array implements
+/// [TryFrom](crate::convert::TryFrom) returning:
+///
+/// - `[T; N]` copies from the slice's elements
+/// - `&[T; N]` references the original slice's elements
+/// - `&mut [T; N]` references the original slice's elements
 ///
 /// You can move elements out of an array with a [slice pattern]. If you want
 /// one element, see [`mem::replace`].
@@ -640,6 +652,15 @@ mod prim_pointer {}
 /// for x in &array { }
 /// ```
 ///
+/// You can use `<ArrayType>::try_from(slice)` or `slice.try_into()` to get an array from
+/// a slice:
+///
+/// ```
+/// let bytes: [u8; 3] = [1, 0, 2];
+/// assert_eq!(1, u16::from_le_bytes(<[u8; 2]>::try_from(&bytes[0..2]).unwrap()));
+/// assert_eq!(512, u16::from_le_bytes(bytes[1..3].try_into().unwrap()));
+/// ```
+///
 /// You can use a [slice pattern] to move elements out of an array:
 ///
 /// ```
diff --git a/library/std/src/sys/sgx/abi/thread.rs b/library/std/src/sys/sgx/abi/thread.rs
index ef55b821a2b..2b23e368cc3 100644
--- a/library/std/src/sys/sgx/abi/thread.rs
+++ b/library/std/src/sys/sgx/abi/thread.rs
@@ -7,7 +7,11 @@ use fortanix_sgx_abi::Tcs;
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn current() -> Tcs {
     extern "C" {
-        fn get_tcs_addr() -> Tcs;
+        fn get_tcs_addr() -> *mut u8;
+    }
+    let addr = unsafe { get_tcs_addr() };
+    match Tcs::new(addr) {
+        Some(tcs) => tcs,
+        None => rtabort!("TCS must not be placed at address zero (this is a linker error)"),
     }
-    unsafe { get_tcs_addr() }
 }
diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs
index 5409bd1777c..0d934318c22 100644
--- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs
+++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs
@@ -316,9 +316,9 @@ where
 //   | small1 | Chunk smaller than 8 bytes
 //   +--------+
 fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (usize, usize, usize) {
-    let small0_size = if ptr as usize % 8 == 0 { 0 } else { 8 - ptr as usize % 8 };
-    let small1_size = (len - small0_size as usize) % 8;
-    let big_size = len - small0_size as usize - small1_size as usize;
+    let small0_size = if ptr.is_aligned_to(8) { 0 } else { 8 - ptr.addr() % 8 };
+    let small1_size = (len - small0_size) % 8;
+    let big_size = len - small0_size - small1_size;
 
     (small0_size, big_size, small1_size)
 }
@@ -364,8 +364,8 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
                     mfence
                     lfence
                     ",
-                    val = in(reg_byte) *src.offset(off as isize),
-                    dst = in(reg) dst.offset(off as isize),
+                    val = in(reg_byte) *src.add(off),
+                    dst = in(reg) dst.add(off),
                     seg_sel = in(reg) &mut seg_sel,
                     options(nostack, att_syntax)
                 );
@@ -378,8 +378,8 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
     assert!(is_enclave_range(src, len));
     assert!(is_user_range(dst, len));
     assert!(len < isize::MAX as usize);
-    assert!(!(src as usize).overflowing_add(len).1);
-    assert!(!(dst as usize).overflowing_add(len).1);
+    assert!(!src.addr().overflowing_add(len).1);
+    assert!(!dst.addr().overflowing_add(len).1);
 
     if len < 8 {
         // Can't align on 8 byte boundary: copy safely byte per byte
@@ -404,17 +404,17 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
 
         unsafe {
             // Copy small0
-            copy_bytewise_to_userspace(src, dst, small0_size as _);
+            copy_bytewise_to_userspace(src, dst, small0_size);
 
             // Copy big
-            let big_src = src.offset(small0_size as _);
-            let big_dst = dst.offset(small0_size as _);
-            copy_quadwords(big_src as _, big_dst, big_size);
+            let big_src = src.add(small0_size);
+            let big_dst = dst.add(small0_size);
+            copy_quadwords(big_src, big_dst, big_size);
 
             // Copy small1
-            let small1_src = src.offset(big_size as isize + small0_size as isize);
-            let small1_dst = dst.offset(big_size as isize + small0_size as isize);
-            copy_bytewise_to_userspace(small1_src, small1_dst, small1_size as _);
+            let small1_src = src.add(big_size + small0_size);
+            let small1_dst = dst.add(big_size + small0_size);
+            copy_bytewise_to_userspace(small1_src, small1_dst, small1_size);
         }
     }
 }
diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs
index b5649d6e0ff..eecb347e599 100644
--- a/library/std/src/sys/solid/os.rs
+++ b/library/std/src/sys/solid/os.rs
@@ -8,7 +8,7 @@ use crate::os::{
     solid::ffi::{OsStrExt, OsStringExt},
 };
 use crate::path::{self, PathBuf};
-use crate::sys_common::rwlock::StaticRwLock;
+use crate::sync::RwLock;
 use crate::vec;
 
 use super::{error, itron, memchr};
@@ -78,7 +78,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
-static ENV_LOCK: StaticRwLock = StaticRwLock::new();
+static ENV_LOCK: RwLock<()> = RwLock::new(());
 
 pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
diff --git a/library/std/src/sys/unix/locks/mod.rs b/library/std/src/sys/unix/locks/mod.rs
index f5f92f69358..9bb314b7010 100644
--- a/library/std/src/sys/unix/locks/mod.rs
+++ b/library/std/src/sys/unix/locks/mod.rs
@@ -11,21 +11,21 @@ cfg_if::cfg_if! {
         mod futex_rwlock;
         mod futex_condvar;
         pub(crate) use futex_mutex::{Mutex, MovableMutex};
-        pub(crate) use futex_rwlock::{RwLock, MovableRwLock};
+        pub(crate) use futex_rwlock::MovableRwLock;
         pub(crate) use futex_condvar::MovableCondvar;
     } else if #[cfg(target_os = "fuchsia")] {
         mod fuchsia_mutex;
         mod futex_rwlock;
         mod futex_condvar;
         pub(crate) use fuchsia_mutex::{Mutex, MovableMutex};
-        pub(crate) use futex_rwlock::{RwLock, MovableRwLock};
+        pub(crate) use futex_rwlock::MovableRwLock;
         pub(crate) use futex_condvar::MovableCondvar;
     } else {
         mod pthread_mutex;
         mod pthread_rwlock;
         mod pthread_condvar;
         pub(crate) use pthread_mutex::{Mutex, MovableMutex};
-        pub(crate) use pthread_rwlock::{RwLock, MovableRwLock};
+        pub(crate) use pthread_rwlock::MovableRwLock;
         pub(crate) use pthread_condvar::MovableCondvar;
     }
 }
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 46545a0839f..3c3770708b1 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -17,10 +17,10 @@ use crate::path::{self, PathBuf};
 use crate::ptr;
 use crate::slice;
 use crate::str;
+use crate::sync::{PoisonError, RwLock};
 use crate::sys::cvt;
 use crate::sys::fd;
 use crate::sys::memchr;
-use crate::sys_common::rwlock::{StaticRwLock, StaticRwLockReadGuard};
 use crate::vec;
 
 #[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
@@ -501,10 +501,10 @@ pub unsafe fn environ() -> *mut *const *const c_char {
     ptr::addr_of_mut!(environ)
 }
 
-static ENV_LOCK: StaticRwLock = StaticRwLock::new();
+static ENV_LOCK: RwLock<()> = RwLock::new(());
 
-pub fn env_read_lock() -> StaticRwLockReadGuard {
-    ENV_LOCK.read()
+pub fn env_read_lock() -> impl Drop {
+    ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
 }
 
 /// Returns a vector of (variable, value) byte-vector pairs for all the
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 26ae6281771..2ff8e600f7c 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -822,14 +822,14 @@ impl crate::os::linux::process::ChildExt for crate::process::Child {
         self.handle
             .pidfd
             .as_ref()
-            .ok_or_else(|| Error::new(ErrorKind::Other, "No pidfd was created."))
+            .ok_or_else(|| Error::new(ErrorKind::Uncategorized, "No pidfd was created."))
     }
 
     fn take_pidfd(&mut self) -> io::Result<PidFd> {
         self.handle
             .pidfd
             .take()
-            .ok_or_else(|| Error::new(ErrorKind::Other, "No pidfd was created."))
+            .ok_or_else(|| Error::new(ErrorKind::Uncategorized, "No pidfd was created."))
     }
 }
 
diff --git a/library/std/src/sys/unsupported/locks/mod.rs b/library/std/src/sys/unsupported/locks/mod.rs
index d412ff152a0..602a2d6231a 100644
--- a/library/std/src/sys/unsupported/locks/mod.rs
+++ b/library/std/src/sys/unsupported/locks/mod.rs
@@ -3,4 +3,4 @@ mod mutex;
 mod rwlock;
 pub use condvar::{Condvar, MovableCondvar};
 pub use mutex::{MovableMutex, Mutex};
-pub use rwlock::{MovableRwLock, RwLock};
+pub use rwlock::MovableRwLock;
diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs
index 4159efe2a05..93838390bee 100644
--- a/library/std/src/sys/wasm/mod.rs
+++ b/library/std/src/sys/wasm/mod.rs
@@ -57,7 +57,7 @@ cfg_if::cfg_if! {
             mod futex_rwlock;
             pub(crate) use futex_condvar::{Condvar, MovableCondvar};
             pub(crate) use futex_mutex::{Mutex, MovableMutex};
-            pub(crate) use futex_rwlock::{RwLock, MovableRwLock};
+            pub(crate) use futex_rwlock::MovableRwLock;
         }
         #[path = "atomics/futex.rs"]
         pub mod futex;
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index 89d0ab59be8..c61a7e7d1e4 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -279,7 +279,6 @@ pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _;
 pub const STATUS_PENDING: NTSTATUS = 0x103 as _;
 pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _;
 pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002_u32 as _;
-pub const STATUS_NOT_SUPPORTED: NTSTATUS = 0xC00000BB_u32 as _;
 
 // Equivalent to the `NT_SUCCESS` C preprocessor macro.
 // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values
@@ -289,6 +288,7 @@ pub fn nt_success(status: NTSTATUS) -> bool {
 
 // "RNG\0"
 pub const BCRYPT_RNG_ALGORITHM: &[u16] = &[b'R' as u16, b'N' as u16, b'G' as u16, 0];
+pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
 
 #[repr(C)]
 pub struct UNICODE_STRING {
@@ -817,10 +817,6 @@ if #[cfg(not(target_vendor = "uwp"))] {
 
     #[link(name = "advapi32")]
     extern "system" {
-        // Forbidden when targeting UWP
-        #[link_name = "SystemFunction036"]
-        pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
-
         // Allowed but unused by UWP
         pub fn OpenProcessToken(
             ProcessHandle: HANDLE,
diff --git a/library/std/src/sys/windows/locks/mod.rs b/library/std/src/sys/windows/locks/mod.rs
index d412ff152a0..602a2d6231a 100644
--- a/library/std/src/sys/windows/locks/mod.rs
+++ b/library/std/src/sys/windows/locks/mod.rs
@@ -3,4 +3,4 @@ mod mutex;
 mod rwlock;
 pub use condvar::{Condvar, MovableCondvar};
 pub use mutex::{MovableMutex, Mutex};
-pub use rwlock::{MovableRwLock, RwLock};
+pub use rwlock::MovableRwLock;
diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs
index d6cd8f80271..b5a49489d3f 100644
--- a/library/std/src/sys/windows/rand.rs
+++ b/library/std/src/sys/windows/rand.rs
@@ -13,15 +13,12 @@
 //! but significant number of users to experience panics caused by a failure of
 //! this function. See [#94098].
 //!
-//! The current version changes this to use the `BCRYPT_RNG_ALG_HANDLE`
-//! [Pseudo-handle], which gets the default RNG algorithm without querying the
-//! system preference thus hopefully avoiding the previous issue.
-//! This is only supported on Windows 10+ so a fallback is used for older versions.
+//! The current version falls back to using `BCryptOpenAlgorithmProvider` if
+//! `BCRYPT_USE_SYSTEM_PREFERRED_RNG` fails for any reason.
 //!
 //! [#94098]: https://github.com/rust-lang/rust/issues/94098
 //! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
 //! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
-//! [Pseudo-handle]: https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-pseudo-handles
 use crate::mem;
 use crate::ptr;
 use crate::sys::c;
@@ -33,37 +30,35 @@ use crate::sys::c;
 /// [`HashMap`]: crate::collections::HashMap
 /// [`RandomState`]: crate::collections::hash_map::RandomState
 pub fn hashmap_random_keys() -> (u64, u64) {
-    Rng::open().and_then(|rng| rng.gen_random_keys()).unwrap_or_else(fallback_rng)
+    Rng::SYSTEM.gen_random_keys().unwrap_or_else(fallback_rng)
 }
 
-struct Rng(c::BCRYPT_ALG_HANDLE);
+struct Rng {
+    algorithm: c::BCRYPT_ALG_HANDLE,
+    flags: u32,
+}
 impl Rng {
-    #[cfg(miri)]
-    fn open() -> Result<Self, c::NTSTATUS> {
-        const BCRYPT_RNG_ALG_HANDLE: c::BCRYPT_ALG_HANDLE = ptr::invalid_mut(0x81);
-        let _ = (
-            c::BCryptOpenAlgorithmProvider,
-            c::BCryptCloseAlgorithmProvider,
-            c::BCRYPT_RNG_ALGORITHM,
-            c::STATUS_NOT_SUPPORTED,
-        );
-        Ok(Self(BCRYPT_RNG_ALG_HANDLE))
+    const SYSTEM: Self = unsafe { Self::new(ptr::null_mut(), c::BCRYPT_USE_SYSTEM_PREFERRED_RNG) };
+
+    /// Create the RNG from an existing algorithm handle.
+    ///
+    /// # Safety
+    ///
+    /// The handle must either be null or a valid algorithm handle.
+    const unsafe fn new(algorithm: c::BCRYPT_ALG_HANDLE, flags: u32) -> Self {
+        Self { algorithm, flags }
     }
-    #[cfg(not(miri))]
-    // Open a handle to the RNG algorithm.
+
+    /// Open a handle to the RNG algorithm.
     fn open() -> Result<Self, c::NTSTATUS> {
         use crate::sync::atomic::AtomicPtr;
         use crate::sync::atomic::Ordering::{Acquire, Release};
-        const ERROR_VALUE: c::LPVOID = ptr::invalid_mut(usize::MAX);
 
         // An atomic is used so we don't need to reopen the handle every time.
         static HANDLE: AtomicPtr<crate::ffi::c_void> = AtomicPtr::new(ptr::null_mut());
 
         let mut handle = HANDLE.load(Acquire);
-        // We use a sentinel value to designate an error occurred last time.
-        if handle == ERROR_VALUE {
-            Err(c::STATUS_NOT_SUPPORTED)
-        } else if handle.is_null() {
+        if handle.is_null() {
             let status = unsafe {
                 c::BCryptOpenAlgorithmProvider(
                     &mut handle,
@@ -80,13 +75,12 @@ impl Rng {
                     unsafe { c::BCryptCloseAlgorithmProvider(handle, 0) };
                     handle = previous_handle;
                 }
-                Ok(Self(handle))
+                Ok(unsafe { Self::new(handle, 0) })
             } else {
-                HANDLE.store(ERROR_VALUE, Release);
                 Err(status)
             }
         } else {
-            Ok(Self(handle))
+            Ok(unsafe { Self::new(handle, 0) })
         }
     }
 
@@ -94,33 +88,19 @@ impl Rng {
         let mut v = (0, 0);
         let status = unsafe {
             let size = mem::size_of_val(&v).try_into().unwrap();
-            c::BCryptGenRandom(self.0, ptr::addr_of_mut!(v).cast(), size, 0)
+            c::BCryptGenRandom(self.algorithm, ptr::addr_of_mut!(v).cast(), size, self.flags)
         };
         if c::nt_success(status) { Ok(v) } else { Err(status) }
     }
 }
 
-/// Generate random numbers using the fallback RNG function (RtlGenRandom)
-#[cfg(not(target_vendor = "uwp"))]
+/// Generate random numbers using the fallback RNG function
 #[inline(never)]
 fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) {
-    let mut v = (0, 0);
-    let ret =
-        unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) };
-
-    if ret != 0 {
-        v
-    } else {
-        panic!(
-            "RNG broken: {rng_status:#x}, fallback RNG broken: {}",
-            crate::io::Error::last_os_error()
-        )
+    match Rng::open().and_then(|rng| rng.gen_random_keys()) {
+        Ok(keys) => keys,
+        Err(status) => {
+            panic!("RNG broken: {rng_status:#x}, fallback RNG broken: {status:#x}")
+        }
     }
 }
-
-/// We can't use RtlGenRandom with UWP, so there is no fallback
-#[cfg(target_vendor = "uwp")]
-#[inline(never)]
-fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) {
-    panic!("RNG broken: {rng_status:#x} fallback RNG broken: RtlGenRandom() not supported on UWP");
-}
diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs
index ba56f3a8f1b..36d721fcbcb 100644
--- a/library/std/src/sys_common/rwlock.rs
+++ b/library/std/src/sys_common/rwlock.rs
@@ -1,65 +1,5 @@
 use crate::sys::locks as imp;
 
-/// An OS-based reader-writer lock, meant for use in static variables.
-///
-/// This rwlock does not implement poisoning.
-///
-/// This rwlock has a const constructor ([`StaticRwLock::new`]), does not
-/// implement `Drop` to cleanup resources.
-pub struct StaticRwLock(imp::RwLock);
-
-impl StaticRwLock {
-    /// Creates a new rwlock for use.
-    #[inline]
-    pub const fn new() -> Self {
-        Self(imp::RwLock::new())
-    }
-
-    /// Acquires shared access to the underlying lock, blocking the current
-    /// thread to do so.
-    ///
-    /// The lock is automatically unlocked when the returned guard is dropped.
-    #[inline]
-    pub fn read(&'static self) -> StaticRwLockReadGuard {
-        unsafe { self.0.read() };
-        StaticRwLockReadGuard(&self.0)
-    }
-
-    /// Acquires write access to the underlying lock, blocking the current thread
-    /// to do so.
-    ///
-    /// The lock is automatically unlocked when the returned guard is dropped.
-    #[inline]
-    pub fn write(&'static self) -> StaticRwLockWriteGuard {
-        unsafe { self.0.write() };
-        StaticRwLockWriteGuard(&self.0)
-    }
-}
-
-#[must_use]
-pub struct StaticRwLockReadGuard(&'static imp::RwLock);
-
-impl Drop for StaticRwLockReadGuard {
-    #[inline]
-    fn drop(&mut self) {
-        unsafe {
-            self.0.read_unlock();
-        }
-    }
-}
-
-#[must_use]
-pub struct StaticRwLockWriteGuard(&'static imp::RwLock);
-
-impl Drop for StaticRwLockWriteGuard {
-    #[inline]
-    fn drop(&mut self) {
-        unsafe {
-            self.0.write_unlock();
-        }
-    }
-}
-
 /// An OS-based reader-writer lock.
 ///
 /// This rwlock cleans up its resources in its `Drop` implementation and may