about summary refs log tree commit diff
path: root/library/std
diff options
context:
space:
mode:
Diffstat (limited to 'library/std')
-rw-r--r--library/std/Cargo.toml14
-rw-r--r--library/std/src/env.rs13
-rw-r--r--library/std/src/env/tests.rs20
-rw-r--r--library/std/src/error.rs13
-rw-r--r--library/std/src/error/tests.rs4
-rw-r--r--library/std/src/f32.rs42
-rw-r--r--library/std/src/f32/tests.rs32
-rw-r--r--library/std/src/f64.rs42
-rw-r--r--library/std/src/f64/tests.rs32
-rw-r--r--library/std/src/ffi/os_str.rs8
-rw-r--r--library/std/src/fs.rs3
-rw-r--r--library/std/src/io/mod.rs6
-rw-r--r--library/std/src/io/readbuf.rs1
-rw-r--r--library/std/src/lib.rs13
-rw-r--r--library/std/src/net/tcp.rs2
-rw-r--r--library/std/src/os/l4re/raw.rs1
-rw-r--r--library/std/src/os/linux/raw.rs1
-rw-r--r--library/std/src/os/unix/net/stream.rs1
-rw-r--r--library/std/src/path.rs16
-rw-r--r--library/std/src/process.rs11
-rw-r--r--library/std/src/sync/barrier.rs7
-rw-r--r--library/std/src/sync/mpsc/mod.rs5
-rw-r--r--library/std/src/sys/common/alloc.rs1
-rw-r--r--library/std/src/sys/hermit/fs.rs1
-rw-r--r--library/std/src/sys/hermit/os.rs28
-rw-r--r--library/std/src/sys/personality/gcc.rs3
-rw-r--r--library/std/src/sys/sgx/os.rs51
-rw-r--r--library/std/src/sys/solid/os.rs28
-rw-r--r--library/std/src/sys/unix/cmath.rs4
-rw-r--r--library/std/src/sys/unix/fs.rs1
-rw-r--r--library/std/src/sys/unix/os.rs28
-rw-r--r--library/std/src/sys/unix/process/process_fuchsia.rs2
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs223
-rw-r--r--library/std/src/sys/unix/process/process_unix/tests.rs25
-rw-r--r--library/std/src/sys/unix/process/process_unsupported.rs2
-rw-r--r--library/std/src/sys/unix/process/process_vxworks.rs2
-rw-r--r--library/std/src/sys/unix/stdio.rs2
-rw-r--r--library/std/src/sys/unsupported/os.rs18
-rw-r--r--library/std/src/sys/unsupported/process.rs37
-rw-r--r--library/std/src/sys/wasi/fd.rs10
-rw-r--r--library/std/src/sys/wasi/os.rs29
-rw-r--r--library/std/src/sys/wasi/thread.rs6
-rw-r--r--library/std/src/sys/windows/cmath.rs6
-rw-r--r--library/std/src/sys/windows/os.rs54
-rw-r--r--library/std/src/sys/windows/process.rs2
-rw-r--r--library/std/src/sys_common/wtf8.rs2
-rw-r--r--library/std/src/thread/local.rs27
47 files changed, 687 insertions, 192 deletions
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index ddcd35b1ac7..33c9c6e63c1 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -18,21 +18,19 @@ panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
 libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'], public = true }
-compiler_builtins = { version = "0.1.98" }
+compiler_builtins = { version = "0.1.100" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] }
 std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] }
 
 # Dependencies of the `backtrace` crate
-addr2line = { version = "0.20.0", optional = true, default-features = false }
 rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] }
-miniz_oxide = { version = "0.7.0", optional = true, default-features = false, public = false }
-[dependencies.object]
-version = "0.31.1"
-optional = true
-default-features = false
-features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
+
+[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies]
+miniz_oxide = { version = "0.7.0", optional = true, default-features = false }
+addr2line = { version = "0.21.0", optional = true, default-features = false }
+object = { version = "0.32.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] }
 
 [dev-dependencies]
 rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index d372fa64065..f67f6034d34 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -178,7 +178,8 @@ impl Iterator for Vars {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Vars {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Vars").finish_non_exhaustive()
+        let Self { inner: VarsOs { inner } } = self;
+        f.debug_struct("Vars").field("inner", &inner.str_debug()).finish()
     }
 }
 
@@ -196,7 +197,8 @@ impl Iterator for VarsOs {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for VarsOs {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("VarOs").finish_non_exhaustive()
+        let Self { inner } = self;
+        f.debug_struct("VarsOs").field("inner", inner).finish()
     }
 }
 
@@ -829,7 +831,8 @@ impl DoubleEndedIterator for Args {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Args {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Args").field("inner", &self.inner.inner).finish()
+        let Self { inner: ArgsOs { inner } } = self;
+        f.debug_struct("Args").field("inner", inner).finish()
     }
 }
 
@@ -870,7 +873,8 @@ impl DoubleEndedIterator for ArgsOs {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ArgsOs {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("ArgsOs").field("inner", &self.inner).finish()
+        let Self { inner } = self;
+        f.debug_struct("ArgsOs").field("inner", inner).finish()
     }
 }
 
@@ -890,6 +894,7 @@ pub mod consts {
     /// - aarch64
     /// - loongarch64
     /// - m68k
+    /// - csky
     /// - mips
     /// - mips64
     /// - powerpc
diff --git a/library/std/src/env/tests.rs b/library/std/src/env/tests.rs
index 94cace03af6..55869229581 100644
--- a/library/std/src/env/tests.rs
+++ b/library/std/src/env/tests.rs
@@ -95,8 +95,28 @@ fn args_debug() {
         format!("Args {{ inner: {:?} }}", args().collect::<Vec<_>>()),
         format!("{:?}", args())
     );
+}
+
+#[test]
+fn args_os_debug() {
     assert_eq!(
         format!("ArgsOs {{ inner: {:?} }}", args_os().collect::<Vec<_>>()),
         format!("{:?}", args_os())
     );
 }
+
+#[test]
+fn vars_debug() {
+    assert_eq!(
+        format!("Vars {{ inner: {:?} }}", vars().collect::<Vec<_>>()),
+        format!("{:?}", vars())
+    );
+}
+
+#[test]
+fn vars_os_debug() {
+    assert_eq!(
+        format!("VarsOs {{ inner: {:?} }}", vars_os().collect::<Vec<_>>()),
+        format!("{:?}", vars_os())
+    );
+}
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index ee5eddebfaf..7bc3af1793e 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -9,6 +9,8 @@ use crate::fmt::{self, Write};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::error::Error;
+#[unstable(feature = "error_generic_member_access", issue = "99301")]
+pub use core::error::{request_ref, Request};
 
 mod private {
     // This is a hack to prevent `type_id` from being overridden by `Error`
@@ -371,11 +373,10 @@ impl<E> Report<E> {
     ///
     /// ```rust
     /// #![feature(error_reporter)]
-    /// #![feature(provide_any)]
     /// #![feature(error_generic_member_access)]
     /// # use std::error::Error;
     /// # use std::fmt;
-    /// use std::any::Demand;
+    /// use std::error::Request;
     /// use std::error::Report;
     /// use std::backtrace::Backtrace;
     ///
@@ -405,8 +406,8 @@ impl<E> Report<E> {
     /// }
     ///
     /// impl Error for SuperErrorSideKick {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         demand.provide_ref::<Backtrace>(&self.backtrace);
+    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+    ///         request.provide_ref::<Backtrace>(&self.backtrace);
     ///     }
     /// }
     ///
@@ -459,11 +460,11 @@ where
     fn backtrace(&self) -> Option<&Backtrace> {
         // have to grab the backtrace on the first error directly since that error may not be
         // 'static
-        let backtrace = (&self.error as &dyn Error).request_ref();
+        let backtrace = request_ref(&self.error);
         let backtrace = backtrace.or_else(|| {
             self.error
                 .source()
-                .map(|source| source.sources().find_map(|source| source.request_ref()))
+                .map(|source| source.sources().find_map(|source| request_ref(source)))
                 .flatten()
         });
         backtrace
diff --git a/library/std/src/error/tests.rs b/library/std/src/error/tests.rs
index ee999bd65c3..ed070a26b0c 100644
--- a/library/std/src/error/tests.rs
+++ b/library/std/src/error/tests.rs
@@ -1,6 +1,6 @@
 use super::Error;
 use crate::fmt;
-use core::any::Demand;
+use core::error::Request;
 
 #[derive(Debug, PartialEq)]
 struct A;
@@ -199,7 +199,7 @@ where
         self.source.as_deref()
     }
 
-    fn provide<'a>(&'a self, req: &mut Demand<'a>) {
+    fn provide<'a>(&'a self, req: &mut Request<'a>) {
         self.backtrace.as_ref().map(|bt| req.provide_ref::<Backtrace>(bt));
     }
 }
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index bc532990e94..a53b8535213 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -957,4 +957,46 @@ impl f32 {
     pub fn atanh(self) -> f32 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
+
+    /// Gamma function.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(float_gamma)]
+    /// let x = 5.0f32;
+    ///
+    /// let abs_difference = (x.gamma() - 24.0).abs();
+    ///
+    /// assert!(abs_difference <= f32::EPSILON);
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "float_gamma", issue = "99842")]
+    #[inline]
+    pub fn gamma(self) -> f32 {
+        unsafe { cmath::tgammaf(self) }
+    }
+
+    /// Returns the natural logarithm of the gamma function.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(float_gamma)]
+    /// let x = 2.0f32;
+    ///
+    /// let abs_difference = (x.ln_gamma().0 - 0.0).abs();
+    ///
+    /// assert!(abs_difference <= f32::EPSILON);
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "float_gamma", issue = "99842")]
+    #[inline]
+    pub fn ln_gamma(self) -> (f32, i32) {
+        let mut signgamp: i32 = 0;
+        let x = unsafe { cmath::lgammaf_r(self, &mut signgamp) };
+        (x, signgamp)
+    }
 }
diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs
index e949def00bb..9ca4e8f2f45 100644
--- a/library/std/src/f32/tests.rs
+++ b/library/std/src/f32/tests.rs
@@ -653,6 +653,38 @@ fn test_atanh() {
 }
 
 #[test]
+fn test_gamma() {
+    // precision can differ between platforms
+    assert_approx_eq!(1.0f32.gamma(), 1.0f32);
+    assert_approx_eq!(2.0f32.gamma(), 1.0f32);
+    assert_approx_eq!(3.0f32.gamma(), 2.0f32);
+    assert_approx_eq!(4.0f32.gamma(), 6.0f32);
+    assert_approx_eq!(5.0f32.gamma(), 24.0f32);
+    assert_approx_eq!(0.5f32.gamma(), consts::PI.sqrt());
+    assert_approx_eq!((-0.5f32).gamma(), -2.0 * consts::PI.sqrt());
+    assert_eq!(0.0f32.gamma(), f32::INFINITY);
+    assert_eq!((-0.0f32).gamma(), f32::NEG_INFINITY);
+    assert!((-1.0f32).gamma().is_nan());
+    assert!((-2.0f32).gamma().is_nan());
+    assert!(f32::NAN.gamma().is_nan());
+    assert!(f32::NEG_INFINITY.gamma().is_nan());
+    assert_eq!(f32::INFINITY.gamma(), f32::INFINITY);
+    assert_eq!(171.71f32.gamma(), f32::INFINITY);
+}
+
+#[test]
+fn test_ln_gamma() {
+    assert_approx_eq!(1.0f32.ln_gamma().0, 0.0f32);
+    assert_eq!(1.0f32.ln_gamma().1, 1);
+    assert_approx_eq!(2.0f32.ln_gamma().0, 0.0f32);
+    assert_eq!(2.0f32.ln_gamma().1, 1);
+    assert_approx_eq!(3.0f32.ln_gamma().0, 2.0f32.ln());
+    assert_eq!(3.0f32.ln_gamma().1, 1);
+    assert_approx_eq!((-0.5f32).ln_gamma().0, (2.0 * consts::PI.sqrt()).ln());
+    assert_eq!((-0.5f32).ln_gamma().1, -1);
+}
+
+#[test]
 fn test_real_consts() {
     use super::consts;
 
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 5af9f8bcb23..a1cec22c97a 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -957,4 +957,46 @@ impl f64 {
     pub fn atanh(self) -> f64 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
+
+    /// Gamma function.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(float_gamma)]
+    /// let x = 5.0f64;
+    ///
+    /// let abs_difference = (x.gamma() - 24.0).abs();
+    ///
+    /// assert!(abs_difference <= f64::EPSILON);
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "float_gamma", issue = "99842")]
+    #[inline]
+    pub fn gamma(self) -> f64 {
+        unsafe { cmath::tgamma(self) }
+    }
+
+    /// Returns the natural logarithm of the gamma function.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(float_gamma)]
+    /// let x = 2.0f64;
+    ///
+    /// let abs_difference = (x.ln_gamma().0 - 0.0).abs();
+    ///
+    /// assert!(abs_difference <= f64::EPSILON);
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "float_gamma", issue = "99842")]
+    #[inline]
+    pub fn ln_gamma(self) -> (f64, i32) {
+        let mut signgamp: i32 = 0;
+        let x = unsafe { cmath::lgamma_r(self, &mut signgamp) };
+        (x, signgamp)
+    }
 }
diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs
index 53d351cceef..f88d01593b5 100644
--- a/library/std/src/f64/tests.rs
+++ b/library/std/src/f64/tests.rs
@@ -636,6 +636,38 @@ fn test_atanh() {
 }
 
 #[test]
+fn test_gamma() {
+    // precision can differ between platforms
+    assert_approx_eq!(1.0f64.gamma(), 1.0f64);
+    assert_approx_eq!(2.0f64.gamma(), 1.0f64);
+    assert_approx_eq!(3.0f64.gamma(), 2.0f64);
+    assert_approx_eq!(4.0f64.gamma(), 6.0f64);
+    assert_approx_eq!(5.0f64.gamma(), 24.0f64);
+    assert_approx_eq!(0.5f64.gamma(), consts::PI.sqrt());
+    assert_approx_eq!((-0.5f64).gamma(), -2.0 * consts::PI.sqrt());
+    assert_eq!(0.0f64.gamma(), f64::INFINITY);
+    assert_eq!((-0.0f64).gamma(), f64::NEG_INFINITY);
+    assert!((-1.0f64).gamma().is_nan());
+    assert!((-2.0f64).gamma().is_nan());
+    assert!(f64::NAN.gamma().is_nan());
+    assert!(f64::NEG_INFINITY.gamma().is_nan());
+    assert_eq!(f64::INFINITY.gamma(), f64::INFINITY);
+    assert_eq!(171.71f64.gamma(), f64::INFINITY);
+}
+
+#[test]
+fn test_ln_gamma() {
+    assert_approx_eq!(1.0f64.ln_gamma().0, 0.0f64);
+    assert_eq!(1.0f64.ln_gamma().1, 1);
+    assert_approx_eq!(2.0f64.ln_gamma().0, 0.0f64);
+    assert_eq!(2.0f64.ln_gamma().1, 1);
+    assert_approx_eq!(3.0f64.ln_gamma().0, 2.0f64.ln());
+    assert_eq!(3.0f64.ln_gamma().1, 1);
+    assert_approx_eq!((-0.5f64).ln_gamma().0, (2.0 * consts::PI.sqrt()).ln());
+    assert_eq!((-0.5f64).ln_gamma().1, -1);
+}
+
+#[test]
 fn test_real_consts() {
     use super::consts;
     let pi: f64 = consts::PI;
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 67e58fd1b86..43cecb19b14 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -110,12 +110,12 @@ impl crate::sealed::Sealed for OsString {}
 /// [conversions]: super#conversions
 #[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")]
 #[stable(feature = "rust1", since = "1.0.0")]
-// FIXME:
 // `OsStr::from_inner` current implementation relies
 // on `OsStr` being layout-compatible with `Slice`.
-// When attribute privacy is implemented, `OsStr` should be annotated as `#[repr(transparent)]`.
-// Anyway, `OsStr` representation and layout are considered implementation details, are
-// not documented and must not be relied upon.
+// However, `OsStr` layout is considered an implementation detail and must not be relied upon. We
+// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
+// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
+#[cfg_attr(not(doc), repr(transparent))]
 pub struct OsStr {
     inner: Slice,
 }
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 0f79e74f555..a7e65305386 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -791,6 +791,7 @@ impl Write for &File {
         self.inner.is_write_vectored()
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         self.inner.flush()
     }
@@ -836,6 +837,7 @@ impl Write for File {
     fn is_write_vectored(&self) -> bool {
         (&&*self).is_write_vectored()
     }
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         (&*self).flush()
     }
@@ -881,6 +883,7 @@ impl Write for Arc<File> {
     fn is_write_vectored(&self) -> bool {
         (&**self).is_write_vectored()
     }
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         (&**self).flush()
     }
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 5c1d2d8f46c..71d91f21362 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1425,9 +1425,9 @@ pub trait Write {
     ///
     /// If this method consumed `n > 0` bytes of `buf` it must return [`Ok(n)`].
     /// If the return value is `Ok(n)` then `n` must satisfy `n <= buf.len()`.
-    /// Unless `buf` is empty, this function shouldn’t return `Ok(0)` since the
-    /// caller may interpret that as an error.  To indicate lack of space,
-    /// implementors should return [`ErrorKind::StorageFull`] error instead.
+    /// A return value of `Ok(0)` typically means that the underlying object is
+    /// no longer able to accept bytes and will likely not be able to in the
+    /// future as well, or that the buffer provided is empty.
     ///
     /// # Errors
     ///
diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs
index 1f3f80b9618..034ddd8df9a 100644
--- a/library/std/src/io/readbuf.rs
+++ b/library/std/src/io/readbuf.rs
@@ -310,6 +310,7 @@ impl<'a> Write for BorrowedCursor<'a> {
         Ok(buf.len())
     }
 
+    #[inline]
     fn flush(&mut self) -> Result<()> {
         Ok(())
     }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 31481de8495..ac4ce222fba 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -190,7 +190,7 @@
 
 // To run std tests without x.py without ending up with two copies of std, Miri needs to be
 // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
-// rustc itself never sets the feature, so this line has no affect there.
+// rustc itself never sets the feature, so this line has no effect there.
 #![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
 // miri-test-libstd also prefers to make std use the sysroot versions of the dependencies.
 #![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))]
@@ -288,11 +288,11 @@
 #![feature(exact_size_is_empty)]
 #![feature(exclusive_wrapper)]
 #![feature(extend_one)]
+#![feature(float_gamma)]
 #![feature(float_minimum_maximum)]
 #![feature(float_next_up_down)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
-#![feature(int_roundings)]
 #![feature(ip)]
 #![feature(ip_in_core)]
 #![feature(maybe_uninit_slice)]
@@ -306,7 +306,6 @@
 #![feature(pointer_is_aligned)]
 #![feature(portable_simd)]
 #![feature(prelude_2024)]
-#![feature(provide_any)]
 #![feature(ptr_as_uninit)]
 #![feature(raw_os_nonzero)]
 #![feature(round_ties_even)]
@@ -396,9 +395,15 @@ extern crate libc;
 #[allow(unused_extern_crates)]
 extern crate unwind;
 
+// FIXME: #94122 this extern crate definition only exist here to stop
+// miniz_oxide docs leaking into std docs. Find better way to do it.
+// Remove exclusion from tidy platform check when this removed.
 #[doc(masked)]
 #[allow(unused_extern_crates)]
-#[cfg(feature = "miniz_oxide")]
+#[cfg(all(
+    not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))),
+    feature = "miniz_oxide"
+))]
 extern crate miniz_oxide;
 
 // During testing, this crate is not actually the "real" std library, but rather
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 141a18a42dd..32fd54c8e75 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -647,6 +647,7 @@ impl Write for TcpStream {
         self.0.is_write_vectored()
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
@@ -685,6 +686,7 @@ impl Write for &TcpStream {
         self.0.is_write_vectored()
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/os/l4re/raw.rs b/library/std/src/os/l4re/raw.rs
index b3f7439f8cd..12c0293285a 100644
--- a/library/std/src/os/l4re/raw.rs
+++ b/library/std/src/os/l4re/raw.rs
@@ -27,6 +27,7 @@ pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t};
 #[cfg(any(
     target_arch = "x86",
     target_arch = "m68k",
+    target_arch = "csky",
     target_arch = "powerpc",
     target_arch = "sparc",
     target_arch = "arm",
diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs
index 7c55e92502f..a568f9b26ba 100644
--- a/library/std/src/os/linux/raw.rs
+++ b/library/std/src/os/linux/raw.rs
@@ -27,6 +27,7 @@ pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t};
 #[cfg(any(
     target_arch = "x86",
     target_arch = "m68k",
+    target_arch = "csky",
     target_arch = "powerpc",
     target_arch = "sparc",
     target_arch = "arm",
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index e20170873bb..41290e0017a 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -712,6 +712,7 @@ impl<'a> io::Write for &'a UnixStream {
         self.0.is_write_vectored()
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 99f7a60f8ab..5842c096f1a 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1158,12 +1158,12 @@ impl FusedIterator for Ancestors<'_> {}
 /// Which method works best depends on what kind of situation you're in.
 #[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]
 #[stable(feature = "rust1", since = "1.0.0")]
-// FIXME:
 // `PathBuf::as_mut_vec` current implementation relies
 // on `PathBuf` being layout-compatible with `Vec<u8>`.
-// When attribute privacy is implemented, `PathBuf` should be annotated as `#[repr(transparent)]`.
-// Anyway, `PathBuf` representation and layout are considered implementation detail, are
-// not documented and must not be relied upon.
+// However, `PathBuf` layout is considered an implementation detail and must not be relied upon. We
+// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
+// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
+#[cfg_attr(not(doc), repr(transparent))]
 pub struct PathBuf {
     inner: OsString,
 }
@@ -1983,12 +1983,12 @@ impl AsRef<OsStr> for PathBuf {
 /// ```
 #[cfg_attr(not(test), rustc_diagnostic_item = "Path")]
 #[stable(feature = "rust1", since = "1.0.0")]
-// FIXME:
 // `Path::new` current implementation relies
 // on `Path` being layout-compatible with `OsStr`.
-// When attribute privacy is implemented, `Path` should be annotated as `#[repr(transparent)]`.
-// Anyway, `Path` representation and layout are considered implementation detail, are
-// not documented and must not be relied upon.
+// However, `Path` layout is considered an implementation detail and must not be relied upon. We
+// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
+// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
+#[cfg_attr(not(doc), repr(transparent))]
 pub struct Path {
     inner: OsStr,
 }
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index f9cb755b01a..f54d5934175 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -280,6 +280,7 @@ impl Write for ChildStdin {
         io::Write::is_write_vectored(&&*self)
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         (&*self).flush()
     }
@@ -299,6 +300,7 @@ impl Write for &ChildStdin {
         self.inner.is_write_vectored()
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
@@ -1532,6 +1534,15 @@ impl From<fs::File> for Stdio {
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ExitStatus(imp::ExitStatus);
 
+/// The default value is one which indicates successful completion.
+#[stable(feature = "process-exitcode-default", since = "CURRENT_RUSTC_VERSION")]
+impl Default for ExitStatus {
+    fn default() -> Self {
+        // Ideally this would be done by ExitCode::default().into() but that is complicated.
+        ExitStatus::from_inner(imp::ExitStatus::default())
+    }
+}
+
 /// Allows extension traits within `std`.
 #[unstable(feature = "sealed", issue = "none")]
 impl crate::sealed::Sealed for ExitStatus {}
diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs
index e39254aa434..ed3c5512084 100644
--- a/library/std/src/sync/barrier.rs
+++ b/library/std/src/sync/barrier.rs
@@ -130,11 +130,8 @@ impl Barrier {
         let local_gen = lock.generation_id;
         lock.count += 1;
         if lock.count < self.num_threads {
-            // We need a while loop to guard against spurious wakeups.
-            // https://en.wikipedia.org/wiki/Spurious_wakeup
-            while local_gen == lock.generation_id {
-                lock = self.cvar.wait(lock).unwrap();
-            }
+            let _guard =
+                self.cvar.wait_while(lock, |state| local_gen == state.generation_id).unwrap();
             BarrierWaitResult(false)
         } else {
             lock.count = 0;
diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs
index c00134c8b95..f92bb1a4b1f 100644
--- a/library/std/src/sync/mpsc/mod.rs
+++ b/library/std/src/sync/mpsc/mod.rs
@@ -303,12 +303,11 @@ pub struct IntoIter<T> {
     rx: Receiver<T>,
 }
 
-/// The sending-half of Rust's asynchronous [`channel`] type. This half can only be
-/// owned by one thread, but it can be cloned to send to other threads.
+/// The sending-half of Rust's asynchronous [`channel`] type.
 ///
 /// Messages can be sent through this channel with [`send`].
 ///
-/// Note: all senders (the original and the clones) need to be dropped for the receiver
+/// Note: all senders (the original and its clones) need to be dropped for the receiver
 /// to stop blocking to receive messages with [`Receiver::recv`].
 ///
 /// [`send`]: Sender::send
diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs
index 3ccea3ce0e3..d58aa6c27b8 100644
--- a/library/std/src/sys/common/alloc.rs
+++ b/library/std/src/sys/common/alloc.rs
@@ -8,6 +8,7 @@ use crate::ptr;
     target_arch = "x86",
     target_arch = "arm",
     target_arch = "m68k",
+    target_arch = "csky",
     target_arch = "mips",
     target_arch = "mips32r6",
     target_arch = "powerpc",
diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs
index 4bb735668d2..6aa4ea7f5b4 100644
--- a/library/std/src/sys/hermit/fs.rs
+++ b/library/std/src/sys/hermit/fs.rs
@@ -335,6 +335,7 @@ impl File {
         false
     }
 
+    #[inline]
     pub fn flush(&self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs
index e53dbae6119..c79197a9ad1 100644
--- a/library/std/src/sys/hermit/os.rs
+++ b/library/std/src/sys/hermit/os.rs
@@ -112,6 +112,34 @@ pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
 }
 
+// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
+pub struct EnvStrDebug<'a> {
+    slice: &'a [(OsString, OsString)],
+}
+
+impl fmt::Debug for EnvStrDebug<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { slice } = self;
+        f.debug_list()
+            .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
+            .finish()
+    }
+}
+
+impl Env {
+    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
+        let Self { iter } = self;
+        EnvStrDebug { slice: iter.as_slice() }
+    }
+}
+
+impl fmt::Debug for Env {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { iter } = self;
+        f.debug_list().entries(iter.as_slice()).finish()
+    }
+}
+
 impl !Send for Env {}
 impl !Sync for Env {}
 
diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs
index dc9636ac8c9..e477a0cd7ab 100644
--- a/library/std/src/sys/personality/gcc.rs
+++ b/library/std/src/sys/personality/gcc.rs
@@ -67,6 +67,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // D0, D1
 ))]
 const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1
 
+#[cfg(target_arch = "csky")]
+const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1
+
 #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
 const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4
 
diff --git a/library/std/src/sys/sgx/os.rs b/library/std/src/sys/sgx/os.rs
index 5da0257f35d..86f4c7d3d56 100644
--- a/library/std/src/sys/sgx/os.rs
+++ b/library/std/src/sys/sgx/os.rs
@@ -96,14 +96,61 @@ fn create_env_store() -> &'static EnvStore {
     unsafe { &*(ENV.load(Ordering::Relaxed) as *const EnvStore) }
 }
 
-pub type Env = vec::IntoIter<(OsString, OsString)>;
+pub struct Env {
+    iter: vec::IntoIter<(OsString, OsString)>,
+}
+
+// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
+pub struct EnvStrDebug<'a> {
+    slice: &'a [(OsString, OsString)],
+}
+
+impl fmt::Debug for EnvStrDebug<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { slice } = self;
+        f.debug_list()
+            .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
+            .finish()
+    }
+}
+
+impl Env {
+    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
+        let Self { iter } = self;
+        EnvStrDebug { slice: iter.as_slice() }
+    }
+}
+
+impl fmt::Debug for Env {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { iter } = self;
+        f.debug_list().entries(iter.as_slice()).finish()
+    }
+}
+
+impl !Send for Env {}
+impl !Sync for Env {}
+
+impl Iterator for Env {
+    type Item = (OsString, OsString);
+    fn next(&mut self) -> Option<(OsString, OsString)> {
+        self.iter.next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
 
 pub fn env() -> Env {
     let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> {
         map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
     };
 
-    get_env_store().map(|env| clone_to_vec(&env.lock().unwrap())).unwrap_or_default().into_iter()
+    let iter = get_env_store()
+        .map(|env| clone_to_vec(&env.lock().unwrap()))
+        .unwrap_or_default()
+        .into_iter();
+    Env { iter }
 }
 
 pub fn getenv(k: &OsStr) -> Option<OsString> {
diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs
index 6135921f0b5..717c08434a8 100644
--- a/library/std/src/sys/solid/os.rs
+++ b/library/std/src/sys/solid/os.rs
@@ -85,6 +85,34 @@ pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
 }
 
+// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
+pub struct EnvStrDebug<'a> {
+    slice: &'a [(OsString, OsString)],
+}
+
+impl fmt::Debug for EnvStrDebug<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { slice } = self;
+        f.debug_list()
+            .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
+            .finish()
+    }
+}
+
+impl Env {
+    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
+        let Self { iter } = self;
+        EnvStrDebug { slice: iter.as_slice() }
+    }
+}
+
+impl fmt::Debug for Env {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { iter } = self;
+        f.debug_list().entries(iter.as_slice()).finish()
+    }
+}
+
 impl !Send for Env {}
 impl !Sync for Env {}
 
diff --git a/library/std/src/sys/unix/cmath.rs b/library/std/src/sys/unix/cmath.rs
index 2bf80d7a4cb..5346d229116 100644
--- a/library/std/src/sys/unix/cmath.rs
+++ b/library/std/src/sys/unix/cmath.rs
@@ -30,4 +30,8 @@ extern "C" {
     pub fn tanf(n: f32) -> f32;
     pub fn tanh(n: f64) -> f64;
     pub fn tanhf(n: f32) -> f32;
+    pub fn tgamma(n: f64) -> f64;
+    pub fn tgammaf(n: f32) -> f32;
+    pub fn lgamma_r(n: f64, s: &mut i32) -> f64;
+    pub fn lgammaf_r(n: f32, s: &mut i32) -> f32;
 }
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 7dc809a038b..a5604c92a80 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -1204,6 +1204,7 @@ impl File {
         self.0.write_vectored_at(bufs, offset)
     }
 
+    #[inline]
     pub fn flush(&self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index a68c14758ff..215f63d04f7 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -495,6 +495,34 @@ pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
 }
 
+// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
+pub struct EnvStrDebug<'a> {
+    slice: &'a [(OsString, OsString)],
+}
+
+impl fmt::Debug for EnvStrDebug<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { slice } = self;
+        f.debug_list()
+            .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
+            .finish()
+    }
+}
+
+impl Env {
+    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
+        let Self { iter } = self;
+        EnvStrDebug { slice: iter.as_slice() }
+    }
+}
+
+impl fmt::Debug for Env {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { iter } = self;
+        f.debug_list().entries(iter.as_slice()).finish()
+    }
+}
+
 impl !Send for Env {}
 impl !Sync for Env {}
 
diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs
index e45c380a0bb..9931c2af2f1 100644
--- a/library/std/src/sys/unix/process/process_fuchsia.rs
+++ b/library/std/src/sys/unix/process/process_fuchsia.rs
@@ -235,7 +235,7 @@ impl Process {
     }
 }
 
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
 pub struct ExitStatus(i64);
 
 impl ExitStatus {
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 0ce93af66ac..3963e7f52d5 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -10,9 +10,6 @@ use core::ffi::NonZero_c_int;
 #[cfg(target_os = "linux")]
 use crate::os::linux::process::PidFd;
 
-#[cfg(target_os = "linux")]
-use crate::sys::weak::raw_syscall;
-
 #[cfg(any(
     target_os = "macos",
     target_os = "watchos",
@@ -91,6 +88,11 @@ impl Command {
         if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
             return Ok((ret, ours));
         }
+
+        #[cfg(target_os = "linux")]
+        let (input, output) = sys::net::Socket::new_pair(libc::AF_UNIX, libc::SOCK_SEQPACKET)?;
+
+        #[cfg(not(target_os = "linux"))]
         let (input, output) = sys::pipe::anon_pipe()?;
 
         // Whatever happens after the fork is almost for sure going to touch or
@@ -104,12 +106,16 @@ impl Command {
         // The child calls `mem::forget` to leak the lock, which is crucial because
         // releasing a lock is not async-signal-safe.
         let env_lock = sys::os::env_read_lock();
-        let (pid, pidfd) = unsafe { self.do_fork()? };
+        let pid = unsafe { self.do_fork()? };
 
         if pid == 0 {
             crate::panic::always_abort();
             mem::forget(env_lock); // avoid non-async-signal-safe unlocking
             drop(input);
+            #[cfg(target_os = "linux")]
+            if self.get_create_pidfd() {
+                self.send_pidfd(&output);
+            }
             let Err(err) = unsafe { self.do_exec(theirs, envp.as_ref()) };
             let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32;
             let errno = errno.to_be_bytes();
@@ -133,6 +139,12 @@ impl Command {
         drop(env_lock);
         drop(output);
 
+        #[cfg(target_os = "linux")]
+        let pidfd = if self.get_create_pidfd() { self.recv_pidfd(&input) } else { -1 };
+
+        #[cfg(not(target_os = "linux"))]
+        let pidfd = -1;
+
         // Safety: We obtained the pidfd from calling `clone3` with
         // `CLONE_PIDFD` so it's valid an otherwise unowned.
         let mut p = unsafe { Process::new(pid, pidfd) };
@@ -160,6 +172,7 @@ impl Command {
                 }
                 Ok(..) => {
                     // pipe I/O up to PIPE_BUF bytes should be atomic
+                    // similarly SOCK_SEQPACKET messages should arrive whole
                     assert!(p.wait().is_ok(), "wait() should either return Ok or panic");
                     panic!("short read on the CLOEXEC pipe")
                 }
@@ -185,20 +198,19 @@ impl Command {
     );
 
     #[cfg(any(target_os = "tvos", target_os = "watchos"))]
-    unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
+    unsafe fn do_fork(&mut self) -> Result<pid_t, io::Error> {
         return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
     }
 
     // Attempts to fork the process. If successful, returns Ok((0, -1))
     // in the child, and Ok((child_pid, -1)) in the parent.
     #[cfg(not(any(
-        target_os = "linux",
         target_os = "watchos",
         target_os = "tvos",
         all(target_os = "nto", target_env = "nto71"),
     )))]
-    unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
-        cvt(libc::fork()).map(|res| (res, -1))
+    unsafe fn do_fork(&mut self) -> Result<pid_t, io::Error> {
+        cvt(libc::fork())
     }
 
     // On QNX Neutrino, fork can fail with EBADF in case "another thread might have opened
@@ -206,7 +218,7 @@ impl Command {
     // Documentation says "... or try calling fork() again". This is what we do here.
     // See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html
     #[cfg(all(target_os = "nto", target_env = "nto71"))]
-    unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
+    unsafe fn do_fork(&mut self) -> Result<pid_t, io::Error> {
         use crate::sys::os::errno;
 
         let mut delay = MIN_FORKSPAWN_SLEEP;
@@ -229,91 +241,11 @@ impl Command {
                 delay *= 2;
                 continue;
             } else {
-                return cvt(r).map(|res| (res, -1));
+                return cvt(r);
             }
         }
     }
 
-    // Attempts to fork the process. If successful, returns Ok((0, -1))
-    // in the child, and Ok((child_pid, child_pidfd)) in the parent.
-    #[cfg(target_os = "linux")]
-    unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
-        use crate::sync::atomic::{AtomicBool, Ordering};
-
-        static HAS_CLONE3: AtomicBool = AtomicBool::new(true);
-        const CLONE_PIDFD: u64 = 0x00001000;
-
-        #[repr(C)]
-        struct clone_args {
-            flags: u64,
-            pidfd: u64,
-            child_tid: u64,
-            parent_tid: u64,
-            exit_signal: u64,
-            stack: u64,
-            stack_size: u64,
-            tls: u64,
-            set_tid: u64,
-            set_tid_size: u64,
-            cgroup: u64,
-        }
-
-        raw_syscall! {
-            fn clone3(cl_args: *mut clone_args, len: libc::size_t) -> libc::c_long
-        }
-
-        // Bypassing libc for `clone3` can make further libc calls unsafe,
-        // so we use it sparingly for now. See #89522 for details.
-        // Some tools (e.g. sandboxing tools) may also expect `fork`
-        // rather than `clone3`.
-        let want_clone3_pidfd = self.get_create_pidfd();
-
-        // If we fail to create a pidfd for any reason, this will
-        // stay as -1, which indicates an error.
-        let mut pidfd: pid_t = -1;
-
-        // Attempt to use the `clone3` syscall, which supports more arguments
-        // (in particular, the ability to create a pidfd). If this fails,
-        // we will fall through this block to a call to `fork()`
-        if want_clone3_pidfd && HAS_CLONE3.load(Ordering::Relaxed) {
-            let mut args = clone_args {
-                flags: CLONE_PIDFD,
-                pidfd: &mut pidfd as *mut pid_t as u64,
-                child_tid: 0,
-                parent_tid: 0,
-                exit_signal: libc::SIGCHLD as u64,
-                stack: 0,
-                stack_size: 0,
-                tls: 0,
-                set_tid: 0,
-                set_tid_size: 0,
-                cgroup: 0,
-            };
-
-            let args_ptr = &mut args as *mut clone_args;
-            let args_size = crate::mem::size_of::<clone_args>();
-
-            let res = cvt(clone3(args_ptr, args_size));
-            match res {
-                Ok(n) => return Ok((n as pid_t, pidfd)),
-                Err(e) => match e.raw_os_error() {
-                    // Multiple threads can race to execute this store,
-                    // but that's fine - that just means that multiple threads
-                    // will have tried and failed to execute the same syscall,
-                    // with no other side effects.
-                    Some(libc::ENOSYS) => HAS_CLONE3.store(false, Ordering::Relaxed),
-                    // Fallback to fork if `EPERM` is returned. (e.g. blocked by seccomp)
-                    Some(libc::EPERM) => {}
-                    _ => return Err(e),
-                },
-            }
-        }
-
-        // Generally, we just call `fork`. If we get here after wanting `clone3`,
-        // then the syscall does not exist or we do not have permission to call it.
-        cvt(libc::fork()).map(|res| (res, pidfd))
-    }
-
     pub fn exec(&mut self, default: Stdio) -> io::Error {
         let envp = self.capture_env();
 
@@ -722,6 +654,115 @@ impl Command {
             Ok(Some(p))
         }
     }
+
+    #[cfg(target_os = "linux")]
+    fn send_pidfd(&self, sock: &crate::sys::net::Socket) {
+        use crate::io::IoSlice;
+        use crate::os::fd::RawFd;
+        use crate::sys::cvt_r;
+        use libc::{CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_SPACE, SCM_RIGHTS, SOL_SOCKET};
+
+        unsafe {
+            let child_pid = libc::getpid();
+            // pidfd_open sets CLOEXEC by default
+            let pidfd = libc::syscall(libc::SYS_pidfd_open, child_pid, 0);
+
+            let fds: [c_int; 1] = [pidfd as RawFd];
+
+            const SCM_MSG_LEN: usize = mem::size_of::<[c_int; 1]>();
+
+            #[repr(C)]
+            union Cmsg {
+                buf: [u8; unsafe { CMSG_SPACE(SCM_MSG_LEN as u32) as usize }],
+                _align: libc::cmsghdr,
+            }
+
+            let mut cmsg: Cmsg = mem::zeroed();
+
+            // 0-length message to send through the socket so we can pass along the fd
+            let mut iov = [IoSlice::new(b"")];
+            let mut msg: libc::msghdr = mem::zeroed();
+
+            msg.msg_iov = &mut iov as *mut _ as *mut _;
+            msg.msg_iovlen = 1;
+            msg.msg_controllen = mem::size_of_val(&cmsg.buf) as _;
+            msg.msg_control = &mut cmsg.buf as *mut _ as *mut _;
+
+            // only attach cmsg if we successfully acquired the pidfd
+            if pidfd >= 0 {
+                let hdr = CMSG_FIRSTHDR(&mut msg as *mut _ as *mut _);
+                (*hdr).cmsg_level = SOL_SOCKET;
+                (*hdr).cmsg_type = SCM_RIGHTS;
+                (*hdr).cmsg_len = CMSG_LEN(SCM_MSG_LEN as _) as _;
+                let data = CMSG_DATA(hdr);
+                crate::ptr::copy_nonoverlapping(
+                    fds.as_ptr().cast::<u8>(),
+                    data as *mut _,
+                    SCM_MSG_LEN,
+                );
+            }
+
+            // we send the 0-length message even if we failed to acquire the pidfd
+            // so we get a consistent SEQPACKET order
+            match cvt_r(|| libc::sendmsg(sock.as_raw(), &msg, 0)) {
+                Ok(0) => {}
+                _ => rtabort!("failed to communicate with parent process"),
+            }
+        }
+    }
+
+    #[cfg(target_os = "linux")]
+    fn recv_pidfd(&self, sock: &crate::sys::net::Socket) -> pid_t {
+        use crate::io::IoSliceMut;
+        use crate::sys::cvt_r;
+
+        use libc::{CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_SPACE, SCM_RIGHTS, SOL_SOCKET};
+
+        unsafe {
+            const SCM_MSG_LEN: usize = mem::size_of::<[c_int; 1]>();
+
+            #[repr(C)]
+            union Cmsg {
+                _buf: [u8; unsafe { CMSG_SPACE(SCM_MSG_LEN as u32) as usize }],
+                _align: libc::cmsghdr,
+            }
+            let mut cmsg: Cmsg = mem::zeroed();
+            // 0-length read to get the fd
+            let mut iov = [IoSliceMut::new(&mut [])];
+
+            let mut msg: libc::msghdr = mem::zeroed();
+
+            msg.msg_iov = &mut iov as *mut _ as *mut _;
+            msg.msg_iovlen = 1;
+            msg.msg_controllen = mem::size_of::<Cmsg>() as _;
+            msg.msg_control = &mut cmsg as *mut _ as *mut _;
+
+            match cvt_r(|| libc::recvmsg(sock.as_raw(), &mut msg, 0)) {
+                Err(_) => return -1,
+                Ok(_) => {}
+            }
+
+            let hdr = CMSG_FIRSTHDR(&mut msg as *mut _ as *mut _);
+            if hdr.is_null()
+                || (*hdr).cmsg_level != SOL_SOCKET
+                || (*hdr).cmsg_type != SCM_RIGHTS
+                || (*hdr).cmsg_len != CMSG_LEN(SCM_MSG_LEN as _) as _
+            {
+                return -1;
+            }
+            let data = CMSG_DATA(hdr);
+
+            let mut fds = [-1 as c_int];
+
+            crate::ptr::copy_nonoverlapping(
+                data as *const _,
+                fds.as_mut_ptr().cast::<u8>(),
+                SCM_MSG_LEN,
+            );
+
+            fds[0]
+        }
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -800,7 +841,7 @@ impl Process {
 //
 // This is not actually an "exit status" in Unix terminology.  Rather, it is a "wait status".
 // See the discussion in comments and doc comments for `std::process::ExitStatus`.
-#[derive(PartialEq, Eq, Clone, Copy)]
+#[derive(PartialEq, Eq, Clone, Copy, Default)]
 pub struct ExitStatus(c_int);
 
 impl fmt::Debug for ExitStatus {
diff --git a/library/std/src/sys/unix/process/process_unix/tests.rs b/library/std/src/sys/unix/process/process_unix/tests.rs
index e5e1f956bc3..6aa79e7f9e7 100644
--- a/library/std/src/sys/unix/process/process_unix/tests.rs
+++ b/library/std/src/sys/unix/process/process_unix/tests.rs
@@ -60,3 +60,28 @@ fn test_command_fork_no_unwind() {
             || signal == libc::SIGSEGV
     );
 }
+
+#[test]
+#[cfg(target_os = "linux")]
+fn test_command_pidfd() {
+    use crate::os::fd::RawFd;
+    use crate::os::linux::process::{ChildExt, CommandExt};
+    use crate::process::Command;
+
+    let our_pid = crate::process::id();
+    let pidfd = unsafe { libc::syscall(libc::SYS_pidfd_open, our_pid, 0) };
+    let pidfd_open_available = if pidfd >= 0 {
+        unsafe { libc::close(pidfd as RawFd) };
+        true
+    } else {
+        false
+    };
+
+    // always exercise creation attempts
+    let child = Command::new("echo").create_pidfd(true).spawn().unwrap();
+
+    // but only check if we know that the kernel supports pidfds
+    if pidfd_open_available {
+        assert!(child.pidfd().is_ok())
+    }
+}
diff --git a/library/std/src/sys/unix/process/process_unsupported.rs b/library/std/src/sys/unix/process/process_unsupported.rs
index f28ca58d020..8e0b971af73 100644
--- a/library/std/src/sys/unix/process/process_unsupported.rs
+++ b/library/std/src/sys/unix/process/process_unsupported.rs
@@ -55,7 +55,7 @@ impl Process {
     }
 }
 
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
 pub struct ExitStatus(c_int);
 
 impl ExitStatus {
diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs
index f70d3cb396b..1ff2b2fb383 100644
--- a/library/std/src/sys/unix/process/process_vxworks.rs
+++ b/library/std/src/sys/unix/process/process_vxworks.rs
@@ -179,7 +179,7 @@ impl Process {
 }
 
 /// Unix exit statuses
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
 pub struct ExitStatus(c_int);
 
 impl ExitStatus {
diff --git a/library/std/src/sys/unix/stdio.rs b/library/std/src/sys/unix/stdio.rs
index a26f20795a1..97e75f1b5b6 100644
--- a/library/std/src/sys/unix/stdio.rs
+++ b/library/std/src/sys/unix/stdio.rs
@@ -54,6 +54,7 @@ impl io::Write for Stdout {
         true
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
@@ -81,6 +82,7 @@ impl io::Write for Stderr {
         true
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/sys/unsupported/os.rs b/library/std/src/sys/unsupported/os.rs
index e150ae143ad..248b34829f2 100644
--- a/library/std/src/sys/unsupported/os.rs
+++ b/library/std/src/sys/unsupported/os.rs
@@ -65,10 +65,26 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 pub struct Env(!);
 
+impl Env {
+    // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
+    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
+        let Self(inner) = self;
+        match *inner {}
+    }
+}
+
+impl fmt::Debug for Env {
+    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self(inner) = self;
+        match *inner {}
+    }
+}
+
 impl Iterator for Env {
     type Item = (OsString, OsString);
     fn next(&mut self) -> Option<(OsString, OsString)> {
-        self.0
+        let Self(inner) = self;
+        match *inner {}
     }
 }
 
diff --git a/library/std/src/sys/unsupported/process.rs b/library/std/src/sys/unsupported/process.rs
index a494f2d6b4c..77b675aaa4e 100644
--- a/library/std/src/sys/unsupported/process.rs
+++ b/library/std/src/sys/unsupported/process.rs
@@ -99,58 +99,59 @@ impl fmt::Debug for Command {
     }
 }
 
-pub struct ExitStatus(!);
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
+#[non_exhaustive]
+pub struct ExitStatus();
 
 impl ExitStatus {
     pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
-        self.0
+        Ok(())
     }
 
     pub fn code(&self) -> Option<i32> {
-        self.0
+        Some(0)
     }
 }
 
-impl Clone for ExitStatus {
-    fn clone(&self) -> ExitStatus {
-        self.0
+impl fmt::Display for ExitStatus {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "<dummy exit status>")
     }
 }
 
-impl Copy for ExitStatus {}
+pub struct ExitStatusError(!);
 
-impl PartialEq for ExitStatus {
-    fn eq(&self, _other: &ExitStatus) -> bool {
+impl Clone for ExitStatusError {
+    fn clone(&self) -> ExitStatusError {
         self.0
     }
 }
 
-impl Eq for ExitStatus {}
+impl Copy for ExitStatusError {}
 
-impl fmt::Debug for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl PartialEq for ExitStatusError {
+    fn eq(&self, _other: &ExitStatusError) -> bool {
         self.0
     }
 }
 
-impl fmt::Display for ExitStatus {
+impl Eq for ExitStatusError {}
+
+impl fmt::Debug for ExitStatusError {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.0
     }
 }
 
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct ExitStatusError(ExitStatus);
-
 impl Into<ExitStatus> for ExitStatusError {
     fn into(self) -> ExitStatus {
-        self.0.0
+        self.0
     }
 }
 
 impl ExitStatusError {
     pub fn code(self) -> Option<NonZeroI32> {
-        self.0.0
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs
index 1b50c2ea6dd..d7295a799da 100644
--- a/library/std/src/sys/wasi/fd.rs
+++ b/library/std/src/sys/wasi/fd.rs
@@ -16,14 +16,20 @@ pub struct WasiFd {
 fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] {
     assert_eq!(mem::size_of::<IoSliceMut<'_>>(), mem::size_of::<wasi::Iovec>());
     assert_eq!(mem::align_of::<IoSliceMut<'_>>(), mem::align_of::<wasi::Iovec>());
-    // SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout
+    // SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout.
+    // We decorate our `IoSliceMut` with `repr(transparent)` (see `io.rs`), and
+    // `crate::io::IoSliceMut` is a `repr(transparent)` wrapper around our type, so this is
+    // guaranteed.
     unsafe { mem::transmute(a) }
 }
 
 fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] {
     assert_eq!(mem::size_of::<IoSlice<'_>>(), mem::size_of::<wasi::Ciovec>());
     assert_eq!(mem::align_of::<IoSlice<'_>>(), mem::align_of::<wasi::Ciovec>());
-    // SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout
+    // SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout.
+    // We decorate our `IoSlice` with `repr(transparent)` (see `io.rs`), and
+    // `crate::io::IoSlice` is a `repr(transparent)` wrapper around our type, so this is
+    // guaranteed.
     unsafe { mem::transmute(a) }
 }
 
diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs
index 197bdeda4fb..e0de284c5e2 100644
--- a/library/std/src/sys/wasi/os.rs
+++ b/library/std/src/sys/wasi/os.rs
@@ -142,10 +142,39 @@ impl StdError for JoinPathsError {
 pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
+
 pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
 }
 
+// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
+pub struct EnvStrDebug<'a> {
+    slice: &'a [(OsString, OsString)],
+}
+
+impl fmt::Debug for EnvStrDebug<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { slice } = self;
+        f.debug_list()
+            .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
+            .finish()
+    }
+}
+
+impl Env {
+    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
+        let Self { iter } = self;
+        EnvStrDebug { slice: iter.as_slice() }
+    }
+}
+
+impl fmt::Debug for Env {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { iter } = self;
+        f.debug_list().entries(iter.as_slice()).finish()
+    }
+}
+
 impl !Send for Env {}
 impl !Sync for Env {}
 
diff --git a/library/std/src/sys/wasi/thread.rs b/library/std/src/sys/wasi/thread.rs
index d27b7a2e0f5..dbad425976a 100644
--- a/library/std/src/sys/wasi/thread.rs
+++ b/library/std/src/sys/wasi/thread.rs
@@ -20,9 +20,9 @@ cfg_if::cfg_if! {
             // https://github.com/WebAssembly/wasi-libc/blob/a6f871343313220b76009827ed0153586361c0d5/libc-top-half/musl/include/alltypes.h.in#L108
             #[repr(C)]
             union pthread_attr_union {
-                __i: [ffi::c_int; if mem::size_of::<ffi::c_int>() == 8 { 14 } else { 9 }],
-                __vi: [ffi::c_int; if mem::size_of::<ffi::c_int>() == 8 { 14 } else { 9 }],
-                __s: [ffi::c_ulong; if mem::size_of::<ffi::c_int>() == 8 { 7 } else { 9 }],
+                __i: [ffi::c_int; if mem::size_of::<ffi::c_long>() == 8 { 14 } else { 9 }],
+                __vi: [ffi::c_int; if mem::size_of::<ffi::c_long>() == 8 { 14 } else { 9 }],
+                __s: [ffi::c_ulong; if mem::size_of::<ffi::c_long>() == 8 { 7 } else { 9 }],
             }
 
             #[repr(C)]
diff --git a/library/std/src/sys/windows/cmath.rs b/library/std/src/sys/windows/cmath.rs
index 43ab8c7ee65..1b2a86f3c0e 100644
--- a/library/std/src/sys/windows/cmath.rs
+++ b/library/std/src/sys/windows/cmath.rs
@@ -1,6 +1,6 @@
 #![cfg(not(test))]
 
-use libc::{c_double, c_float};
+use libc::{c_double, c_float, c_int};
 
 extern "C" {
     pub fn acos(n: c_double) -> c_double;
@@ -23,6 +23,10 @@ extern "C" {
     pub fn sinh(n: c_double) -> c_double;
     pub fn tan(n: c_double) -> c_double;
     pub fn tanh(n: c_double) -> c_double;
+    pub fn tgamma(n: c_double) -> c_double;
+    pub fn tgammaf(n: c_float) -> c_float;
+    pub fn lgamma_r(n: c_double, s: &mut c_int) -> c_double;
+    pub fn lgammaf_r(n: c_float, s: &mut c_int) -> c_float;
 }
 
 pub use self::shims::*;
diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs
index d7adeb266ed..2329426ad1d 100644
--- a/library/std/src/sys/windows/os.rs
+++ b/library/std/src/sys/windows/os.rs
@@ -85,25 +85,69 @@ pub fn error_string(mut errnum: i32) -> String {
 
 pub struct Env {
     base: c::LPWCH,
-    cur: c::LPWCH,
+    iter: EnvIterator,
+}
+
+// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
+pub struct EnvStrDebug<'a> {
+    iter: &'a EnvIterator,
+}
+
+impl fmt::Debug for EnvStrDebug<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { iter } = self;
+        let iter: EnvIterator = (*iter).clone();
+        let mut list = f.debug_list();
+        for (a, b) in iter {
+            list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));
+        }
+        list.finish()
+    }
+}
+
+impl Env {
+    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
+        let Self { base: _, iter } = self;
+        EnvStrDebug { iter }
+    }
+}
+
+impl fmt::Debug for Env {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { base: _, iter } = self;
+        f.debug_list().entries(iter.clone()).finish()
+    }
 }
 
 impl Iterator for Env {
     type Item = (OsString, OsString);
 
     fn next(&mut self) -> Option<(OsString, OsString)> {
+        let Self { base: _, iter } = self;
+        iter.next()
+    }
+}
+
+#[derive(Clone)]
+struct EnvIterator(c::LPWCH);
+
+impl Iterator for EnvIterator {
+    type Item = (OsString, OsString);
+
+    fn next(&mut self) -> Option<(OsString, OsString)> {
+        let Self(cur) = self;
         loop {
             unsafe {
-                if *self.cur == 0 {
+                if **cur == 0 {
                     return None;
                 }
-                let p = self.cur as *const u16;
+                let p = *cur as *const u16;
                 let mut len = 0;
                 while *p.add(len) != 0 {
                     len += 1;
                 }
                 let s = slice::from_raw_parts(p, len);
-                self.cur = self.cur.add(len + 1);
+                *cur = cur.add(len + 1);
 
                 // Windows allows environment variables to start with an equals
                 // symbol (in any other position, this is the separator between
@@ -137,7 +181,7 @@ pub fn env() -> Env {
         if ch.is_null() {
             panic!("failure getting env string from OS: {}", io::Error::last_os_error());
         }
-        Env { base: ch, cur: ch }
+        Env { base: ch, iter: EnvIterator(ch) }
     }
 }
 
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index e3493cbb850..2dd0c67acdb 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -652,7 +652,7 @@ impl Process {
     }
 }
 
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
 pub struct ExitStatus(c::DWORD);
 
 impl ExitStatus {
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index 195d175cc9b..67db5ebd89c 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -459,6 +459,7 @@ impl Wtf8Buf {
     /// Converts this `Wtf8Buf` into a boxed `Wtf8`.
     #[inline]
     pub fn into_box(self) -> Box<Wtf8> {
+        // SAFETY: relies on `Wtf8` being `repr(transparent)`.
         unsafe { mem::transmute(self.bytes.into_boxed_slice()) }
     }
 
@@ -511,6 +512,7 @@ impl Extend<CodePoint> for Wtf8Buf {
 /// Similar to `&str`, but can additionally contain surrogate code points
 /// if they’re not in a surrogate pair.
 #[derive(Eq, Ord, PartialEq, PartialOrd)]
+#[repr(transparent)]
 pub struct Wtf8 {
     bytes: [u8],
 }
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 1b86d898cc7..21515adc6c4 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -313,7 +313,6 @@ impl<T: 'static> LocalKey<Cell<T>> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(local_key_cell_methods)]
     /// use std::cell::Cell;
     ///
     /// thread_local! {
@@ -326,7 +325,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
     ///
     /// assert_eq!(X.get(), 123);
     /// ```
-    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")]
     pub fn set(&'static self, value: T) {
         self.initialize_with(Cell::new(value), |value, cell| {
             if let Some(value) = value {
@@ -351,7 +350,6 @@ impl<T: 'static> LocalKey<Cell<T>> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(local_key_cell_methods)]
     /// use std::cell::Cell;
     ///
     /// thread_local! {
@@ -360,7 +358,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
     ///
     /// assert_eq!(X.get(), 1);
     /// ```
-    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")]
     pub fn get(&'static self) -> T
     where
         T: Copy,
@@ -381,7 +379,6 @@ impl<T: 'static> LocalKey<Cell<T>> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(local_key_cell_methods)]
     /// use std::cell::Cell;
     ///
     /// thread_local! {
@@ -391,7 +388,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
     /// assert_eq!(X.take(), Some(1));
     /// assert_eq!(X.take(), None);
     /// ```
-    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")]
     pub fn take(&'static self) -> T
     where
         T: Default,
@@ -412,7 +409,6 @@ impl<T: 'static> LocalKey<Cell<T>> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(local_key_cell_methods)]
     /// use std::cell::Cell;
     ///
     /// thread_local! {
@@ -422,7 +418,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
     /// assert_eq!(X.replace(2), 1);
     /// assert_eq!(X.replace(3), 2);
     /// ```
-    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")]
     pub fn replace(&'static self, value: T) -> T {
         self.with(|cell| cell.replace(value))
     }
@@ -444,7 +440,6 @@ impl<T: 'static> LocalKey<RefCell<T>> {
     /// # Example
     ///
     /// ```
-    /// #![feature(local_key_cell_methods)]
     /// use std::cell::RefCell;
     ///
     /// thread_local! {
@@ -453,7 +448,7 @@ impl<T: 'static> LocalKey<RefCell<T>> {
     ///
     /// X.with_borrow(|v| assert!(v.is_empty()));
     /// ```
-    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")]
     pub fn with_borrow<F, R>(&'static self, f: F) -> R
     where
         F: FnOnce(&T) -> R,
@@ -476,7 +471,6 @@ impl<T: 'static> LocalKey<RefCell<T>> {
     /// # Example
     ///
     /// ```
-    /// #![feature(local_key_cell_methods)]
     /// use std::cell::RefCell;
     ///
     /// thread_local! {
@@ -487,7 +481,7 @@ impl<T: 'static> LocalKey<RefCell<T>> {
     ///
     /// X.with_borrow(|v| assert_eq!(*v, vec![1]));
     /// ```
-    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")]
     pub fn with_borrow_mut<F, R>(&'static self, f: F) -> R
     where
         F: FnOnce(&mut T) -> R,
@@ -511,7 +505,6 @@ impl<T: 'static> LocalKey<RefCell<T>> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(local_key_cell_methods)]
     /// use std::cell::RefCell;
     ///
     /// thread_local! {
@@ -524,7 +517,7 @@ impl<T: 'static> LocalKey<RefCell<T>> {
     ///
     /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
     /// ```
-    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")]
     pub fn set(&'static self, value: T) {
         self.initialize_with(RefCell::new(value), |value, cell| {
             if let Some(value) = value {
@@ -551,7 +544,6 @@ impl<T: 'static> LocalKey<RefCell<T>> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(local_key_cell_methods)]
     /// use std::cell::RefCell;
     ///
     /// thread_local! {
@@ -566,7 +558,7 @@ impl<T: 'static> LocalKey<RefCell<T>> {
     ///
     /// X.with_borrow(|v| assert!(v.is_empty()));
     /// ```
-    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")]
     pub fn take(&'static self) -> T
     where
         T: Default,
@@ -586,7 +578,6 @@ impl<T: 'static> LocalKey<RefCell<T>> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(local_key_cell_methods)]
     /// use std::cell::RefCell;
     ///
     /// thread_local! {
@@ -598,7 +589,7 @@ impl<T: 'static> LocalKey<RefCell<T>> {
     ///
     /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
     /// ```
-    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    #[stable(feature = "local_key_cell_methods", since = "CURRENT_RUSTC_VERSION")]
     pub fn replace(&'static self, value: T) -> T {
         self.with(|cell| cell.replace(value))
     }