about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorJakub Beránek <berykubik@gmail.com>2025-01-20 15:54:51 +0100
committerGitHub <noreply@github.com>2025-01-20 15:54:51 +0100
commit470ab13c5c28a42e706ee8cee92e44257065324f (patch)
treeea612d81208c7fa15d3477ca173d9fe6a18ccc83 /library/std/src
parent1b5b0515f9c12ea8181deec0d9997fe9af6ab417 (diff)
parent1e0204beae7c0ebc5cddc64d1375bc7ee95f41db (diff)
Merge pull request #2215 from Kobzol/pull
rustc pull
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/collections/hash/map.rs5
-rw-r--r--library/std/src/collections/hash/set.rs5
-rw-r--r--library/std/src/env.rs2
-rw-r--r--library/std/src/ffi/os_str/tests.rs2
-rw-r--r--library/std/src/io/buffered/bufreader/buffer.rs2
-rw-r--r--library/std/src/io/error.rs4
-rw-r--r--library/std/src/io/error/repr_bitpacked.rs7
-rw-r--r--library/std/src/io/mod.rs249
-rw-r--r--library/std/src/io/tests.rs17
-rw-r--r--library/std/src/lib.rs5
-rw-r--r--library/std/src/os/fd/owned.rs34
-rw-r--r--library/std/src/os/fd/raw.rs5
-rw-r--r--library/std/src/os/solid/io.rs27
-rw-r--r--library/std/src/os/wasi/io/fd.rs9
-rw-r--r--library/std/src/os/wasi/io/mod.rs4
-rw-r--r--library/std/src/os/wasi/io/raw.rs20
-rw-r--r--library/std/src/os/wasi/io/tests.rs (renamed from library/std/src/os/wasi/io/fd/tests.rs)0
-rw-r--r--library/std/src/os/windows/io/socket.rs39
-rw-r--r--library/std/src/panicking.rs39
-rw-r--r--library/std/src/path.rs15
-rw-r--r--library/std/src/path/tests.rs4
-rw-r--r--library/std/src/pipe.rs258
-rw-r--r--library/std/src/pipe/tests.rs19
-rw-r--r--library/std/src/prelude/common.rs3
-rw-r--r--library/std/src/prelude/mod.rs4
-rw-r--r--library/std/src/rt.rs75
-rw-r--r--library/std/src/sync/lazy_lock.rs2
-rw-r--r--library/std/src/sys/anonymous_pipe/unix.rs3
-rw-r--r--library/std/src/sys/anonymous_pipe/unsupported.rs3
-rw-r--r--library/std/src/sys/anonymous_pipe/windows.rs4
-rw-r--r--library/std/src/sys/pal/solid/fs.rs14
-rw-r--r--library/std/src/sys/pal/uefi/fs.rs344
-rw-r--r--library/std/src/sys/pal/uefi/helpers.rs21
-rw-r--r--library/std/src/sys/pal/uefi/mod.rs1
-rw-r--r--library/std/src/sys/pal/uefi/process.rs2
-rw-r--r--library/std/src/sys/pal/unix/fs.rs36
-rw-r--r--library/std/src/sys/pal/unix/kernel_copy.rs5
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow.rs9
-rw-r--r--library/std/src/sys/pal/unix/thread.rs24
-rw-r--r--library/std/src/sys/pal/unix/time.rs33
-rw-r--r--library/std/src/sys/pal/windows/mod.rs2
-rw-r--r--library/std/src/sys/pal/windows/stack_overflow.rs8
-rw-r--r--library/std/src/sys/pal/windows/stdio.rs6
-rw-r--r--library/std/src/sys/path/sgx.rs4
-rw-r--r--library/std/src/sys/path/unix.rs11
-rw-r--r--library/std/src/sys/path/unsupported_backslash.rs4
-rw-r--r--library/std/src/sys/path/windows.rs4
-rw-r--r--library/std/src/thread/current.rs39
-rw-r--r--library/std/src/thread/mod.rs276
49 files changed, 1007 insertions, 701 deletions
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 56d734ba2fb..d2342d8fd51 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -296,10 +296,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// ```
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
-    #[rustc_const_stable(
-        feature = "const_collections_with_hasher",
-        since = "CURRENT_RUSTC_VERSION"
-    )]
+    #[rustc_const_stable(feature = "const_collections_with_hasher", since = "1.85.0")]
     pub const fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
         HashMap { base: base::HashMap::with_hasher(hash_builder) }
     }
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index bcf6d6b4ccf..bbb6ca23521 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -388,10 +388,7 @@ impl<T, S> HashSet<T, S> {
     /// ```
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
-    #[rustc_const_stable(
-        feature = "const_collections_with_hasher",
-        since = "CURRENT_RUSTC_VERSION"
-    )]
+    #[rustc_const_stable(feature = "const_collections_with_hasher", since = "1.85.0")]
     pub const fn with_hasher(hasher: S) -> HashSet<T, S> {
         HashSet { base: base::HashSet::with_hasher(hasher) }
     }
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 535236ff89a..11a29cdae62 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -622,7 +622,7 @@ impl Error for JoinPathsError {
 ///
 /// In UWP (Universal Windows Platform) targets this function is unimplemented and always returns `None`.
 ///
-/// Before Rust CURRENT_RUSTC_VERSION, this function used to return the value of the 'HOME' environment variable
+/// Before Rust 1.85.0, this function used to return the value of the 'HOME' environment variable
 /// on Windows, which in Cygwin or Mingw environments could return non-standard paths like `/home/you`
 /// instead of `C:\Users\you`.
 ///
diff --git a/library/std/src/ffi/os_str/tests.rs b/library/std/src/ffi/os_str/tests.rs
index cbec44c8626..2572b71fd9a 100644
--- a/library/std/src/ffi/os_str/tests.rs
+++ b/library/std/src/ffi/os_str/tests.rs
@@ -295,7 +295,7 @@ fn clone_to_uninit() {
 
     let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<OsStr>(a)];
     unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) };
-    assert_eq!(a.as_encoded_bytes(), unsafe { MaybeUninit::slice_assume_init_ref(&storage) });
+    assert_eq!(a.as_encoded_bytes(), unsafe { storage.assume_init_ref() });
 
     let mut b: Box<OsStr> = OsStr::new("world.exe").into();
     assert_eq!(size_of_val::<OsStr>(a), size_of_val::<OsStr>(&b));
diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs
index 17721090db5..5251cc302cb 100644
--- a/library/std/src/io/buffered/bufreader/buffer.rs
+++ b/library/std/src/io/buffered/bufreader/buffer.rs
@@ -50,7 +50,7 @@ impl Buffer {
     pub fn buffer(&self) -> &[u8] {
         // SAFETY: self.pos and self.cap are valid, and self.cap => self.pos, and
         // that region is initialized because those are all invariants of this type.
-        unsafe { MaybeUninit::slice_assume_init_ref(self.buf.get_unchecked(self.pos..self.filled)) }
+        unsafe { self.buf.get_unchecked(self.pos..self.filled).assume_init_ref() }
     }
 
     #[inline]
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 476c403c21f..38b72336617 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -339,7 +339,7 @@ pub enum ErrorKind {
     #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
     NotSeekable,
     /// Filesystem quota or some other kind of quota was exceeded.
-    #[stable(feature = "io_error_quota_exceeded", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "io_error_quota_exceeded", since = "1.85.0")]
     QuotaExceeded,
     /// File larger than allowed or supported.
     ///
@@ -364,7 +364,7 @@ pub enum ErrorKind {
     #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
     Deadlock,
     /// Cross-device or cross-filesystem (hard) link or rename.
-    #[stable(feature = "io_error_crosses_devices", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "io_error_crosses_devices", since = "1.85.0")]
     CrossesDevices,
     /// Too many (hard) links to the same filesystem object.
     ///
diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs
index f958a938646..716da37168d 100644
--- a/library/std/src/io/error/repr_bitpacked.rs
+++ b/library/std/src/io/error/repr_bitpacked.rs
@@ -103,7 +103,8 @@
 //! the time.
 
 use core::marker::PhantomData;
-use core::ptr::{self, NonNull};
+use core::num::NonZeroUsize;
+use core::ptr::NonNull;
 
 use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
 
@@ -176,7 +177,7 @@ impl Repr {
         let utagged = ((code as usize) << 32) | TAG_OS;
         // Safety: `TAG_OS` is not zero, so the result of the `|` is not 0.
         let res = Self(
-            unsafe { NonNull::new_unchecked(ptr::without_provenance_mut(utagged)) },
+            NonNull::without_provenance(unsafe { NonZeroUsize::new_unchecked(utagged) }),
             PhantomData,
         );
         // quickly smoke-check we encoded the right thing (This generally will
@@ -193,7 +194,7 @@ impl Repr {
         let utagged = ((kind as usize) << 32) | TAG_SIMPLE;
         // Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0.
         let res = Self(
-            unsafe { NonNull::new_unchecked(ptr::without_provenance_mut(utagged)) },
+            NonNull::without_provenance(unsafe { NonZeroUsize::new_unchecked(utagged) }),
             PhantomData,
         );
         // quickly smoke-check we encoded the right thing (This generally will
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 7912f969bbd..231c8712ebd 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -330,6 +330,7 @@ pub use self::{
 };
 use crate::mem::take;
 use crate::ops::{Deref, DerefMut};
+use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
 use crate::{cmp, fmt, slice, str, sys};
 
 mod buffered;
@@ -3250,3 +3251,251 @@ impl<B: BufRead> Iterator for Lines<B> {
         }
     }
 }
+
+/// Create anonymous pipe that is close-on-exec and blocking.
+///
+/// # Behavior
+///
+/// A pipe is a synchronous, unidirectional data channel between two or more processes, like an
+/// interprocess [`mpsc`](crate::sync::mpsc) provided by the OS. In particular:
+///
+/// * A read on a [`PipeReader`] blocks until the pipe is non-empty.
+/// * A write on a [`PipeWriter`] blocks when the pipe is full.
+/// * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`]
+///   returns EOF.
+/// * [`PipeReader`] can be shared, but only one process will consume the data in the pipe.
+///
+/// # Capacity
+///
+/// Pipe capacity is platform dependent. To quote the Linux [man page]:
+///
+/// > Different implementations have different limits for the pipe capacity. Applications should
+/// > not rely on a particular capacity: an application should be designed so that a reading process
+/// > consumes data as soon as it is available, so that a writing process does not remain blocked.
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(anonymous_pipe)]
+/// # #[cfg(miri)] fn main() {}
+/// # #[cfg(not(miri))]
+/// # fn main() -> std::io::Result<()> {
+/// # use std::process::Command;
+/// # use std::io::{Read, Write};
+/// let (ping_rx, mut ping_tx) = std::io::pipe()?;
+/// let (mut pong_rx, pong_tx) = std::io::pipe()?;
+///
+/// // Spawn a process that echoes its input.
+/// let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
+///
+/// ping_tx.write_all(b"hello")?;
+/// // Close to unblock echo_server's reader.
+/// drop(ping_tx);
+///
+/// let mut buf = String::new();
+/// // Block until echo_server's writer is closed.
+/// pong_rx.read_to_string(&mut buf)?;
+/// assert_eq!(&buf, "hello");
+///
+/// echo_server.wait()?;
+/// # Ok(())
+/// # }
+/// ```
+/// [pipe]: https://man7.org/linux/man-pages/man2/pipe.2.html
+/// [CreatePipe]: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe
+/// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+#[inline]
+pub fn pipe() -> Result<(PipeReader, PipeWriter)> {
+    pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer)))
+}
+
+/// Read end of the anonymous pipe.
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+#[derive(Debug)]
+pub struct PipeReader(pub(crate) AnonPipe);
+
+/// Write end of the anonymous pipe.
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+#[derive(Debug)]
+pub struct PipeWriter(pub(crate) AnonPipe);
+
+impl PipeReader {
+    /// Create a new [`PipeReader`] instance that shares the same underlying file description.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(anonymous_pipe)]
+    /// # #[cfg(miri)] fn main() {}
+    /// # #[cfg(not(miri))]
+    /// # fn main() -> std::io::Result<()> {
+    /// # use std::fs;
+    /// # use std::io::Write;
+    /// # use std::process::Command;
+    /// const NUM_SLOT: u8 = 2;
+    /// const NUM_PROC: u8 = 5;
+    /// const OUTPUT: &str = "work.txt";
+    ///
+    /// let mut jobs = vec![];
+    /// let (reader, mut writer) = std::io::pipe()?;
+    ///
+    /// // Write NUM_SLOT characters the pipe.
+    /// writer.write_all(&[b'|'; NUM_SLOT as usize])?;
+    ///
+    /// // Spawn several processes that read a character from the pipe, do some work, then
+    /// // write back to the pipe. When the pipe is empty, the processes block, so only
+    /// // NUM_SLOT processes can be working at any given time.
+    /// for _ in 0..NUM_PROC {
+    ///     jobs.push(
+    ///         Command::new("bash")
+    ///             .args(["-c",
+    ///                 &format!(
+    ///                      "read -n 1\n\
+    ///                       echo -n 'x' >> '{OUTPUT}'\n\
+    ///                       echo -n '|'",
+    ///                 ),
+    ///             ])
+    ///             .stdin(reader.try_clone()?)
+    ///             .stdout(writer.try_clone()?)
+    ///             .spawn()?,
+    ///     );
+    /// }
+    ///
+    /// // Wait for all jobs to finish.
+    /// for mut job in jobs {
+    ///     job.wait()?;
+    /// }
+    ///
+    /// // Check our work and clean up.
+    /// let xs = fs::read_to_string(OUTPUT)?;
+    /// fs::remove_file(OUTPUT)?;
+    /// assert_eq!(xs, "x".repeat(NUM_PROC.into()));
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[unstable(feature = "anonymous_pipe", issue = "127154")]
+    pub fn try_clone(&self) -> Result<Self> {
+        self.0.try_clone().map(Self)
+    }
+}
+
+impl PipeWriter {
+    /// Create a new [`PipeWriter`] instance that shares the same underlying file description.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(anonymous_pipe)]
+    /// # #[cfg(miri)] fn main() {}
+    /// # #[cfg(not(miri))]
+    /// # fn main() -> std::io::Result<()> {
+    /// # use std::process::Command;
+    /// # use std::io::Read;
+    /// let (mut reader, writer) = std::io::pipe()?;
+    ///
+    /// // Spawn a process that writes to stdout and stderr.
+    /// let mut peer = Command::new("bash")
+    ///     .args([
+    ///         "-c",
+    ///         "echo -n foo\n\
+    ///          echo -n bar >&2"
+    ///     ])
+    ///     .stdout(writer.try_clone()?)
+    ///     .stderr(writer)
+    ///     .spawn()?;
+    ///
+    /// // Read and check the result.
+    /// let mut msg = String::new();
+    /// reader.read_to_string(&mut msg)?;
+    /// assert_eq!(&msg, "foobar");
+    ///
+    /// peer.wait()?;
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[unstable(feature = "anonymous_pipe", issue = "127154")]
+    pub fn try_clone(&self) -> Result<Self> {
+        self.0.try_clone().map(Self)
+    }
+}
+
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+impl Read for &PipeReader {
+    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
+        self.0.read(buf)
+    }
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+    #[inline]
+    fn is_read_vectored(&self) -> bool {
+        self.0.is_read_vectored()
+    }
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
+        self.0.read_to_end(buf)
+    }
+    fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> {
+        self.0.read_buf(buf)
+    }
+}
+
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+impl Read for PipeReader {
+    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
+        self.0.read(buf)
+    }
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+    #[inline]
+    fn is_read_vectored(&self) -> bool {
+        self.0.is_read_vectored()
+    }
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
+        self.0.read_to_end(buf)
+    }
+    fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> {
+        self.0.read_buf(buf)
+    }
+}
+
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+impl Write for &PipeWriter {
+    fn write(&mut self, buf: &[u8]) -> Result<usize> {
+        self.0.write(buf)
+    }
+    #[inline]
+    fn flush(&mut self) -> Result<()> {
+        Ok(())
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        self.0.is_write_vectored()
+    }
+}
+
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+impl Write for PipeWriter {
+    fn write(&mut self, buf: &[u8]) -> Result<usize> {
+        self.0.write(buf)
+    }
+    #[inline]
+    fn flush(&mut self) -> Result<()> {
+        Ok(())
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        self.0.is_write_vectored()
+    }
+}
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index 47cbb9614af..85098b3bb18 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -823,3 +823,20 @@ fn try_oom_error() {
     let io_err = io::Error::from(reserve_err);
     assert_eq!(io::ErrorKind::OutOfMemory, io_err.kind());
 }
+
+#[test]
+#[cfg(all(windows, unix, not(miri)))]
+fn pipe_creation_clone_and_rw() {
+    let (rx, tx) = std::io::pipe().unwrap();
+
+    tx.try_clone().unwrap().write_all(b"12345").unwrap();
+    drop(tx);
+
+    let mut rx2 = rx.try_clone().unwrap();
+    drop(rx);
+
+    let mut s = String::new();
+    rx2.read_to_string(&mut s).unwrap();
+    drop(rx2);
+    assert_eq!(s, "12345");
+}
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 2f8f5c5c581..39f234e4ba6 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -333,7 +333,6 @@
 #![feature(extend_one)]
 #![feature(float_gamma)]
 #![feature(float_minimum_maximum)]
-#![feature(float_next_up_down)]
 #![feature(fmt_internals)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
@@ -342,6 +341,7 @@
 #![feature(lazy_get)]
 #![feature(maybe_uninit_slice)]
 #![feature(maybe_uninit_write_slice)]
+#![feature(nonnull_provenance)]
 #![feature(panic_can_unwind)]
 #![feature(panic_internals)]
 #![feature(pin_coerce_unsized_trait)]
@@ -357,6 +357,7 @@
 #![feature(str_internals)]
 #![feature(strict_provenance_atomic_ptr)]
 #![feature(sync_unsafe_cell)]
+#![feature(temporary_niche_types)]
 #![feature(ub_checks)]
 #![feature(used_with_arg)]
 // tidy-alphabetical-end
@@ -594,8 +595,6 @@ pub mod panic;
 #[unstable(feature = "pattern_type_macro", issue = "123646")]
 pub mod pat;
 pub mod path;
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-pub mod pipe;
 pub mod process;
 #[unstable(feature = "random", issue = "130703")]
 pub mod random;
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index abb13b75f50..1e814eca3c1 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -11,6 +11,8 @@ use crate::sys::cvt;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::{fmt, fs, io};
 
+type ValidRawFd = core::num::niche_types::NotAllOnes<RawFd>;
+
 /// A borrowed file descriptor.
 ///
 /// This has a lifetime parameter to tie it to the lifetime of something that owns the file
@@ -32,15 +34,10 @@ use crate::{fmt, fs, io};
 /// instead, but this is not supported on all platforms.
 #[derive(Copy, Clone)]
 #[repr(transparent)]
-#[rustc_layout_scalar_valid_range_start(0)]
-// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
-// 32-bit c_int. Below is -2, in two's complement, but that only works out
-// because c_int is 32 bits.
-#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
 #[rustc_nonnull_optimization_guaranteed]
 #[stable(feature = "io_safety", since = "1.63.0")]
 pub struct BorrowedFd<'fd> {
-    fd: RawFd,
+    fd: ValidRawFd,
     _phantom: PhantomData<&'fd OwnedFd>,
 }
 
@@ -56,15 +53,10 @@ pub struct BorrowedFd<'fd> {
 ///
 /// You can use [`AsFd::as_fd`] to obtain a [`BorrowedFd`].
 #[repr(transparent)]
-#[rustc_layout_scalar_valid_range_start(0)]
-// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
-// 32-bit c_int. Below is -2, in two's complement, but that only works out
-// because c_int is 32 bits.
-#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
 #[rustc_nonnull_optimization_guaranteed]
 #[stable(feature = "io_safety", since = "1.63.0")]
 pub struct OwnedFd {
-    fd: RawFd,
+    fd: ValidRawFd,
 }
 
 impl BorrowedFd<'_> {
@@ -80,7 +72,8 @@ impl BorrowedFd<'_> {
     pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
         assert!(fd != u32::MAX as RawFd);
         // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
-        unsafe { Self { fd, _phantom: PhantomData } }
+        let fd = unsafe { ValidRawFd::new_unchecked(fd) };
+        Self { fd, _phantom: PhantomData }
     }
 }
 
@@ -130,7 +123,7 @@ impl BorrowedFd<'_> {
 impl AsRawFd for BorrowedFd<'_> {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
-        self.fd
+        self.fd.as_inner()
     }
 }
 
@@ -138,7 +131,7 @@ impl AsRawFd for BorrowedFd<'_> {
 impl AsRawFd for OwnedFd {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
-        self.fd
+        self.fd.as_inner()
     }
 }
 
@@ -146,7 +139,7 @@ impl AsRawFd for OwnedFd {
 impl IntoRawFd for OwnedFd {
     #[inline]
     fn into_raw_fd(self) -> RawFd {
-        ManuallyDrop::new(self).fd
+        ManuallyDrop::new(self).fd.as_inner()
     }
 }
 
@@ -164,7 +157,8 @@ impl FromRawFd for OwnedFd {
     unsafe fn from_raw_fd(fd: RawFd) -> Self {
         assert_ne!(fd, u32::MAX as RawFd);
         // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
-        unsafe { Self { fd } }
+        let fd = unsafe { ValidRawFd::new_unchecked(fd) };
+        Self { fd }
     }
 }
 
@@ -187,12 +181,12 @@ impl Drop for OwnedFd {
             #[cfg(not(target_os = "hermit"))]
             {
                 #[cfg(unix)]
-                crate::sys::fs::debug_assert_fd_is_open(self.fd);
+                crate::sys::fs::debug_assert_fd_is_open(self.fd.as_inner());
 
-                let _ = libc::close(self.fd);
+                let _ = libc::close(self.fd.as_inner());
             }
             #[cfg(target_os = "hermit")]
-            let _ = hermit_abi::close(self.fd);
+            let _ = hermit_abi::close(self.fd.as_inner());
         }
     }
 }
diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs
index 22f5528248a..03dff94350d 100644
--- a/library/std/src/os/fd/raw.rs
+++ b/library/std/src/os/fd/raw.rs
@@ -19,11 +19,9 @@ use crate::sys_common::{AsInner, IntoInner};
 use crate::{fs, io};
 
 /// Raw file descriptors.
-#[rustc_allowed_through_unstable_modules]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg(not(target_os = "hermit"))]
 pub type RawFd = raw::c_int;
-#[rustc_allowed_through_unstable_modules]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg(target_os = "hermit")]
 pub type RawFd = i32;
@@ -33,7 +31,6 @@ pub type RawFd = i32;
 /// This is only available on unix and WASI platforms and must be imported in
 /// order to call the method. Windows platforms have a corresponding
 /// `AsRawHandle` and `AsRawSocket` set of traits.
-#[rustc_allowed_through_unstable_modules]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsRawFd {
     /// Extracts the raw file descriptor.
@@ -67,7 +64,6 @@ pub trait AsRawFd {
 
 /// A trait to express the ability to construct an object from a raw file
 /// descriptor.
-#[rustc_allowed_through_unstable_modules]
 #[stable(feature = "from_raw_os", since = "1.1.0")]
 pub trait FromRawFd {
     /// Constructs a new instance of `Self` from the given raw file
@@ -112,7 +108,6 @@ pub trait FromRawFd {
 
 /// A trait to express the ability to consume an object and acquire ownership of
 /// its raw file descriptor.
-#[rustc_allowed_through_unstable_modules]
 #[stable(feature = "into_raw_os", since = "1.4.0")]
 pub trait IntoRawFd {
     /// Consumes this object, returning the raw underlying file descriptor.
diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs
index 2d18f339615..b8601b533fe 100644
--- a/library/std/src/os/solid/io.rs
+++ b/library/std/src/os/solid/io.rs
@@ -54,6 +54,9 @@ use crate::{fmt, net, sys};
 /// Raw file descriptors.
 pub type RawFd = i32;
 
+// The max of this is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`.
+type ValidRawFd = core::num::niche_types::NotAllOnes<RawFd>;
+
 /// A borrowed SOLID Sockets file descriptor.
 ///
 /// This has a lifetime parameter to tie it to the lifetime of something that
@@ -69,12 +72,9 @@ pub type RawFd = i32;
 /// socket, which is then borrowed under the same lifetime.
 #[derive(Copy, Clone)]
 #[repr(transparent)]
-#[rustc_layout_scalar_valid_range_start(0)]
-// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`.
-#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
 #[rustc_nonnull_optimization_guaranteed]
 pub struct BorrowedFd<'socket> {
-    fd: RawFd,
+    fd: ValidRawFd,
     _phantom: PhantomData<&'socket OwnedFd>,
 }
 
@@ -87,12 +87,9 @@ pub struct BorrowedFd<'socket> {
 /// an argument, it is not captured or consumed, and it never has the value
 /// `SOLID_NET_INVALID_FD`.
 #[repr(transparent)]
-#[rustc_layout_scalar_valid_range_start(0)]
-// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`.
-#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
 #[rustc_nonnull_optimization_guaranteed]
 pub struct OwnedFd {
-    fd: RawFd,
+    fd: ValidRawFd,
 }
 
 impl BorrowedFd<'_> {
@@ -108,7 +105,8 @@ impl BorrowedFd<'_> {
         assert!(fd != -1 as RawFd);
         // SAFETY: we just asserted that the value is in the valid range and
         // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
-        unsafe { Self { fd, _phantom: PhantomData } }
+        let fd = unsafe { ValidRawFd::new_unchecked(fd) };
+        Self { fd, _phantom: PhantomData }
     }
 }
 
@@ -132,21 +130,21 @@ impl BorrowedFd<'_> {
 impl AsRawFd for BorrowedFd<'_> {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
-        self.fd
+        self.fd.as_inner()
     }
 }
 
 impl AsRawFd for OwnedFd {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
-        self.fd
+        self.fd.as_inner()
     }
 }
 
 impl IntoRawFd for OwnedFd {
     #[inline]
     fn into_raw_fd(self) -> RawFd {
-        ManuallyDrop::new(self).fd
+        ManuallyDrop::new(self).fd.as_inner()
     }
 }
 
@@ -162,14 +160,15 @@ impl FromRawFd for OwnedFd {
         assert_ne!(fd, -1 as RawFd);
         // SAFETY: we just asserted that the value is in the valid range and
         // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
-        unsafe { Self { fd } }
+        let fd = unsafe { ValidRawFd::new_unchecked(fd) };
+        Self { fd }
     }
 }
 
 impl Drop for OwnedFd {
     #[inline]
     fn drop(&mut self) {
-        unsafe { sys::net::netc::close(self.fd) };
+        unsafe { sys::net::netc::close(self.fd.as_inner()) };
     }
 }
 
diff --git a/library/std/src/os/wasi/io/fd.rs b/library/std/src/os/wasi/io/fd.rs
deleted file mode 100644
index 930aca887e3..00000000000
--- a/library/std/src/os/wasi/io/fd.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//! Owned and borrowed file descriptors.
-
-#![unstable(feature = "wasi_ext", issue = "71213")]
-
-// Tests for this module
-#[cfg(test)]
-mod tests;
-
-pub use crate::os::fd::owned::*;
diff --git a/library/std/src/os/wasi/io/mod.rs b/library/std/src/os/wasi/io/mod.rs
index 4e123a1eec8..5f9a735db08 100644
--- a/library/std/src/os/wasi/io/mod.rs
+++ b/library/std/src/os/wasi/io/mod.rs
@@ -4,3 +4,7 @@
 
 #[stable(feature = "io_safety_wasi", since = "1.65.0")]
 pub use crate::os::fd::*;
+
+// Tests for this module
+#[cfg(test)]
+mod tests;
diff --git a/library/std/src/os/wasi/io/raw.rs b/library/std/src/os/wasi/io/raw.rs
deleted file mode 100644
index da3b36adad4..00000000000
--- a/library/std/src/os/wasi/io/raw.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//! WASI-specific extensions to general I/O primitives.
-
-#![unstable(feature = "wasi_ext", issue = "71213")]
-
-// NOTE: despite the fact that this module is unstable,
-// stable Rust had the capability to access the stable
-// re-exported items from os::fd::raw through this
-// unstable module.
-// In PR #95956 the stability checker was changed to check
-// all path segments of an item rather than just the last,
-// which caused the aforementioned stable usage to regress
-// (see issue #99502).
-// As a result, the items in os::fd::raw were given the
-// rustc_allowed_through_unstable_modules attribute.
-// No regression tests were added to ensure this property,
-// as CI is not configured to test wasm32-wasi.
-// If this module is stabilized,
-// you may want to remove those attributes
-// (assuming no other unstable modules need them).
-pub use crate::os::fd::raw::*;
diff --git a/library/std/src/os/wasi/io/fd/tests.rs b/library/std/src/os/wasi/io/tests.rs
index 418274752b0..418274752b0 100644
--- a/library/std/src/os/wasi/io/fd/tests.rs
+++ b/library/std/src/os/wasi/io/tests.rs
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index c6d7bad9440..6e13a8b502a 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -9,6 +9,9 @@ use crate::mem::{self, ManuallyDrop};
 use crate::sys::cvt;
 use crate::{fmt, io, sys};
 
+// The max here is -2, in two's complement. -1 is `INVALID_SOCKET`.
+type ValidRawSocket = core::num::niche_types::NotAllOnes<RawSocket>;
+
 /// A borrowed socket.
 ///
 /// This has a lifetime parameter to tie it to the lifetime of something that
@@ -24,17 +27,10 @@ use crate::{fmt, io, sys};
 /// socket, which is then borrowed under the same lifetime.
 #[derive(Copy, Clone)]
 #[repr(transparent)]
-#[rustc_layout_scalar_valid_range_start(0)]
-// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
-#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
-#[cfg_attr(
-    target_pointer_width = "64",
-    rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
-)]
 #[rustc_nonnull_optimization_guaranteed]
 #[stable(feature = "io_safety", since = "1.63.0")]
 pub struct BorrowedSocket<'socket> {
-    socket: RawSocket,
+    socket: ValidRawSocket,
     _phantom: PhantomData<&'socket OwnedSocket>,
 }
 
@@ -47,17 +43,10 @@ pub struct BorrowedSocket<'socket> {
 /// argument or returned as an owned value, and it never has the value
 /// `INVALID_SOCKET`.
 #[repr(transparent)]
-#[rustc_layout_scalar_valid_range_start(0)]
-// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
-#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
-#[cfg_attr(
-    target_pointer_width = "64",
-    rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
-)]
 #[rustc_nonnull_optimization_guaranteed]
 #[stable(feature = "io_safety", since = "1.63.0")]
 pub struct OwnedSocket {
-    socket: RawSocket,
+    socket: ValidRawSocket,
 }
 
 impl BorrowedSocket<'_> {
@@ -73,7 +62,8 @@ impl BorrowedSocket<'_> {
     #[stable(feature = "io_safety", since = "1.63.0")]
     pub const unsafe fn borrow_raw(socket: RawSocket) -> Self {
         assert!(socket != sys::c::INVALID_SOCKET as RawSocket);
-        unsafe { Self { socket, _phantom: PhantomData } }
+        let socket = unsafe { ValidRawSocket::new_unchecked(socket) };
+        Self { socket, _phantom: PhantomData }
     }
 }
 
@@ -172,7 +162,7 @@ fn last_error() -> io::Error {
 impl AsRawSocket for BorrowedSocket<'_> {
     #[inline]
     fn as_raw_socket(&self) -> RawSocket {
-        self.socket
+        self.socket.as_inner()
     }
 }
 
@@ -180,7 +170,7 @@ impl AsRawSocket for BorrowedSocket<'_> {
 impl AsRawSocket for OwnedSocket {
     #[inline]
     fn as_raw_socket(&self) -> RawSocket {
-        self.socket
+        self.socket.as_inner()
     }
 }
 
@@ -188,7 +178,7 @@ impl AsRawSocket for OwnedSocket {
 impl IntoRawSocket for OwnedSocket {
     #[inline]
     fn into_raw_socket(self) -> RawSocket {
-        ManuallyDrop::new(self).socket
+        ManuallyDrop::new(self).socket.as_inner()
     }
 }
 
@@ -196,10 +186,9 @@ impl IntoRawSocket for OwnedSocket {
 impl FromRawSocket for OwnedSocket {
     #[inline]
     unsafe fn from_raw_socket(socket: RawSocket) -> Self {
-        unsafe {
-            debug_assert_ne!(socket, sys::c::INVALID_SOCKET as RawSocket);
-            Self { socket }
-        }
+        debug_assert_ne!(socket, sys::c::INVALID_SOCKET as RawSocket);
+        let socket = unsafe { ValidRawSocket::new_unchecked(socket) };
+        Self { socket }
     }
 }
 
@@ -208,7 +197,7 @@ impl Drop for OwnedSocket {
     #[inline]
     fn drop(&mut self) {
         unsafe {
-            let _ = sys::c::closesocket(self.socket as sys::c::SOCKET);
+            let _ = sys::c::closesocket(self.socket.as_inner() as sys::c::SOCKET);
         }
     }
 }
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 3b02254548b..8e50bf11dd0 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -258,31 +258,34 @@ fn default_hook(info: &PanicHookInfo<'_>) {
     let location = info.location().unwrap();
 
     let msg = payload_as_str(info.payload());
-    let thread = thread::try_current();
-    let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
 
     let write = #[optimize(size)]
     |err: &mut dyn crate::io::Write| {
         // Use a lock to prevent mixed output in multithreading context.
         // Some platforms also require it when printing a backtrace, like `SymFromAddr` on Windows.
         let mut lock = backtrace::lock();
-        // Try to write the panic message to a buffer first to prevent other concurrent outputs
-        // interleaving with it.
-        let mut buffer = [0u8; 512];
-        let mut cursor = crate::io::Cursor::new(&mut buffer[..]);
-
-        let write_msg = |dst: &mut dyn crate::io::Write| {
-            // We add a newline to ensure the panic message appears at the start of a line.
-            writeln!(dst, "\nthread '{name}' panicked at {location}:\n{msg}")
-        };
 
-        if write_msg(&mut cursor).is_ok() {
-            let pos = cursor.position() as usize;
-            let _ = err.write_all(&buffer[0..pos]);
-        } else {
-            // The message did not fit into the buffer, write it directly instead.
-            let _ = write_msg(err);
-        };
+        thread::with_current_name(|name| {
+            let name = name.unwrap_or("<unnamed>");
+
+            // Try to write the panic message to a buffer first to prevent other concurrent outputs
+            // interleaving with it.
+            let mut buffer = [0u8; 512];
+            let mut cursor = crate::io::Cursor::new(&mut buffer[..]);
+
+            let write_msg = |dst: &mut dyn crate::io::Write| {
+                // We add a newline to ensure the panic message appears at the start of a line.
+                writeln!(dst, "\nthread '{name}' panicked at {location}:\n{msg}")
+            };
+
+            if write_msg(&mut cursor).is_ok() {
+                let pos = cursor.position() as usize;
+                let _ = err.write_all(&buffer[0..pos]);
+            } else {
+                // The message did not fit into the buffer, write it directly instead.
+                let _ = write_msg(err);
+            };
+        });
 
         static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
 
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 35e920ab344..7fd08a97f1f 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -298,7 +298,7 @@ where
 }
 
 // Detect scheme on Redox
-fn has_redox_scheme(s: &[u8]) -> bool {
+pub(crate) fn has_redox_scheme(s: &[u8]) -> bool {
     cfg!(target_os = "redox") && s.contains(&b':')
 }
 
@@ -2155,7 +2155,7 @@ impl Path {
         unsafe { Path::new(OsStr::from_encoded_bytes_unchecked(s)) }
     }
     // The following (private!) function reveals the byte encoding used for OsStr.
-    fn as_u8_slice(&self) -> &[u8] {
+    pub(crate) fn as_u8_slice(&self) -> &[u8] {
         self.inner.as_encoded_bytes()
     }
 
@@ -2323,14 +2323,7 @@ impl Path {
     #[must_use]
     #[allow(deprecated)]
     pub fn is_absolute(&self) -> bool {
-        if cfg!(target_os = "redox") {
-            // FIXME: Allow Redox prefixes
-            self.has_root() || has_redox_scheme(self.as_u8_slice())
-        } else {
-            self.has_root()
-                && (cfg!(any(unix, target_os = "hermit", target_os = "wasi"))
-                    || self.prefix().is_some())
-        }
+        sys::path::is_absolute(self)
     }
 
     /// Returns `true` if the `Path` is relative, i.e., not absolute.
@@ -2353,7 +2346,7 @@ impl Path {
         !self.is_absolute()
     }
 
-    fn prefix(&self) -> Option<Prefix<'_>> {
+    pub(crate) fn prefix(&self) -> Option<Prefix<'_>> {
         self.components().prefix
     }
 
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs
index ff3f7151bb8..3f96ac4672a 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/src/path/tests.rs
@@ -2069,9 +2069,7 @@ fn clone_to_uninit() {
 
     let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<Path>(a)];
     unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) };
-    assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe {
-        MaybeUninit::slice_assume_init_ref(&storage)
-    });
+    assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe { storage.assume_init_ref() });
 
     let mut b: Box<Path> = Path::new("world.exe").into();
     assert_eq!(size_of_val::<Path>(a), size_of_val::<Path>(&b));
diff --git a/library/std/src/pipe.rs b/library/std/src/pipe.rs
deleted file mode 100644
index 913c22588a7..00000000000
--- a/library/std/src/pipe.rs
+++ /dev/null
@@ -1,258 +0,0 @@
-//!  A cross-platform anonymous pipe.
-//!
-//! This module provides support for anonymous OS pipes, like [pipe] on Linux or [CreatePipe] on
-//! Windows.
-//!
-//! # Behavior
-//!
-//! A pipe is a synchronous, unidirectional data channel between two or more processes, like an
-//! interprocess [`mpsc`](crate::sync::mpsc) provided by the OS. In particular:
-//!
-//! * A read on a [`PipeReader`] blocks until the pipe is non-empty.
-//! * A write on a [`PipeWriter`] blocks when the pipe is full.
-//! * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`]
-//!   returns EOF.
-//! * [`PipeReader`] can be shared, but only one process will consume the data in the pipe.
-//!
-//! # Capacity
-//!
-//! Pipe capacity is platform dependent. To quote the Linux [man page]:
-//!
-//! > Different implementations have different limits for the pipe capacity. Applications should
-//! > not rely on a particular capacity: an application should be designed so that a reading process
-//! > consumes data as soon as it is available, so that a writing process does not remain blocked.
-//!
-//! # Examples
-//!
-//! ```no_run
-//! #![feature(anonymous_pipe)]
-//! # #[cfg(miri)] fn main() {}
-//! # #[cfg(not(miri))]
-//! # fn main() -> std::io::Result<()> {
-//! # use std::process::Command;
-//! # use std::io::{Read, Write};
-//! let (ping_rx, mut ping_tx) = std::pipe::pipe()?;
-//! let (mut pong_rx, pong_tx) = std::pipe::pipe()?;
-//!
-//! // Spawn a process that echoes its input.
-//! let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
-//!
-//! ping_tx.write_all(b"hello")?;
-//! // Close to unblock echo_server's reader.
-//! drop(ping_tx);
-//!
-//! let mut buf = String::new();
-//! // Block until echo_server's writer is closed.
-//! pong_rx.read_to_string(&mut buf)?;
-//! assert_eq!(&buf, "hello");
-//!
-//! echo_server.wait()?;
-//! # Ok(())
-//! # }
-//! ```
-//! [pipe]: https://man7.org/linux/man-pages/man2/pipe.2.html
-//! [CreatePipe]: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe
-//! [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html
-use crate::io;
-use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
-
-/// Create anonymous pipe that is close-on-exec and blocking.
-///
-/// # Examples
-///
-/// See the [module-level](crate::pipe) documentation for examples.
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-#[inline]
-pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
-    pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer)))
-}
-
-/// Read end of the anonymous pipe.
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-#[derive(Debug)]
-pub struct PipeReader(pub(crate) AnonPipe);
-
-/// Write end of the anonymous pipe.
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-#[derive(Debug)]
-pub struct PipeWriter(pub(crate) AnonPipe);
-
-impl PipeReader {
-    /// Create a new [`PipeReader`] instance that shares the same underlying file description.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// #![feature(anonymous_pipe)]
-    /// # #[cfg(miri)] fn main() {}
-    /// # #[cfg(not(miri))]
-    /// # fn main() -> std::io::Result<()> {
-    /// # use std::fs;
-    /// # use std::io::Write;
-    /// # use std::process::Command;
-    /// const NUM_SLOT: u8 = 2;
-    /// const NUM_PROC: u8 = 5;
-    /// const OUTPUT: &str = "work.txt";
-    ///
-    /// let mut jobs = vec![];
-    /// let (reader, mut writer) = std::pipe::pipe()?;
-    ///
-    /// // Write NUM_SLOT characters the pipe.
-    /// writer.write_all(&[b'|'; NUM_SLOT as usize])?;
-    ///
-    /// // Spawn several processes that read a character from the pipe, do some work, then
-    /// // write back to the pipe. When the pipe is empty, the processes block, so only
-    /// // NUM_SLOT processes can be working at any given time.
-    /// for _ in 0..NUM_PROC {
-    ///     jobs.push(
-    ///         Command::new("bash")
-    ///             .args(["-c",
-    ///                 &format!(
-    ///                      "read -n 1\n\
-    ///                       echo -n 'x' >> '{OUTPUT}'\n\
-    ///                       echo -n '|'",
-    ///                 ),
-    ///             ])
-    ///             .stdin(reader.try_clone()?)
-    ///             .stdout(writer.try_clone()?)
-    ///             .spawn()?,
-    ///     );
-    /// }
-    ///
-    /// // Wait for all jobs to finish.
-    /// for mut job in jobs {
-    ///     job.wait()?;
-    /// }
-    ///
-    /// // Check our work and clean up.
-    /// let xs = fs::read_to_string(OUTPUT)?;
-    /// fs::remove_file(OUTPUT)?;
-    /// assert_eq!(xs, "x".repeat(NUM_PROC.into()));
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[unstable(feature = "anonymous_pipe", issue = "127154")]
-    pub fn try_clone(&self) -> io::Result<Self> {
-        self.0.try_clone().map(Self)
-    }
-}
-
-impl PipeWriter {
-    /// Create a new [`PipeWriter`] instance that shares the same underlying file description.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// #![feature(anonymous_pipe)]
-    /// # #[cfg(miri)] fn main() {}
-    /// # #[cfg(not(miri))]
-    /// # fn main() -> std::io::Result<()> {
-    /// # use std::process::Command;
-    /// # use std::io::Read;
-    /// let (mut reader, writer) = std::pipe::pipe()?;
-    ///
-    /// // Spawn a process that writes to stdout and stderr.
-    /// let mut peer = Command::new("bash")
-    ///     .args([
-    ///         "-c",
-    ///         "echo -n foo\n\
-    ///          echo -n bar >&2"
-    ///     ])
-    ///     .stdout(writer.try_clone()?)
-    ///     .stderr(writer)
-    ///     .spawn()?;
-    ///
-    /// // Read and check the result.
-    /// let mut msg = String::new();
-    /// reader.read_to_string(&mut msg)?;
-    /// assert_eq!(&msg, "foobar");
-    ///
-    /// peer.wait()?;
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[unstable(feature = "anonymous_pipe", issue = "127154")]
-    pub fn try_clone(&self) -> io::Result<Self> {
-        self.0.try_clone().map(Self)
-    }
-}
-
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-impl io::Read for &PipeReader {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
-    }
-    fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
-        self.0.read_vectored(bufs)
-    }
-    #[inline]
-    fn is_read_vectored(&self) -> bool {
-        self.0.is_read_vectored()
-    }
-    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        self.0.read_to_end(buf)
-    }
-    fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
-        self.0.read_buf(buf)
-    }
-}
-
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-impl io::Read for PipeReader {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
-    }
-    fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
-        self.0.read_vectored(bufs)
-    }
-    #[inline]
-    fn is_read_vectored(&self) -> bool {
-        self.0.is_read_vectored()
-    }
-    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        self.0.read_to_end(buf)
-    }
-    fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
-        self.0.read_buf(buf)
-    }
-}
-
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-impl io::Write for &PipeWriter {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
-    }
-    #[inline]
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-
-    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
-        self.0.write_vectored(bufs)
-    }
-
-    #[inline]
-    fn is_write_vectored(&self) -> bool {
-        self.0.is_write_vectored()
-    }
-}
-
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-impl io::Write for PipeWriter {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
-    }
-    #[inline]
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-
-    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
-        self.0.write_vectored(bufs)
-    }
-
-    #[inline]
-    fn is_write_vectored(&self) -> bool {
-        self.0.is_write_vectored()
-    }
-}
diff --git a/library/std/src/pipe/tests.rs b/library/std/src/pipe/tests.rs
deleted file mode 100644
index 9c38e106787..00000000000
--- a/library/std/src/pipe/tests.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use crate::io::{Read, Write};
-use crate::pipe::pipe;
-
-#[test]
-#[cfg(all(windows, unix, not(miri)))]
-fn pipe_creation_clone_and_rw() {
-    let (rx, tx) = pipe().unwrap();
-
-    tx.try_clone().unwrap().write_all(b"12345").unwrap();
-    drop(tx);
-
-    let mut rx2 = rx.try_clone().unwrap();
-    drop(rx);
-
-    let mut s = String::new();
-    rx2.read_to_string(&mut s).unwrap();
-    drop(rx2);
-    assert_eq!(s, "12345");
-}
diff --git a/library/std/src/prelude/common.rs b/library/std/src/prelude/common.rs
index 22a364074c5..0f2d8334fca 100644
--- a/library/std/src/prelude/common.rs
+++ b/library/std/src/prelude/common.rs
@@ -12,8 +12,7 @@ pub use crate::marker::{Send, Sized, Sync, Unpin};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
-#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
-#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
+#[stable(feature = "async_closure", since = "1.85.0")]
 #[doc(no_inline)]
 pub use crate::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce};
 
diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs
index 64349987fcf..4ec328208f0 100644
--- a/library/std/src/prelude/mod.rs
+++ b/library/std/src/prelude/mod.rs
@@ -169,12 +169,12 @@ pub mod rust_2021 {
 /// The 2024 version of the prelude of The Rust Standard Library.
 ///
 /// See the [module-level documentation](self) for more.
-#[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "prelude_2024", since = "1.85.0")]
 pub mod rust_2024 {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::common::*;
 
-    #[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "prelude_2024", since = "1.85.0")]
     #[doc(no_inline)]
     pub use core::prelude::rust_2024::*;
 }
diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs
index b2492238bd3..3a22a16cb16 100644
--- a/library/std/src/rt.rs
+++ b/library/std/src/rt.rs
@@ -23,7 +23,7 @@ pub use core::panicking::{panic_display, panic_fmt};
 #[rustfmt::skip]
 use crate::any::Any;
 use crate::sync::Once;
-use crate::thread::{self, Thread};
+use crate::thread::{self, main_thread};
 use crate::{mem, panic, sys};
 
 // Prints to the "panic output", depending on the platform this may be:
@@ -32,9 +32,14 @@ use crate::{mem, panic, sys};
 // - nothing (so this macro is a no-op)
 macro_rules! rtprintpanic {
     ($($t:tt)*) => {
+        #[cfg(not(feature = "panic_immediate_abort"))]
         if let Some(mut out) = crate::sys::stdio::panic_output() {
             let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*));
         }
+        #[cfg(feature = "panic_immediate_abort")]
+        {
+            let _ = format_args!($($t)*);
+        }
     }
 }
 
@@ -67,7 +72,7 @@ macro_rules! rtunwrap {
     };
 }
 
-fn handle_rt_panic(e: Box<dyn Any + Send>) {
+fn handle_rt_panic<T>(e: Box<dyn Any + Send>) -> T {
     mem::forget(e);
     rtabort!("initialization or cleanup bug");
 }
@@ -102,24 +107,9 @@ unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
         sys::init(argc, argv, sigpipe)
     };
 
-    // Set up the current thread handle to give it the right name.
-    //
-    // When code running before main uses `ReentrantLock` (for example by
-    // using `println!`), the thread ID can become initialized before we
-    // create this handle. Since `set_current` fails when the ID of the
-    // handle does not match the current ID, we should attempt to use the
-    // current thread ID here instead of unconditionally creating a new
-    // one. Also see #130210.
-    let thread = unsafe { Thread::new_main(thread::current_id()) };
-    if let Err(_thread) = thread::set_current(thread) {
-        // `thread::current` will create a new handle if none has been set yet.
-        // Thus, if someone uses it before main, this call will fail. That's a
-        // bad idea though, as we then cannot set the main thread name here.
-        //
-        // FIXME: detect the main thread in `thread::current` and use the
-        //        correct name there.
-        rtabort!("code running before main must not use thread::current");
-    }
+    // Remember the main thread ID to give it the correct name.
+    // SAFETY: this is the only time and place where we call this function.
+    unsafe { main_thread::set(thread::current_id()) };
 }
 
 /// Clean up the thread-local runtime state. This *should* be run after all other
@@ -157,7 +147,7 @@ fn lang_start_internal(
     argc: isize,
     argv: *const *const u8,
     sigpipe: u8,
-) -> Result<isize, !> {
+) -> isize {
     // Guard against the code called by this function from unwinding outside of the Rust-controlled
     // code, which is UB. This is a requirement imposed by a combination of how the
     // `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking
@@ -168,19 +158,33 @@ fn lang_start_internal(
     // panic is a std implementation bug. A quite likely one too, as there isn't any way to
     // prevent std from accidentally introducing a panic to these functions. Another is from
     // user code from `main` or, more nefariously, as described in e.g. issue #86030.
-    // SAFETY: Only called once during runtime initialization.
-    panic::catch_unwind(move || unsafe { init(argc, argv, sigpipe) })
-        .unwrap_or_else(handle_rt_panic);
-    let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize)
-        .map_err(move |e| {
-            mem::forget(e);
-            rtabort!("drop of the panic payload panicked");
+    //
+    // We use `catch_unwind` with `handle_rt_panic` instead of `abort_unwind` to make the error in
+    // case of a panic a bit nicer.
+    panic::catch_unwind(move || {
+        // SAFETY: Only called once during runtime initialization.
+        unsafe { init(argc, argv, sigpipe) };
+
+        let ret_code = panic::catch_unwind(main).unwrap_or_else(move |payload| {
+            // Carefully dispose of the panic payload.
+            let payload = panic::AssertUnwindSafe(payload);
+            panic::catch_unwind(move || drop({ payload }.0)).unwrap_or_else(move |e| {
+                mem::forget(e); // do *not* drop the 2nd payload
+                rtabort!("drop of the panic payload panicked");
+            });
+            // Return error code for panicking programs.
+            101
         });
-    panic::catch_unwind(cleanup).unwrap_or_else(handle_rt_panic);
-    // Guard against multiple threads calling `libc::exit` concurrently.
-    // See the documentation for `unique_thread_exit` for more information.
-    panic::catch_unwind(crate::sys::exit_guard::unique_thread_exit).unwrap_or_else(handle_rt_panic);
-    ret_code
+        let ret_code = ret_code as isize;
+
+        cleanup();
+        // Guard against multiple threads calling `libc::exit` concurrently.
+        // See the documentation for `unique_thread_exit` for more information.
+        crate::sys::exit_guard::unique_thread_exit();
+
+        ret_code
+    })
+    .unwrap_or_else(handle_rt_panic)
 }
 
 #[cfg(not(any(test, doctest)))]
@@ -191,11 +195,10 @@ fn lang_start<T: crate::process::Termination + 'static>(
     argv: *const *const u8,
     sigpipe: u8,
 ) -> isize {
-    let Ok(v) = lang_start_internal(
+    lang_start_internal(
         &move || crate::sys::backtrace::__rust_begin_short_backtrace(main).report().to_i32(),
         argc,
         argv,
         sigpipe,
-    );
-    v
+    )
 }
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 1e4f9b79e0f..98c83d8d326 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -31,7 +31,7 @@ union Data<T, F> {
 /// ```
 /// use std::sync::LazyLock;
 ///
-/// // n.b. static items do not call [`Drop`] on program termination, so this won't be deallocated.
+/// // Note: static items do not call [`Drop`] on program termination, so this won't be deallocated.
 /// // this is fine, as the OS can deallocate the terminated program faster than we can free memory
 /// // but tools like valgrind might report "memory leaks" as it isn't obvious this is intentional.
 /// static DEEP_THOUGHT: LazyLock<String> = LazyLock::new(|| {
diff --git a/library/std/src/sys/anonymous_pipe/unix.rs b/library/std/src/sys/anonymous_pipe/unix.rs
index 9168024730e..9e398765634 100644
--- a/library/std/src/sys/anonymous_pipe/unix.rs
+++ b/library/std/src/sys/anonymous_pipe/unix.rs
@@ -1,6 +1,5 @@
-use crate::io;
+use crate::io::{self, PipeReader, PipeWriter};
 use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
-use crate::pipe::{PipeReader, PipeWriter};
 use crate::process::Stdio;
 use crate::sys::fd::FileDesc;
 use crate::sys::pipe::anon_pipe;
diff --git a/library/std/src/sys/anonymous_pipe/unsupported.rs b/library/std/src/sys/anonymous_pipe/unsupported.rs
index dd51e70315e..4e79ac9c21a 100644
--- a/library/std/src/sys/anonymous_pipe/unsupported.rs
+++ b/library/std/src/sys/anonymous_pipe/unsupported.rs
@@ -1,5 +1,4 @@
-use crate::io;
-use crate::pipe::{PipeReader, PipeWriter};
+use crate::io::{self, PipeReader, PipeWriter};
 use crate::process::Stdio;
 pub use crate::sys::pipe::AnonPipe;
 
diff --git a/library/std/src/sys/anonymous_pipe/windows.rs b/library/std/src/sys/anonymous_pipe/windows.rs
index a48198f8a81..eb7fa8ec1c9 100644
--- a/library/std/src/sys/anonymous_pipe/windows.rs
+++ b/library/std/src/sys/anonymous_pipe/windows.rs
@@ -1,12 +1,12 @@
+use crate::io::{self, PipeReader, PipeWriter};
 use crate::os::windows::io::{
     AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
 };
-use crate::pipe::{PipeReader, PipeWriter};
 use crate::process::Stdio;
+use crate::ptr;
 use crate::sys::c;
 use crate::sys::handle::Handle;
 use crate::sys_common::{FromInner, IntoInner};
-use crate::{io, ptr};
 
 pub type AnonPipe = Handle;
 
diff --git a/library/std/src/sys/pal/solid/fs.rs b/library/std/src/sys/pal/solid/fs.rs
index 04dd10ad806..fa2e470d6b6 100644
--- a/library/std/src/sys/pal/solid/fs.rs
+++ b/library/std/src/sys/pal/solid/fs.rs
@@ -12,15 +12,12 @@ use crate::sys::unsupported;
 pub use crate::sys_common::fs::exists;
 use crate::sys_common::ignore_notfound;
 
+type CIntNotMinusOne = core::num::niche_types::NotAllOnes<c_int>;
+
 /// A file descriptor.
 #[derive(Clone, Copy)]
-#[rustc_layout_scalar_valid_range_start(0)]
-// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
-// 32-bit c_int. Below is -2, in two's complement, but that only works out
-// because c_int is 32 bits.
-#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
 struct FileDesc {
-    fd: c_int,
+    fd: CIntNotMinusOne,
 }
 
 impl FileDesc {
@@ -29,12 +26,13 @@ impl FileDesc {
         assert_ne!(fd, -1i32);
         // Safety: we just asserted that the value is in the valid range and
         // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
-        unsafe { FileDesc { fd } }
+        let fd = unsafe { CIntNotMinusOne::new_unchecked(fd) };
+        FileDesc { fd }
     }
 
     #[inline]
     fn raw(&self) -> c_int {
-        self.fd
+        self.fd.as_inner()
     }
 }
 
diff --git a/library/std/src/sys/pal/uefi/fs.rs b/library/std/src/sys/pal/uefi/fs.rs
new file mode 100644
index 00000000000..9585ec24f68
--- /dev/null
+++ b/library/std/src/sys/pal/uefi/fs.rs
@@ -0,0 +1,344 @@
+use crate::ffi::OsString;
+use crate::fmt;
+use crate::hash::{Hash, Hasher};
+use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
+use crate::path::{Path, PathBuf};
+use crate::sys::time::SystemTime;
+use crate::sys::unsupported;
+
+pub struct File(!);
+
+pub struct FileAttr(!);
+
+pub struct ReadDir(!);
+
+pub struct DirEntry(!);
+
+#[derive(Clone, Debug)]
+pub struct OpenOptions {}
+
+#[derive(Copy, Clone, Debug, Default)]
+pub struct FileTimes {}
+
+pub struct FilePermissions(!);
+
+pub struct FileType(!);
+
+#[derive(Debug)]
+pub struct DirBuilder {}
+
+impl FileAttr {
+    pub fn size(&self) -> u64 {
+        self.0
+    }
+
+    pub fn perm(&self) -> FilePermissions {
+        self.0
+    }
+
+    pub fn file_type(&self) -> FileType {
+        self.0
+    }
+
+    pub fn modified(&self) -> io::Result<SystemTime> {
+        self.0
+    }
+
+    pub fn accessed(&self) -> io::Result<SystemTime> {
+        self.0
+    }
+
+    pub fn created(&self) -> io::Result<SystemTime> {
+        self.0
+    }
+}
+
+impl Clone for FileAttr {
+    fn clone(&self) -> FileAttr {
+        self.0
+    }
+}
+
+impl FilePermissions {
+    pub fn readonly(&self) -> bool {
+        self.0
+    }
+
+    pub fn set_readonly(&mut self, _readonly: bool) {
+        self.0
+    }
+}
+
+impl Clone for FilePermissions {
+    fn clone(&self) -> FilePermissions {
+        self.0
+    }
+}
+
+impl PartialEq for FilePermissions {
+    fn eq(&self, _other: &FilePermissions) -> bool {
+        self.0
+    }
+}
+
+impl Eq for FilePermissions {}
+
+impl fmt::Debug for FilePermissions {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0
+    }
+}
+
+impl FileTimes {
+    pub fn set_accessed(&mut self, _t: SystemTime) {}
+    pub fn set_modified(&mut self, _t: SystemTime) {}
+}
+
+impl FileType {
+    pub fn is_dir(&self) -> bool {
+        self.0
+    }
+
+    pub fn is_file(&self) -> bool {
+        self.0
+    }
+
+    pub fn is_symlink(&self) -> bool {
+        self.0
+    }
+}
+
+impl Clone for FileType {
+    fn clone(&self) -> FileType {
+        self.0
+    }
+}
+
+impl Copy for FileType {}
+
+impl PartialEq for FileType {
+    fn eq(&self, _other: &FileType) -> bool {
+        self.0
+    }
+}
+
+impl Eq for FileType {}
+
+impl Hash for FileType {
+    fn hash<H: Hasher>(&self, _h: &mut H) {
+        self.0
+    }
+}
+
+impl fmt::Debug for FileType {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0
+    }
+}
+
+impl fmt::Debug for ReadDir {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0
+    }
+}
+
+impl Iterator for ReadDir {
+    type Item = io::Result<DirEntry>;
+
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        self.0
+    }
+}
+
+impl DirEntry {
+    pub fn path(&self) -> PathBuf {
+        self.0
+    }
+
+    pub fn file_name(&self) -> OsString {
+        self.0
+    }
+
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        self.0
+    }
+
+    pub fn file_type(&self) -> io::Result<FileType> {
+        self.0
+    }
+}
+
+impl OpenOptions {
+    pub fn new() -> OpenOptions {
+        OpenOptions {}
+    }
+
+    pub fn read(&mut self, _read: bool) {}
+    pub fn write(&mut self, _write: bool) {}
+    pub fn append(&mut self, _append: bool) {}
+    pub fn truncate(&mut self, _truncate: bool) {}
+    pub fn create(&mut self, _create: bool) {}
+    pub fn create_new(&mut self, _create_new: bool) {}
+}
+
+impl File {
+    pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
+        unsupported()
+    }
+
+    pub fn file_attr(&self) -> io::Result<FileAttr> {
+        self.0
+    }
+
+    pub fn fsync(&self) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn datasync(&self) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn lock(&self) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn lock_shared(&self) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn try_lock(&self) -> io::Result<bool> {
+        self.0
+    }
+
+    pub fn try_lock_shared(&self) -> io::Result<bool> {
+        self.0
+    }
+
+    pub fn unlock(&self) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn truncate(&self, _size: u64) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
+        self.0
+    }
+
+    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.0
+    }
+
+    pub fn is_read_vectored(&self) -> bool {
+        self.0
+    }
+
+    pub fn read_buf(&self, _cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
+        self.0
+    }
+
+    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.0
+    }
+
+    pub fn is_write_vectored(&self) -> bool {
+        self.0
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
+        self.0
+    }
+
+    pub fn duplicate(&self) -> io::Result<File> {
+        self.0
+    }
+
+    pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
+        self.0
+    }
+}
+
+impl DirBuilder {
+    pub fn new() -> DirBuilder {
+        DirBuilder {}
+    }
+
+    pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
+        unsupported()
+    }
+}
+
+impl fmt::Debug for File {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0
+    }
+}
+
+pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
+    unsupported()
+}
+
+pub fn unlink(_p: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
+    match perm.0 {}
+}
+
+pub fn rmdir(_p: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn exists(_path: &Path) -> io::Result<bool> {
+    unsupported()
+}
+
+pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn stat(_p: &Path) -> io::Result<FileAttr> {
+    unsupported()
+}
+
+pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
+    unsupported()
+}
+
+pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
+    unsupported()
+}
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index 47d9add72b5..7504a0f7ad7 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -222,14 +222,14 @@ pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>>
     NonNull::new(runtime_services)
 }
 
-pub(crate) struct DevicePath(NonNull<r_efi::protocols::device_path::Protocol>);
+pub(crate) struct OwnedDevicePath(NonNull<r_efi::protocols::device_path::Protocol>);
 
-impl DevicePath {
+impl OwnedDevicePath {
     pub(crate) fn from_text(p: &OsStr) -> io::Result<Self> {
         fn inner(
             p: &OsStr,
             protocol: NonNull<r_efi::protocols::device_path_from_text::Protocol>,
-        ) -> io::Result<DevicePath> {
+        ) -> io::Result<OwnedDevicePath> {
             let path_vec = p.encode_wide().chain(Some(0)).collect::<Vec<u16>>();
             if path_vec[..path_vec.len() - 1].contains(&0) {
                 return Err(const_error!(
@@ -242,7 +242,7 @@ impl DevicePath {
                 unsafe { ((*protocol.as_ptr()).convert_text_to_device_path)(path_vec.as_ptr()) };
 
             NonNull::new(path)
-                .map(DevicePath)
+                .map(OwnedDevicePath)
                 .ok_or_else(|| const_error!(io::ErrorKind::InvalidFilename, "Invalid Device Path"))
         }
 
@@ -275,12 +275,12 @@ impl DevicePath {
         ))
     }
 
-    pub(crate) fn as_ptr(&self) -> *mut r_efi::protocols::device_path::Protocol {
+    pub(crate) const fn as_ptr(&self) -> *mut r_efi::protocols::device_path::Protocol {
         self.0.as_ptr()
     }
 }
 
-impl Drop for DevicePath {
+impl Drop for OwnedDevicePath {
     fn drop(&mut self) {
         if let Some(bt) = boot_services() {
             let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
@@ -291,6 +291,15 @@ impl Drop for DevicePath {
     }
 }
 
+impl crate::fmt::Debug for OwnedDevicePath {
+    fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
+        match device_path_to_text(self.0) {
+            Ok(p) => p.fmt(f),
+            Err(_) => f.debug_struct("OwnedDevicePath").finish_non_exhaustive(),
+        }
+    }
+}
+
 pub(crate) struct OwnedProtocol<T> {
     guid: r_efi::efi::Guid,
     handle: NonNull<crate::ffi::c_void>,
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index f29c91f3bfe..111bed7a7eb 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -15,7 +15,6 @@
 
 pub mod args;
 pub mod env;
-#[path = "../unsupported/fs.rs"]
 pub mod fs;
 pub mod helpers;
 #[path = "../unsupported/io.rs"]
diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/pal/uefi/process.rs
index 95707ebb7f0..1a0754134df 100644
--- a/library/std/src/sys/pal/uefi/process.rs
+++ b/library/std/src/sys/pal/uefi/process.rs
@@ -326,7 +326,7 @@ mod uefi_command_internal {
 
     impl Image {
         pub fn load_image(p: &OsStr) -> io::Result<Self> {
-            let path = helpers::DevicePath::from_text(p)?;
+            let path = helpers::OwnedDevicePath::from_text(p)?;
             let boot_services: NonNull<r_efi::efi::BootServices> = boot_services()
                 .ok_or_else(|| const_error!(io::ErrorKind::NotFound, "Boot Services not found"))?
                 .cast();
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index 54fa31620ac..fdf011c1948 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -709,7 +709,7 @@ impl Iterator for ReadDir {
                 // thread safety for readdir() as long an individual DIR* is not accessed
                 // concurrently, which is sufficient for Rust.
                 super::os::set_errno(0);
-                let entry_ptr = readdir64(self.inner.dirp.0);
+                let entry_ptr: *const dirent64 = readdir64(self.inner.dirp.0);
                 if entry_ptr.is_null() {
                     // We either encountered an error, or reached the end. Either way,
                     // the next call to next() should return None.
@@ -735,29 +735,19 @@ impl Iterator for ReadDir {
                 // contents were "simply" partially initialized data.
                 //
                 // Like for uninitialized contents, converting entry_ptr to `&dirent64`
-                // would not be legal. However, unique to dirent64 is that we don't even
-                // get to use `&raw const (*entry_ptr).d_name` because that operation
-                // requires the full extent of *entry_ptr to be in bounds of the same
-                // allocation, which is not necessarily the case here.
-                //
-                // Instead we must access fields individually through their offsets.
-                macro_rules! offset_ptr {
-                    ($entry_ptr:expr, $field:ident) => {{
-                        const OFFSET: isize = mem::offset_of!(dirent64, $field) as isize;
-                        if true {
-                            // Cast to the same type determined by the else branch.
-                            $entry_ptr.byte_offset(OFFSET).cast::<_>()
-                        } else {
-                            #[allow(deref_nullptr)]
-                            {
-                                &raw const (*ptr::null::<dirent64>()).$field
-                            }
-                        }
-                    }};
+                // would not be legal. However, we can use `&raw const (*entry_ptr).d_name`
+                // to refer the fields individually, because that operation is equivalent
+                // to `byte_offset` and thus does not require the full extent of `*entry_ptr`
+                // to be in bounds of the same allocation, only the offset of the field
+                // being referenced.
+                macro_rules! entry_field_ptr {
+                    ($field:ident) => {
+                        &raw const (*entry_ptr).$field
+                    };
                 }
 
                 // d_name is guaranteed to be null-terminated.
-                let name = CStr::from_ptr(offset_ptr!(entry_ptr, d_name).cast());
+                let name = CStr::from_ptr(entry_field_ptr!(d_name).cast());
                 let name_bytes = name.to_bytes();
                 if name_bytes == b"." || name_bytes == b".." {
                     continue;
@@ -765,14 +755,14 @@ impl Iterator for ReadDir {
 
                 #[cfg(not(target_os = "vita"))]
                 let entry = dirent64_min {
-                    d_ino: *offset_ptr!(entry_ptr, d_ino) as u64,
+                    d_ino: *entry_field_ptr!(d_ino) as u64,
                     #[cfg(not(any(
                         target_os = "solaris",
                         target_os = "illumos",
                         target_os = "aix",
                         target_os = "nto",
                     )))]
-                    d_type: *offset_ptr!(entry_ptr, d_type) as u8,
+                    d_type: *entry_field_ptr!(d_type) as u8,
                 };
 
                 #[cfg(target_os = "vita")]
diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs
index 36823a503b1..bbf29f32523 100644
--- a/library/std/src/sys/pal/unix/kernel_copy.rs
+++ b/library/std/src/sys/pal/unix/kernel_copy.rs
@@ -52,15 +52,14 @@ use crate::cmp::min;
 use crate::fs::{File, Metadata};
 use crate::io::copy::generic_copy;
 use crate::io::{
-    BufRead, BufReader, BufWriter, Error, Read, Result, StderrLock, StdinLock, StdoutLock, Take,
-    Write,
+    BufRead, BufReader, BufWriter, Error, PipeReader, PipeWriter, Read, Result, StderrLock,
+    StdinLock, StdoutLock, Take, Write,
 };
 use crate::mem::ManuallyDrop;
 use crate::net::TcpStream;
 use crate::os::unix::fs::FileTypeExt;
 use crate::os::unix::io::{AsRawFd, FromRawFd, RawFd};
 use crate::os::unix::net::UnixStream;
-use crate::pipe::{PipeReader, PipeWriter};
 use crate::process::{ChildStderr, ChildStdin, ChildStdout};
 use crate::ptr;
 use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 69b31da427f..db5c6bd3a1c 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -100,10 +100,11 @@ mod imp {
         // If the faulting address is within the guard page, then we print a
         // message saying so and abort.
         if start <= addr && addr < end {
-            rtprintpanic!(
-                "\nthread '{}' has overflowed its stack\n",
-                thread::current().name().unwrap_or("<unknown>")
-            );
+            thread::with_current_name(|name| {
+                let name = name.unwrap_or("<unknown>");
+                rtprintpanic!("\nthread '{name}' has overflowed its stack\n");
+            });
+
             rtabort!("stack overflow");
         } else {
             // Unregister ourselves by reverting back to the default behavior.
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index e360ba0f6d7..f657f82e6e3 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -130,25 +130,27 @@ impl Thread {
         }
     }
 
-    #[cfg(target_os = "linux")]
+    #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"))]
     pub fn set_name(name: &CStr) {
-        const TASK_COMM_LEN: usize = 16;
-
         unsafe {
-            // Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20.
-            let name = truncate_cstr::<{ TASK_COMM_LEN }>(name);
+            cfg_if::cfg_if! {
+                if #[cfg(target_os = "linux")] {
+                    // Linux limits the allowed length of the name.
+                    const TASK_COMM_LEN: usize = 16;
+                    let name = truncate_cstr::<{ TASK_COMM_LEN }>(name);
+                } else {
+                    // FreeBSD and DragonFly BSD do not enforce length limits.
+                }
+            };
+            // Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20 for Linux,
+            // FreeBSD 12.2 and 13.0, and DragonFly BSD 6.0.
             let res = libc::pthread_setname_np(libc::pthread_self(), name.as_ptr());
             // We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
             debug_assert_eq!(res, 0);
         }
     }
 
-    #[cfg(any(
-        target_os = "freebsd",
-        target_os = "dragonfly",
-        target_os = "openbsd",
-        target_os = "nuttx"
-    ))]
+    #[cfg(any(target_os = "openbsd", target_os = "nuttx"))]
     pub fn set_name(name: &CStr) {
         unsafe {
             libc::pthread_set_name_np(libc::pthread_self(), name.as_ptr());
diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs
index 343864d0b3f..e224980e95f 100644
--- a/library/std/src/sys/pal/unix/time.rs
+++ b/library/std/src/sys/pal/unix/time.rs
@@ -1,3 +1,5 @@
+use core::num::niche_types::Nanoseconds;
+
 use crate::time::Duration;
 use crate::{fmt, io};
 
@@ -16,12 +18,6 @@ pub(in crate::sys) const TIMESPEC_MAX_CAPPED: libc::timespec = libc::timespec {
 };
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[repr(transparent)]
-#[rustc_layout_scalar_valid_range_start(0)]
-#[rustc_layout_scalar_valid_range_end(999_999_999)]
-struct Nanoseconds(u32);
-
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct SystemTime {
     pub(crate) t: Timespec,
 }
@@ -59,14 +55,14 @@ impl fmt::Debug for SystemTime {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("SystemTime")
             .field("tv_sec", &self.t.tv_sec)
-            .field("tv_nsec", &self.t.tv_nsec.0)
+            .field("tv_nsec", &self.t.tv_nsec)
             .finish()
     }
 }
 
 impl Timespec {
     const unsafe fn new_unchecked(tv_sec: i64, tv_nsec: i64) -> Timespec {
-        Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds(tv_nsec as u32) } }
+        Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds::new_unchecked(tv_nsec as u32) } }
     }
 
     pub const fn zero() -> Timespec {
@@ -147,12 +143,15 @@ impl Timespec {
             //
             // Ideally this code could be rearranged such that it more
             // directly expresses the lower-cost behavior we want from it.
-            let (secs, nsec) = if self.tv_nsec.0 >= other.tv_nsec.0 {
-                ((self.tv_sec - other.tv_sec) as u64, self.tv_nsec.0 - other.tv_nsec.0)
+            let (secs, nsec) = if self.tv_nsec.as_inner() >= other.tv_nsec.as_inner() {
+                (
+                    (self.tv_sec - other.tv_sec) as u64,
+                    self.tv_nsec.as_inner() - other.tv_nsec.as_inner(),
+                )
             } else {
                 (
                     (self.tv_sec - other.tv_sec - 1) as u64,
-                    self.tv_nsec.0 + (NSEC_PER_SEC as u32) - other.tv_nsec.0,
+                    self.tv_nsec.as_inner() + (NSEC_PER_SEC as u32) - other.tv_nsec.as_inner(),
                 )
             };
 
@@ -170,7 +169,7 @@ impl Timespec {
 
         // Nano calculations can't overflow because nanos are <1B which fit
         // in a u32.
-        let mut nsec = other.subsec_nanos() + self.tv_nsec.0;
+        let mut nsec = other.subsec_nanos() + self.tv_nsec.as_inner();
         if nsec >= NSEC_PER_SEC as u32 {
             nsec -= NSEC_PER_SEC as u32;
             secs = secs.checked_add(1)?;
@@ -182,7 +181,7 @@ impl Timespec {
         let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?;
 
         // Similar to above, nanos can't overflow.
-        let mut nsec = self.tv_nsec.0 as i32 - other.subsec_nanos() as i32;
+        let mut nsec = self.tv_nsec.as_inner() as i32 - other.subsec_nanos() as i32;
         if nsec < 0 {
             nsec += NSEC_PER_SEC as i32;
             secs = secs.checked_sub(1)?;
@@ -194,7 +193,7 @@ impl Timespec {
     pub fn to_timespec(&self) -> Option<libc::timespec> {
         Some(libc::timespec {
             tv_sec: self.tv_sec.try_into().ok()?,
-            tv_nsec: self.tv_nsec.0.try_into().ok()?,
+            tv_nsec: self.tv_nsec.as_inner().try_into().ok()?,
         })
     }
 
@@ -203,7 +202,7 @@ impl Timespec {
     #[cfg(target_os = "nto")]
     pub(in crate::sys) fn to_timespec_capped(&self) -> Option<libc::timespec> {
         // Check if timeout in nanoseconds would fit into an u64
-        if (self.tv_nsec.0 as u64)
+        if (self.tv_nsec.as_inner() as u64)
             .checked_add((self.tv_sec as u64).checked_mul(NSEC_PER_SEC)?)
             .is_none()
         {
@@ -219,7 +218,7 @@ impl Timespec {
         not(target_arch = "riscv32")
     ))]
     pub fn to_timespec64(&self) -> __timespec64 {
-        __timespec64::new(self.tv_sec, self.tv_nsec.0 as _)
+        __timespec64::new(self.tv_sec, self.tv_nsec.as_inner() as _)
     }
 }
 
@@ -293,7 +292,7 @@ impl fmt::Debug for Instant {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Instant")
             .field("tv_sec", &self.t.tv_sec)
-            .field("tv_nsec", &self.t.tv_nsec.0)
+            .field("tv_nsec", &self.t.tv_nsec)
             .finish()
     }
 }
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index 88e6def7a75..4282dbb5493 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -272,7 +272,7 @@ where
                 unreachable!();
             } else {
                 // Safety: First `k` values are initialized.
-                let slice: &[u16] = MaybeUninit::slice_assume_init_ref(&buf[..k]);
+                let slice: &[u16] = buf[..k].assume_init_ref();
                 return Ok(f2(slice));
             }
         }
diff --git a/library/std/src/sys/pal/windows/stack_overflow.rs b/library/std/src/sys/pal/windows/stack_overflow.rs
index 467e21ab56a..734cd30bed0 100644
--- a/library/std/src/sys/pal/windows/stack_overflow.rs
+++ b/library/std/src/sys/pal/windows/stack_overflow.rs
@@ -18,10 +18,10 @@ unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POIN
         let code = rec.ExceptionCode;
 
         if code == c::EXCEPTION_STACK_OVERFLOW {
-            rtprintpanic!(
-                "\nthread '{}' has overflowed its stack\n",
-                thread::current().name().unwrap_or("<unknown>")
-            );
+            thread::with_current_name(|name| {
+                let name = name.unwrap_or("<unknown>");
+                rtprintpanic!("\nthread '{name}' has overflowed its stack\n");
+            });
         }
         c::EXCEPTION_CONTINUE_SEARCH
     }
diff --git a/library/std/src/sys/pal/windows/stdio.rs b/library/std/src/sys/pal/windows/stdio.rs
index 1b735e7f0cb..fd3f559ba19 100644
--- a/library/std/src/sys/pal/windows/stdio.rs
+++ b/library/std/src/sys/pal/windows/stdio.rs
@@ -207,7 +207,7 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usiz
         assert!(result != 0, "Unexpected error in MultiByteToWideChar");
 
         // Safety: MultiByteToWideChar initializes `result` values.
-        MaybeUninit::slice_assume_init_ref(&utf16[..result as usize])
+        utf16[..result as usize].assume_init_ref()
     };
 
     let mut written = write_u16s(handle, utf16)?;
@@ -283,7 +283,7 @@ impl io::Read for Stdin {
             let read = read_u16s_fixup_surrogates(handle, &mut utf16_buf, 1, &mut self.surrogate)?;
             // Read bytes, using the (now-empty) self.incomplete_utf8 as extra space.
             let read_bytes = utf16_to_utf8(
-                unsafe { MaybeUninit::slice_assume_init_ref(&utf16_buf[..read]) },
+                unsafe { utf16_buf[..read].assume_init_ref() },
                 &mut self.incomplete_utf8.bytes,
             )?;
 
@@ -303,7 +303,7 @@ impl io::Read for Stdin {
                 read_u16s_fixup_surrogates(handle, &mut utf16_buf, amount, &mut self.surrogate)?;
             // Safety `read_u16s_fixup_surrogates` returns the number of items
             // initialized.
-            let utf16s = unsafe { MaybeUninit::slice_assume_init_ref(&utf16_buf[..read]) };
+            let utf16s = unsafe { utf16_buf[..read].assume_init_ref() };
             match utf16_to_utf8(utf16s, buf) {
                 Ok(value) => return Ok(bytes_copied + value),
                 Err(e) => return Err(e),
diff --git a/library/std/src/sys/path/sgx.rs b/library/std/src/sys/path/sgx.rs
index c805c15e702..32c7752f605 100644
--- a/library/std/src/sys/path/sgx.rs
+++ b/library/std/src/sys/path/sgx.rs
@@ -23,3 +23,7 @@ pub const MAIN_SEP: char = '/';
 pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> {
     unsupported()
 }
+
+pub(crate) fn is_absolute(path: &Path) -> bool {
+    path.has_root() && path.prefix().is_some()
+}
diff --git a/library/std/src/sys/path/unix.rs b/library/std/src/sys/path/unix.rs
index 2a7c025c3c4..361e99964f1 100644
--- a/library/std/src/sys/path/unix.rs
+++ b/library/std/src/sys/path/unix.rs
@@ -60,3 +60,14 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
 
     Ok(normalized)
 }
+
+pub(crate) fn is_absolute(path: &Path) -> bool {
+    if cfg!(target_os = "redox") {
+        // FIXME: Allow Redox prefixes
+        path.has_root() || crate::path::has_redox_scheme(path.as_u8_slice())
+    } else if cfg!(any(unix, target_os = "hermit", target_os = "wasi")) {
+        path.has_root()
+    } else {
+        path.has_root() && path.prefix().is_some()
+    }
+}
diff --git a/library/std/src/sys/path/unsupported_backslash.rs b/library/std/src/sys/path/unsupported_backslash.rs
index 855f443678c..30b06c132c9 100644
--- a/library/std/src/sys/path/unsupported_backslash.rs
+++ b/library/std/src/sys/path/unsupported_backslash.rs
@@ -24,3 +24,7 @@ pub const MAIN_SEP: char = '\\';
 pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> {
     unsupported()
 }
+
+pub(crate) fn is_absolute(path: &Path) -> bool {
+    path.has_root() && path.prefix().is_some()
+}
diff --git a/library/std/src/sys/path/windows.rs b/library/std/src/sys/path/windows.rs
index de042fa3f82..1c534721916 100644
--- a/library/std/src/sys/path/windows.rs
+++ b/library/std/src/sys/path/windows.rs
@@ -346,3 +346,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
         os2path,
     )
 }
+
+pub(crate) fn is_absolute(path: &Path) -> bool {
+    path.has_root() && path.prefix().is_some()
+}
diff --git a/library/std/src/thread/current.rs b/library/std/src/thread/current.rs
index 3d2c288b360..414711298f0 100644
--- a/library/std/src/thread/current.rs
+++ b/library/std/src/thread/current.rs
@@ -15,7 +15,7 @@ local_pointer! {
 ///
 /// We store the thread ID so that it never gets destroyed during the lifetime
 /// of a thread, either using `#[thread_local]` or multiple `local_pointer!`s.
-mod id {
+pub(super) mod id {
     use super::*;
 
     cfg_if::cfg_if! {
@@ -27,7 +27,7 @@ mod id {
 
             pub(super) const CHEAP: bool = true;
 
-            pub(super) fn get() -> Option<ThreadId> {
+            pub(crate) fn get() -> Option<ThreadId> {
                 ID.get()
             }
 
@@ -44,7 +44,7 @@ mod id {
 
             pub(super) const CHEAP: bool = false;
 
-            pub(super) fn get() -> Option<ThreadId> {
+            pub(crate) fn get() -> Option<ThreadId> {
                 let id0 = ID0.get().addr() as u64;
                 let id16 = ID16.get().addr() as u64;
                 let id32 = ID32.get().addr() as u64;
@@ -67,7 +67,7 @@ mod id {
 
             pub(super) const CHEAP: bool = false;
 
-            pub(super) fn get() -> Option<ThreadId> {
+            pub(crate) fn get() -> Option<ThreadId> {
                 let id0 = ID0.get().addr() as u64;
                 let id32 = ID32.get().addr() as u64;
                 ThreadId::from_u64((id32 << 32) + id0)
@@ -85,7 +85,7 @@ mod id {
 
             pub(super) const CHEAP: bool = true;
 
-            pub(super) fn get() -> Option<ThreadId> {
+            pub(crate) fn get() -> Option<ThreadId> {
                 let id = ID.get().addr() as u64;
                 ThreadId::from_u64(id)
             }
@@ -112,7 +112,7 @@ mod id {
 
 /// Tries to set the thread handle for the current thread. Fails if a handle was
 /// already set or if the thread ID of `thread` would change an already-set ID.
-pub(crate) fn set_current(thread: Thread) -> Result<(), Thread> {
+pub(super) fn set_current(thread: Thread) -> Result<(), Thread> {
     if CURRENT.get() != NONE {
         return Err(thread);
     }
@@ -140,28 +140,31 @@ pub(crate) fn current_id() -> ThreadId {
     // to retrieve it from the current thread handle, which will only take one
     // TLS access.
     if !id::CHEAP {
-        let current = CURRENT.get();
-        if current > DESTROYED {
-            unsafe {
-                let current = ManuallyDrop::new(Thread::from_raw(current));
-                return current.id();
-            }
+        if let Some(id) = try_with_current(|t| t.map(|t| t.id())) {
+            return id;
         }
     }
 
     id::get_or_init()
 }
 
-/// Gets a handle to the thread that invokes it, if the handle has been initialized.
-pub(crate) fn try_current() -> Option<Thread> {
+/// Gets a reference to the handle of the thread that invokes it, if the handle
+/// has been initialized.
+pub(super) fn try_with_current<F, R>(f: F) -> R
+where
+    F: FnOnce(Option<&Thread>) -> R,
+{
     let current = CURRENT.get();
     if current > DESTROYED {
+        // SAFETY: `Arc` does not contain interior mutability, so it does not
+        // matter that the address of the handle might be different depending
+        // on where this is called.
         unsafe {
             let current = ManuallyDrop::new(Thread::from_raw(current));
-            Some((*current).clone())
+            f(Some(&current))
         }
     } else {
-        None
+        f(None)
     }
 }
 
@@ -176,7 +179,7 @@ pub(crate) fn current_or_unnamed() -> Thread {
             (*current).clone()
         }
     } else if current == DESTROYED {
-        Thread::new_unnamed(id::get_or_init())
+        Thread::new(id::get_or_init(), None)
     } else {
         init_current(current)
     }
@@ -221,7 +224,7 @@ fn init_current(current: *mut ()) -> Thread {
         CURRENT.set(BUSY);
         // If the thread ID was initialized already, use it.
         let id = id::get_or_init();
-        let thread = Thread::new_unnamed(id);
+        let thread = Thread::new(id, None);
 
         // Make sure that `crate::rt::thread_cleanup` will be run, which will
         // call `drop_current`.
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 85ee369ca2b..59b395336f2 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -158,12 +158,9 @@
 #[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
 mod tests;
 
-use core::cell::SyncUnsafeCell;
-use core::ffi::CStr;
-use core::mem::MaybeUninit;
-
 use crate::any::Any;
 use crate::cell::UnsafeCell;
+use crate::ffi::CStr;
 use crate::marker::PhantomData;
 use crate::mem::{self, ManuallyDrop, forget};
 use crate::num::NonZero;
@@ -186,7 +183,8 @@ mod current;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use current::current;
-pub(crate) use current::{current_id, current_or_unnamed, drop_current, set_current, try_current};
+pub(crate) use current::{current_id, current_or_unnamed, drop_current};
+use current::{set_current, try_with_current};
 
 mod spawnhook;
 
@@ -501,10 +499,7 @@ impl Builder {
         });
 
         let id = ThreadId::new();
-        let my_thread = match name {
-            Some(name) => Thread::new(id, name.into()),
-            None => Thread::new_unnamed(id),
-        };
+        let my_thread = Thread::new(id, name);
 
         let hooks = if no_hooks {
             spawnhook::ChildSpawnHooks::default()
@@ -1235,7 +1230,7 @@ impl ThreadId {
         }
     }
 
-    #[cfg(not(target_thread_local))]
+    #[cfg(any(not(target_thread_local), target_has_atomic = "64"))]
     fn from_u64(v: u64) -> Option<ThreadId> {
         NonZero::new(v).map(ThreadId)
     }
@@ -1261,29 +1256,14 @@ impl ThreadId {
 
 // This module ensures private fields are kept private, which is necessary to enforce the safety requirements.
 mod thread_name_string {
-    use core::str;
-
     use crate::ffi::{CStr, CString};
+    use crate::str;
 
     /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated.
     pub(crate) struct ThreadNameString {
         inner: CString,
     }
 
-    impl ThreadNameString {
-        pub fn as_str(&self) -> &str {
-            // SAFETY: `self.inner` is only initialised via `String`, which upholds the validity invariant of `str`.
-            unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) }
-        }
-    }
-
-    impl core::ops::Deref for ThreadNameString {
-        type Target = CStr;
-        fn deref(&self) -> &CStr {
-            &self.inner
-        }
-    }
-
     impl From<String> for ThreadNameString {
         fn from(s: String) -> Self {
             Self {
@@ -1291,82 +1271,124 @@ mod thread_name_string {
             }
         }
     }
-}
-pub(crate) use thread_name_string::ThreadNameString;
-
-static MAIN_THREAD_INFO: SyncUnsafeCell<(MaybeUninit<ThreadId>, MaybeUninit<Parker>)> =
-    SyncUnsafeCell::new((MaybeUninit::uninit(), MaybeUninit::uninit()));
-
-/// The internal representation of a `Thread` that is not the main thread.
-struct OtherInner {
-    name: Option<ThreadNameString>,
-    id: ThreadId,
-    parker: Parker,
-}
-
-/// The internal representation of a `Thread` handle.
-#[derive(Clone)]
-enum Inner {
-    /// Represents the main thread. May only be constructed by Thread::new_main.
-    Main(&'static (ThreadId, Parker)),
-    /// Represents any other thread.
-    Other(Pin<Arc<OtherInner>>),
-}
-
-impl Inner {
-    fn id(&self) -> ThreadId {
-        match self {
-            Self::Main((thread_id, _)) => *thread_id,
-            Self::Other(other) => other.id,
-        }
-    }
 
-    fn cname(&self) -> Option<&CStr> {
-        match self {
-            Self::Main(_) => Some(c"main"),
-            Self::Other(other) => other.name.as_deref(),
+    impl ThreadNameString {
+        pub fn as_cstr(&self) -> &CStr {
+            &self.inner
         }
-    }
 
-    fn name(&self) -> Option<&str> {
-        match self {
-            Self::Main(_) => Some("main"),
-            Self::Other(other) => other.name.as_ref().map(ThreadNameString::as_str),
+        pub fn as_str(&self) -> &str {
+            // SAFETY: `ThreadNameString` is guaranteed to be UTF-8.
+            unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) }
         }
     }
+}
 
-    fn into_raw(self) -> *const () {
-        match self {
-            // Just return the pointer to `MAIN_THREAD_INFO`.
-            Self::Main(ptr) => crate::ptr::from_ref(ptr).cast(),
-            Self::Other(arc) => {
-                // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant.
-                let inner = unsafe { Pin::into_inner_unchecked(arc) };
-                Arc::into_raw(inner) as *const ()
+use thread_name_string::ThreadNameString;
+
+/// Store the ID of the main thread.
+///
+/// The thread handle for the main thread is created lazily, and this might even
+/// happen pre-main. Since not every platform has a way to identify the main
+/// thread when that happens – macOS's `pthread_main_np` function being a notable
+/// exception – we cannot assign it the right name right then. Instead, in our
+/// runtime startup code, we remember the thread ID of the main thread (through
+/// this modules `set` function) and use it to identify the main thread from then
+/// on. This works reliably and has the additional advantage that we can report
+/// the right thread name on main even after the thread handle has been destroyed.
+/// Note however that this also means that the name reported in pre-main functions
+/// will be incorrect, but that's just something we have to live with.
+pub(crate) mod main_thread {
+    cfg_if::cfg_if! {
+        if #[cfg(target_has_atomic = "64")] {
+            use super::ThreadId;
+            use crate::sync::atomic::AtomicU64;
+            use crate::sync::atomic::Ordering::Relaxed;
+
+            static MAIN: AtomicU64 = AtomicU64::new(0);
+
+            pub(super) fn get() -> Option<ThreadId> {
+                ThreadId::from_u64(MAIN.load(Relaxed))
             }
-        }
-    }
 
-    /// # Safety
-    ///
-    /// See [`Thread::from_raw`].
-    unsafe fn from_raw(ptr: *const ()) -> Self {
-        // If the pointer is to `MAIN_THREAD_INFO`, we know it is the `Main` variant.
-        if crate::ptr::eq(ptr.cast(), &MAIN_THREAD_INFO) {
-            Self::Main(unsafe { &*ptr.cast() })
+            /// # Safety
+            /// May only be called once.
+            pub(crate) unsafe fn set(id: ThreadId) {
+                MAIN.store(id.as_u64().get(), Relaxed)
+            }
         } else {
-            // Safety: Upheld by caller
-            Self::Other(unsafe { Pin::new_unchecked(Arc::from_raw(ptr as *const OtherInner)) })
+            use super::ThreadId;
+            use crate::mem::MaybeUninit;
+            use crate::sync::atomic::AtomicBool;
+            use crate::sync::atomic::Ordering::{Acquire, Release};
+
+            static INIT: AtomicBool = AtomicBool::new(false);
+            static mut MAIN: MaybeUninit<ThreadId> = MaybeUninit::uninit();
+
+            pub(super) fn get() -> Option<ThreadId> {
+                if INIT.load(Acquire) {
+                    Some(unsafe { MAIN.assume_init() })
+                } else {
+                    None
+                }
+            }
+
+            /// # Safety
+            /// May only be called once.
+            pub(crate) unsafe fn set(id: ThreadId) {
+                unsafe { MAIN = MaybeUninit::new(id) };
+                INIT.store(true, Release);
+            }
         }
     }
+}
 
-    fn parker(&self) -> Pin<&Parker> {
-        match self {
-            Self::Main((_, parker_ref)) => Pin::static_ref(parker_ref),
-            Self::Other(inner) => unsafe {
-                Pin::map_unchecked(inner.as_ref(), |inner| &inner.parker)
-            },
+/// Run a function with the current thread's name.
+///
+/// Modulo thread local accesses, this function is safe to call from signal
+/// handlers and in similar circumstances where allocations are not possible.
+pub(crate) fn with_current_name<F, R>(f: F) -> R
+where
+    F: FnOnce(Option<&str>) -> R,
+{
+    try_with_current(|thread| {
+        if let Some(thread) = thread {
+            // If there is a current thread handle, try to use the name stored
+            // there.
+            if let Some(name) = &thread.inner.name {
+                return f(Some(name.as_str()));
+            } else if Some(thread.inner.id) == main_thread::get() {
+                // The main thread doesn't store its name in the handle, we must
+                // identify it through its ID. Since we already have the `Thread`,
+                // we can retrieve the ID from it instead of going through another
+                // thread local.
+                return f(Some("main"));
+            }
+        } else if let Some(main) = main_thread::get()
+            && let Some(id) = current::id::get()
+            && id == main
+        {
+            // The main thread doesn't always have a thread handle, we must
+            // identify it through its ID instead. The checks are ordered so
+            // that the current ID is only loaded if it is actually needed,
+            // since loading it from TLS might need multiple expensive accesses.
+            return f(Some("main"));
         }
+
+        f(None)
+    })
+}
+
+/// The internal representation of a `Thread` handle
+struct Inner {
+    name: Option<ThreadNameString>,
+    id: ThreadId,
+    parker: Parker,
+}
+
+impl Inner {
+    fn parker(self: Pin<&Self>) -> Pin<&Parker> {
+        unsafe { Pin::map_unchecked(self, |inner| &inner.parker) }
     }
 }
 
@@ -1390,47 +1412,21 @@ impl Inner {
 /// docs of [`Builder`] and [`spawn`] for more details.
 ///
 /// [`thread::current`]: current::current
-pub struct Thread(Inner);
+pub struct Thread {
+    inner: Pin<Arc<Inner>>,
+}
 
 impl Thread {
-    /// Used only internally to construct a thread object without spawning.
-    pub(crate) fn new(id: ThreadId, name: String) -> Thread {
-        Self::new_inner(id, Some(ThreadNameString::from(name)))
-    }
+    pub(crate) fn new(id: ThreadId, name: Option<String>) -> Thread {
+        let name = name.map(ThreadNameString::from);
 
-    pub(crate) fn new_unnamed(id: ThreadId) -> Thread {
-        Self::new_inner(id, None)
-    }
-
-    /// Used in runtime to construct main thread
-    ///
-    /// # Safety
-    ///
-    /// This must only ever be called once, and must be called on the main thread.
-    pub(crate) unsafe fn new_main(thread_id: ThreadId) -> Thread {
-        // Safety: As this is only called once and on the main thread, nothing else is accessing MAIN_THREAD_INFO
-        // as the only other read occurs in `main_thread_info` *after* the main thread has been constructed,
-        // and this function is the only one that constructs the main thread.
-        //
-        // Pre-main thread spawning cannot hit this either, as the caller promises that this is only called on the main thread.
-        let main_thread_info = unsafe { &mut *MAIN_THREAD_INFO.get() };
-
-        unsafe { Parker::new_in_place((&raw mut main_thread_info.1).cast()) };
-        main_thread_info.0.write(thread_id);
-
-        // Store a `'static` ref to the initialised ThreadId and Parker,
-        // to avoid having to repeatedly prove initialisation.
-        Self(Inner::Main(unsafe { &*MAIN_THREAD_INFO.get().cast() }))
-    }
-
-    fn new_inner(id: ThreadId, name: Option<ThreadNameString>) -> Thread {
         // We have to use `unsafe` here to construct the `Parker` in-place,
         // which is required for the UNIX implementation.
         //
         // SAFETY: We pin the Arc immediately after creation, so its address never
         // changes.
         let inner = unsafe {
-            let mut arc = Arc::<OtherInner>::new_uninit();
+            let mut arc = Arc::<Inner>::new_uninit();
             let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr();
             (&raw mut (*ptr).name).write(name);
             (&raw mut (*ptr).id).write(id);
@@ -1438,7 +1434,7 @@ impl Thread {
             Pin::new_unchecked(arc.assume_init())
         };
 
-        Self(Inner::Other(inner))
+        Thread { inner }
     }
 
     /// Like the public [`park`], but callable on any handle. This is used to
@@ -1447,7 +1443,7 @@ impl Thread {
     /// # Safety
     /// May only be called from the thread to which this handle belongs.
     pub(crate) unsafe fn park(&self) {
-        unsafe { self.0.parker().park() }
+        unsafe { self.inner.as_ref().parker().park() }
     }
 
     /// Like the public [`park_timeout`], but callable on any handle. This is
@@ -1456,7 +1452,7 @@ impl Thread {
     /// # Safety
     /// May only be called from the thread to which this handle belongs.
     pub(crate) unsafe fn park_timeout(&self, dur: Duration) {
-        unsafe { self.0.parker().park_timeout(dur) }
+        unsafe { self.inner.as_ref().parker().park_timeout(dur) }
     }
 
     /// Atomically makes the handle's token available if it is not already.
@@ -1492,7 +1488,7 @@ impl Thread {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn unpark(&self) {
-        self.0.parker().unpark();
+        self.inner.as_ref().parker().unpark();
     }
 
     /// Gets the thread's unique identifier.
@@ -1512,7 +1508,7 @@ impl Thread {
     #[stable(feature = "thread_id", since = "1.19.0")]
     #[must_use]
     pub fn id(&self) -> ThreadId {
-        self.0.id()
+        self.inner.id
     }
 
     /// Gets the thread's name.
@@ -1555,11 +1551,13 @@ impl Thread {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     pub fn name(&self) -> Option<&str> {
-        self.0.name()
-    }
-
-    fn cname(&self) -> Option<&CStr> {
-        self.0.cname()
+        if let Some(name) = &self.inner.name {
+            Some(name.as_str())
+        } else if main_thread::get() == Some(self.inner.id) {
+            Some("main")
+        } else {
+            None
+        }
     }
 
     /// Consumes the `Thread`, returning a raw pointer.
@@ -1583,7 +1581,9 @@ impl Thread {
     /// ```
     #[unstable(feature = "thread_raw", issue = "97523")]
     pub fn into_raw(self) -> *const () {
-        self.0.into_raw()
+        // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant.
+        let inner = unsafe { Pin::into_inner_unchecked(self.inner) };
+        Arc::into_raw(inner) as *const ()
     }
 
     /// Constructs a `Thread` from a raw pointer.
@@ -1605,7 +1605,17 @@ impl Thread {
     #[unstable(feature = "thread_raw", issue = "97523")]
     pub unsafe fn from_raw(ptr: *const ()) -> Thread {
         // Safety: Upheld by caller.
-        unsafe { Thread(Inner::from_raw(ptr)) }
+        unsafe { Thread { inner: Pin::new_unchecked(Arc::from_raw(ptr as *const Inner)) } }
+    }
+
+    fn cname(&self) -> Option<&CStr> {
+        if let Some(name) = &self.inner.name {
+            Some(name.as_cstr())
+        } else if main_thread::get() == Some(self.inner.id) {
+            Some(c"main")
+        } else {
+            None
+        }
     }
 }