about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/collections/hash/map.rs20
-rw-r--r--library/std/src/collections/hash/set.rs20
-rw-r--r--library/std/src/ffi/mod.rs9
-rw-r--r--library/std/src/io/error.rs13
-rw-r--r--library/std/src/keyword_docs.rs14
-rw-r--r--library/std/src/lib.rs5
-rw-r--r--library/std/src/os/fd/mod.rs3
-rw-r--r--library/std/src/os/fd/owned.rs10
-rw-r--r--library/std/src/os/fd/raw.rs42
-rw-r--r--library/std/src/os/fd/tests.rs34
-rw-r--r--library/std/src/os/raw/char.md9
-rw-r--r--library/std/src/os/raw/double.md6
-rw-r--r--library/std/src/os/raw/float.md5
-rw-r--r--library/std/src/os/raw/int.md5
-rw-r--r--library/std/src/os/raw/long.md5
-rw-r--r--library/std/src/os/raw/longlong.md5
-rw-r--r--library/std/src/os/raw/mod.rs167
-rw-r--r--library/std/src/os/raw/schar.md5
-rw-r--r--library/std/src/os/raw/short.md5
-rw-r--r--library/std/src/os/raw/uchar.md5
-rw-r--r--library/std/src/os/raw/uint.md5
-rw-r--r--library/std/src/os/raw/ulong.md5
-rw-r--r--library/std/src/os/raw/ulonglong.md5
-rw-r--r--library/std/src/os/raw/ushort.md5
-rw-r--r--library/std/src/os/windows/io/handle.rs66
-rw-r--r--library/std/src/os/windows/io/raw.rs96
-rw-r--r--library/std/src/os/windows/io/socket.rs21
-rw-r--r--library/std/src/sys/unix/os.rs5
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs2
-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.rs12
-rw-r--r--library/std/src/sys/unix/thread.rs85
-rw-r--r--library/std/src/sys/windows/c.rs2
-rw-r--r--library/std/src/sys/windows/net.rs4
-rw-r--r--library/std/src/sys_common/net.rs33
-rw-r--r--library/std/src/thread/local.rs4
-rw-r--r--library/std/src/thread/mod.rs7
38 files changed, 381 insertions, 367 deletions
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 53b43455b5a..c0524352193 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -371,7 +371,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// assert_eq!(vec, ["a", "b", "c"]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "map_into_keys_values", since = "1.54.0")]
     pub fn into_keys(self) -> IntoKeys<K, V> {
         IntoKeys { inner: self.into_iter() }
@@ -449,7 +449,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// assert_eq!(vec, [1, 2, 3]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "map_into_keys_values", since = "1.54.0")]
     pub fn into_values(self) -> IntoValues<K, V> {
         IntoValues { inner: self.into_iter() }
@@ -473,7 +473,7 @@ impl<K, V, S> HashMap<K, V, S> {
     ///     println!("key: {} val: {}", key, val);
     /// }
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<'_, K, V> {
         Iter { base: self.base.iter() }
@@ -503,7 +503,7 @@ impl<K, V, S> HashMap<K, V, S> {
     ///     println!("key: {} val: {}", key, val);
     /// }
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
         IterMut { base: self.base.iter_mut() }
@@ -568,7 +568,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// assert!(a.is_empty());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "drain", since = "1.6.0")]
     pub fn drain(&mut self) -> Drain<'_, K, V> {
         Drain { base: self.base.drain() }
@@ -610,7 +610,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// assert_eq!(odds, vec![1, 3, 5, 7]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[unstable(feature = "hash_drain_filter", issue = "59618")]
     pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F>
     where
@@ -634,7 +634,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// assert_eq!(map.len(), 4);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "retain_hash_collection", since = "1.18.0")]
     pub fn retain<F>(&mut self, f: F)
     where
@@ -2001,7 +2001,7 @@ impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> {
     type IntoIter = Iter<'a, K, V>;
 
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     fn into_iter(self) -> Iter<'a, K, V> {
         self.iter()
     }
@@ -2013,7 +2013,7 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S> {
     type IntoIter = IterMut<'a, K, V>;
 
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     fn into_iter(self) -> IterMut<'a, K, V> {
         self.iter_mut()
     }
@@ -2043,7 +2043,7 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S> {
     /// let vec: Vec<(&str, i32)> = map.into_iter().collect();
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     fn into_iter(self) -> IntoIter<K, V> {
         IntoIter { base: self.base.into_iter() }
     }
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 200667ae390..2eb4cacabb8 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -185,7 +185,7 @@ impl<T, S> HashSet<T, S> {
     /// }
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<'_, T> {
         Iter { base: self.base.iter() }
@@ -250,7 +250,7 @@ impl<T, S> HashSet<T, S> {
     /// assert!(set.is_empty());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "drain", since = "1.6.0")]
     pub fn drain(&mut self) -> Drain<'_, T> {
         Drain { base: self.base.drain() }
@@ -289,7 +289,7 @@ impl<T, S> HashSet<T, S> {
     /// assert_eq!(odds, vec![1, 3, 5, 7]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[unstable(feature = "hash_drain_filter", issue = "59618")]
     pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, T, F>
     where
@@ -312,7 +312,7 @@ impl<T, S> HashSet<T, S> {
     /// set.retain(|&k| k % 2 == 0);
     /// assert_eq!(set.len(), 3);
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "retain_hash_collection", since = "1.18.0")]
     pub fn retain<F>(&mut self, f: F)
     where
@@ -537,7 +537,7 @@ where
     /// assert_eq!(diff, [4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> {
         Difference { iter: self.iter(), other }
@@ -565,7 +565,7 @@ where
     /// assert_eq!(diff1, [1, 4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn symmetric_difference<'a>(
         &'a self,
@@ -593,7 +593,7 @@ where
     /// assert_eq!(intersection, [2, 3].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
         if self.len() <= other.len() {
@@ -622,7 +622,7 @@ where
     /// assert_eq!(union, [1, 2, 3, 4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
         if self.len() >= other.len() {
@@ -1423,7 +1423,7 @@ impl<'a, T, S> IntoIterator for &'a HashSet<T, S> {
     type IntoIter = Iter<'a, T>;
 
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     fn into_iter(self) -> Iter<'a, T> {
         self.iter()
     }
@@ -1455,7 +1455,7 @@ impl<T, S> IntoIterator for HashSet<T, S> {
     /// }
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     fn into_iter(self) -> IntoIter<T> {
         IntoIter { base: self.base.into_iter() }
     }
diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs
index 019b64c395e..13e3dacc30d 100644
--- a/library/std/src/ffi/mod.rs
+++ b/library/std/src/ffi/mod.rs
@@ -159,6 +159,15 @@ pub use self::os_str::{OsStr, OsString};
 #[stable(feature = "core_c_void", since = "1.30.0")]
 pub use core::ffi::c_void;
 
+#[unstable(feature = "core_ffi_c", issue = "94501")]
+pub use core::ffi::{
+    c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
+    c_ulong, c_ulonglong, c_ushort,
+};
+
+#[unstable(feature = "c_size_t", issue = "88345")]
+pub use core::ffi::{c_ptrdiff_t, c_size_t, c_ssize_t};
+
 #[unstable(
     feature = "c_variadic",
     reason = "the `c_variadic` feature has not been properly tested on \
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 1aa6d657889..17e2b97545a 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -141,6 +141,19 @@ struct Custom {
 /// It is used with the [`io::Error`] type.
 ///
 /// [`io::Error`]: Error
+///
+/// # Handling errors and matching on `ErrorKind`
+///
+/// In application code, use `match` for the `ErrorKind` values you are
+/// expecting; use `_` to match "all other errors".
+///
+/// In comprehensive and thorough tests that want to verify that a test doesn't
+/// return any known incorrect error kind, you may want to cut-and-paste the
+/// current full list of errors from here into your test code, and then match
+/// `_` as the correct case. This seems counterintuitive, but it will make your
+/// tests more robust. In particular, if you want to verify that your code does
+/// produce an unrecognized error kind, the robust solution is to check for all
+/// the recognized error kinds and fail in those cases.
 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated)]
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 35d230eee96..5b76259afc1 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -2203,17 +2203,18 @@ mod where_keyword {}
 ///
 /// Use `async` in front of `fn`, `closure`, or a `block` to turn the marked code into a `Future`.
 /// As such the code will not be run immediately, but will only be evaluated when the returned
-/// future is `.await`ed.
+/// future is [`.await`]ed.
 ///
-/// We have written an [async book] detailing async/await and trade-offs compared to using threads.
+/// We have written an [async book] detailing `async`/`await` and trade-offs compared to using threads.
 ///
 /// ## Editions
 ///
 /// `async` is a keyword from the 2018 edition onwards.
 ///
-/// It is available for use in stable rust from version 1.39 onwards.
+/// It is available for use in stable Rust from version 1.39 onwards.
 ///
 /// [`Future`]: future::Future
+/// [`.await`]: ../std/keyword.await.html
 /// [async book]: https://rust-lang.github.io/async-book/
 mod async_keyword {}
 
@@ -2221,19 +2222,20 @@ mod async_keyword {}
 //
 /// Suspend execution until the result of a [`Future`] is ready.
 ///
-/// `.await`ing a future will suspend the current function's execution until the `executor`
+/// `.await`ing a future will suspend the current function's execution until the executor
 /// has run the future to completion.
 ///
-/// Read the [async book] for details on how async/await and executors work.
+/// Read the [async book] for details on how [`async`]/`await` and executors work.
 ///
 /// ## Editions
 ///
 /// `await` is a keyword from the 2018 edition onwards.
 ///
-/// It is available for use in stable rust from version 1.39 onwards.
+/// It is available for use in stable Rust from version 1.39 onwards.
 ///
 /// [`Future`]: future::Future
 /// [async book]: https://rust-lang.github.io/async-book/
+/// [`async`]: ../std/keyword.async.html
 mod await_keyword {}
 
 #[doc(keyword = "dyn")]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 2628afd4237..10fec8e1152 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -243,7 +243,6 @@
 #![feature(c_variadic)]
 #![feature(cfg_accessible)]
 #![feature(cfg_eval)]
-#![cfg_attr(bootstrap, feature(cfg_target_has_atomic))]
 #![feature(cfg_target_thread_local)]
 #![feature(char_error_internals)]
 #![feature(char_internals)]
@@ -262,6 +261,8 @@
 #![feature(const_socketaddr)]
 #![feature(const_trait_impl)]
 #![feature(container_error_extra)]
+#![feature(c_size_t)]
+#![feature(core_ffi_c)]
 #![feature(core_intrinsics)]
 #![feature(core_panic)]
 #![feature(custom_test_frameworks)]
@@ -316,6 +317,7 @@
 #![feature(prelude_import)]
 #![feature(ptr_as_uninit)]
 #![feature(ptr_internals)]
+#![feature(raw_os_nonzero)]
 #![feature(rustc_attrs)]
 #![feature(rustc_private)]
 #![feature(saturating_int_impl)]
@@ -366,6 +368,7 @@ extern crate unwind;
 
 #[doc(masked)]
 #[allow(unused_extern_crates)]
+#[cfg(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/os/fd/mod.rs b/library/std/src/os/fd/mod.rs
index df11dc21aa7..13bb079194f 100644
--- a/library/std/src/os/fd/mod.rs
+++ b/library/std/src/os/fd/mod.rs
@@ -11,3 +11,6 @@ pub mod owned;
 
 // Implementations for `AsRawFd` etc. for network types.
 mod net;
+
+#[cfg(test)]
+mod tests;
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index 71c660e7186..807b057234a 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -8,7 +8,7 @@ use crate::fmt;
 use crate::fs;
 use crate::marker::PhantomData;
 use crate::mem::forget;
-#[cfg(not(target_os = "wasi"))]
+#[cfg(not(any(target_os = "wasi", target_env = "sgx")))]
 use crate::sys::cvt;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 
@@ -21,6 +21,10 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 /// descriptor, so it can be used in FFI in places where a file descriptor is
 /// passed as an argument, it is not captured or consumed, and it never has the
 /// value `-1`.
+///
+/// This type's `.to_owned()` implementation returns another `BorrowedFd`
+/// rather than an `OwnedFd`. It just makes a trivial copy of the raw file
+/// descriptor, which is then borrowed under the same lifetime.
 #[derive(Copy, Clone)]
 #[repr(transparent)]
 #[rustc_layout_scalar_valid_range_start(0)]
@@ -62,7 +66,7 @@ impl BorrowedFd<'_> {
     /// the returned `BorrowedFd`, and it must not have the value `-1`.
     #[inline]
     #[unstable(feature = "io_safety", issue = "87074")]
-    pub unsafe fn borrow_raw_fd(fd: RawFd) -> Self {
+    pub unsafe fn borrow_raw(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, _phantom: PhantomData } }
@@ -231,7 +235,7 @@ impl AsFd for OwnedFd {
         // Safety: `OwnedFd` and `BorrowedFd` have the same validity
         // invariants, and the `BorrowdFd` is bounded by the lifetime
         // of `&self`.
-        unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) }
+        unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
     }
 }
 
diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs
index f874cf0b42d..f9c883dd6bf 100644
--- a/library/std/src/os/fd/raw.rs
+++ b/library/std/src/os/fd/raw.rs
@@ -5,6 +5,8 @@
 use crate::fs;
 use crate::io;
 use crate::os::raw;
+#[cfg(doc)]
+use crate::os::unix::io::AsFd;
 #[cfg(unix)]
 use crate::os::unix::io::OwnedFd;
 #[cfg(target_os = "wasi")]
@@ -24,9 +26,14 @@ pub type RawFd = raw::c_int;
 pub trait AsRawFd {
     /// Extracts the raw file descriptor.
     ///
-    /// This method does **not** pass ownership of the raw file descriptor
-    /// to the caller. The descriptor is only guaranteed to be valid while
-    /// the original object has not yet been destroyed.
+    /// This function is typically used to **borrow** an owned file descriptor.
+    /// When used in this way, this method does **not** pass ownership of the
+    /// raw file descriptor to the caller, and the file descriptor is only
+    /// guaranteed to be valid while the original object has not yet been
+    /// destroyed.
+    ///
+    /// However, borrowing is not strictly required. See [`AsFd::as_fd`]
+    /// for an API which strictly borrows a file descriptor.
     ///
     /// # Example
     ///
@@ -55,15 +62,18 @@ pub trait FromRawFd {
     /// Constructs a new instance of `Self` from the given raw file
     /// descriptor.
     ///
-    /// This function **consumes ownership** of the specified file
-    /// descriptor. The returned object will take responsibility for closing
-    /// it when the object goes out of scope.
+    /// This function is typically used to **consume ownership** of the
+    /// specified file descriptor. When used in this way, the returned object
+    /// will take responsibility for closing it when the object goes out of
+    /// scope.
+    ///
+    /// However, consuming ownership is not strictly required. Use a
+    /// [`From<OwnedFd>::from`] implementation for an API which strictly
+    /// consumes ownership.
     ///
-    /// This function is also unsafe as the primitives currently returned
-    /// have the contract that they are the sole owner of the file
-    /// descriptor they are wrapping. Usage of this function could
-    /// accidentally allow violating this contract which can cause memory
-    /// unsafety in code that relies on it being true.
+    /// # Safety
+    ///
+    /// The `fd` passed in must be a valid an open file descriptor.
     ///
     /// # Example
     ///
@@ -94,9 +104,13 @@ pub trait FromRawFd {
 pub trait IntoRawFd {
     /// Consumes this object, returning the raw underlying file descriptor.
     ///
-    /// This function **transfers ownership** of the underlying file descriptor
-    /// to the caller. Callers are then the unique owners of the file descriptor
-    /// and must close the descriptor once it's no longer needed.
+    /// This function is typically used to **transfer ownership** of the underlying
+    /// file descriptor to the caller. When used in this way, callers are then the unique
+    /// owners of the file descriptor and must close it once it's no longer needed.
+    ///
+    /// However, transferring ownership is not strictly required. Use a
+    /// [`Into<OwnedFd>::into`] implementation for an API which strictly
+    /// transfers ownership.
     ///
     /// # Example
     ///
diff --git a/library/std/src/os/fd/tests.rs b/library/std/src/os/fd/tests.rs
new file mode 100644
index 00000000000..26ef93e3d71
--- /dev/null
+++ b/library/std/src/os/fd/tests.rs
@@ -0,0 +1,34 @@
+#[cfg(any(unix, target_os = "wasi"))]
+#[test]
+fn test_raw_fd() {
+    #[cfg(unix)]
+    use crate::os::unix::io::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
+    #[cfg(target_os = "wasi")]
+    use crate::os::wasi::io::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
+
+    let raw_fd: RawFd = crate::io::stdin().as_raw_fd();
+
+    let stdin_as_file = unsafe { crate::fs::File::from_raw_fd(raw_fd) };
+    assert_eq!(stdin_as_file.as_raw_fd(), raw_fd);
+    assert_eq!(unsafe { BorrowedFd::borrow_raw(raw_fd).as_raw_fd() }, raw_fd);
+    assert_eq!(stdin_as_file.into_raw_fd(), 0);
+}
+
+#[cfg(any(unix, target_os = "wasi"))]
+#[test]
+fn test_fd() {
+    #[cfg(unix)]
+    use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
+    #[cfg(target_os = "wasi")]
+    use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
+
+    let stdin = crate::io::stdin();
+    let fd: BorrowedFd<'_> = stdin.as_fd();
+    let raw_fd: RawFd = fd.as_raw_fd();
+    let owned_fd: OwnedFd = unsafe { OwnedFd::from_raw_fd(raw_fd) };
+
+    let stdin_as_file = crate::fs::File::from(owned_fd);
+
+    assert_eq!(stdin_as_file.as_fd().as_raw_fd(), raw_fd);
+    assert_eq!(Into::<OwnedFd>::into(stdin_as_file).into_raw_fd(), raw_fd);
+}
diff --git a/library/std/src/os/raw/char.md b/library/std/src/os/raw/char.md
deleted file mode 100644
index 375d070516e..00000000000
--- a/library/std/src/os/raw/char.md
+++ /dev/null
@@ -1,9 +0,0 @@
-Equivalent to C's `char` type.
-
-[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. On modern architectures this type will always be either [`i8`] or [`u8`], as they use byte-addresses memory with 8-bit bytes.
-
-C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information.
-
-[C's `char` type]: https://en.wikipedia.org/wiki/C_data_types#Basic_types
-[Rust's `char` type]: char
-[`CStr`]: crate::ffi::CStr
diff --git a/library/std/src/os/raw/double.md b/library/std/src/os/raw/double.md
deleted file mode 100644
index 57f4534829e..00000000000
--- a/library/std/src/os/raw/double.md
+++ /dev/null
@@ -1,6 +0,0 @@
-Equivalent to C's `double` type.
-
-This type will almost always be [`f64`], which is guaranteed to be an [IEEE-754 double-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number with at least the precision of a [`float`], and it may be `f32` or something entirely different from the IEEE-754 standard.
-
-[IEEE-754 double-precision float]: https://en.wikipedia.org/wiki/IEEE_754
-[`float`]: c_float
diff --git a/library/std/src/os/raw/float.md b/library/std/src/os/raw/float.md
deleted file mode 100644
index 61e2abc0518..00000000000
--- a/library/std/src/os/raw/float.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Equivalent to C's `float` type.
-
-This type will almost always be [`f32`], which is guaranteed to be an [IEEE-754 single-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number, and it may have less precision than `f32` or not follow the IEEE-754 standard at all.
-
-[IEEE-754 single-precision float]: https://en.wikipedia.org/wiki/IEEE_754
diff --git a/library/std/src/os/raw/int.md b/library/std/src/os/raw/int.md
deleted file mode 100644
index 8062ff2307a..00000000000
--- a/library/std/src/os/raw/int.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Equivalent to C's `signed int` (`int`) type.
-
-This type will almost always be [`i32`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer that is at least the size of a [`short`]; some systems define it as an [`i16`], for example.
-
-[`short`]: c_short
diff --git a/library/std/src/os/raw/long.md b/library/std/src/os/raw/long.md
deleted file mode 100644
index cc160783f78..00000000000
--- a/library/std/src/os/raw/long.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Equivalent to C's `signed long` (`long`) type.
-
-This type will always be [`i32`] or [`i64`]. Most notably, many Linux-based systems assume an `i64`, but Windows assumes `i32`. The C standard technically only requires that this type be a signed integer that is at least 32 bits and at least the size of an [`int`], although in practice, no system would have a `long` that is neither an `i32` nor `i64`.
-
-[`int`]: c_int
diff --git a/library/std/src/os/raw/longlong.md b/library/std/src/os/raw/longlong.md
deleted file mode 100644
index 49c61bd61f4..00000000000
--- a/library/std/src/os/raw/longlong.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Equivalent to C's `signed long long` (`long long`) type.
-
-This type will almost always be [`i64`], but may differ on some systems. The C standard technically only requires that this type be a signed integer that is at least 64 bits and at least the size of a [`long`], although in practice, no system would have a `long long` that is not an `i64`, as most systems do not have a standardised [`i128`] type.
-
-[`long`]: c_int
diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs
index b6d5199341c..19d0ffb2e39 100644
--- a/library/std/src/os/raw/mod.rs
+++ b/library/std/src/os/raw/mod.rs
@@ -1,156 +1,31 @@
-//! Platform-specific types, as defined by C.
-//!
-//! Code that interacts via FFI will almost certainly be using the
-//! base types provided by C, which aren't nearly as nicely defined
-//! as Rust's primitive types. This module provides types which will
-//! match those defined by C, so that code that interacts with C will
-//! refer to the correct types.
+//! Compatibility module for C platform-specific types. Use [`core::ffi`] instead.
 
 #![stable(feature = "raw_os", since = "1.1.0")]
 
 #[cfg(test)]
 mod tests;
 
-use core::num::*;
-
-macro_rules! type_alias_no_nz {
-    {
-      $Docfile:tt, $Alias:ident = $Real:ty;
-      $( $Cfg:tt )*
-    } => {
-        #[doc = include_str!($Docfile)]
-        $( $Cfg )*
+macro_rules! alias_core_ffi {
+    ($($t:ident)*) => {$(
         #[stable(feature = "raw_os", since = "1.1.0")]
-        pub type $Alias = $Real;
-    }
-}
-
-// To verify that the NonZero types in this file's macro invocations correspond
-//
-//  perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
-//
-// NB this does not check that the main c_* types are right.
-
-macro_rules! type_alias {
-    {
-      $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty;
-      $( $Cfg:tt )*
-    } => {
-        type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* }
-
-        #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")]
-        #[unstable(feature = "raw_os_nonzero", issue = "82363")]
-        $( $Cfg )*
-        pub type $NZAlias = $NZReal;
-    }
+        #[doc = include_str!(concat!("../../../../core/src/ffi/", stringify!($t), ".md"))]
+        // Make this type alias appear cfg-dependent so that Clippy does not suggest
+        // replacing expressions like `0 as c_char` with `0_i8`/`0_u8`. This #[cfg(all())] can be
+        // removed after the false positive in https://github.com/rust-lang/rust-clippy/issues/8093
+        // is fixed.
+        #[cfg(all())]
+        #[doc(cfg(all()))]
+        pub type $t = core::ffi::$t;
+    )*}
 }
 
-type_alias! { "char.md", c_char = c_char_definition::c_char, NonZero_c_char = c_char_definition::NonZero_c_char;
-// Make this type alias appear cfg-dependent so that Clippy does not suggest
-// replacing `0 as c_char` with `0_i8`/`0_u8`. This #[cfg(all())] can be removed
-// after the false positive in https://github.com/rust-lang/rust-clippy/issues/8093
-// is fixed.
-#[cfg(all())]
-#[doc(cfg(all()))] }
-type_alias! { "schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; }
-type_alias! { "uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; }
-type_alias! { "short.md", c_short = i16, NonZero_c_short = NonZeroI16; }
-type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
-type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
-type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
-type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
-#[doc(cfg(all()))]
-#[cfg(any(target_pointer_width = "32", windows))] }
-type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
-#[doc(cfg(all()))]
-#[cfg(any(target_pointer_width = "32", windows))] }
-type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
-#[doc(cfg(all()))]
-#[cfg(all(target_pointer_width = "64", not(windows)))] }
-type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
-#[doc(cfg(all()))]
-#[cfg(all(target_pointer_width = "64", not(windows)))] }
-type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
-type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
-type_alias_no_nz! { "float.md", c_float = f32; }
-type_alias_no_nz! { "double.md", c_double = f64; }
-
-#[stable(feature = "raw_os", since = "1.1.0")]
-#[doc(no_inline)]
-pub use core::ffi::c_void;
-
-/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
-///
-/// This type is currently always [`usize`], however in the future there may be
-/// platforms where this is not the case.
-#[unstable(feature = "c_size_t", issue = "88345")]
-pub type c_size_t = usize;
-
-/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
-///
-/// This type is currently always [`isize`], however in the future there may be
-/// platforms where this is not the case.
-#[unstable(feature = "c_size_t", issue = "88345")]
-pub type c_ptrdiff_t = isize;
-
-/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type.
-///
-/// This type is currently always [`isize`], however in the future there may be
-/// platforms where this is not the case.
-#[unstable(feature = "c_size_t", issue = "88345")]
-pub type c_ssize_t = isize;
-
-mod c_char_definition {
-    cfg_if::cfg_if! {
-        // These are the targets on which c_char is unsigned.
-        if #[cfg(any(
-            all(
-                target_os = "linux",
-                any(
-                    target_arch = "aarch64",
-                    target_arch = "arm",
-                    target_arch = "hexagon",
-                    target_arch = "powerpc",
-                    target_arch = "powerpc64",
-                    target_arch = "s390x",
-                    target_arch = "riscv64",
-                    target_arch = "riscv32"
-                )
-            ),
-            all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
-            all(target_os = "l4re", target_arch = "x86_64"),
-            all(
-                target_os = "freebsd",
-                any(
-                    target_arch = "aarch64",
-                    target_arch = "arm",
-                    target_arch = "powerpc",
-                    target_arch = "powerpc64",
-                    target_arch = "riscv64"
-                )
-            ),
-            all(
-                target_os = "netbsd",
-                any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
-            ),
-            all(target_os = "openbsd", target_arch = "aarch64"),
-            all(
-                target_os = "vxworks",
-                any(
-                    target_arch = "aarch64",
-                    target_arch = "arm",
-                    target_arch = "powerpc64",
-                    target_arch = "powerpc"
-                )
-            ),
-            all(target_os = "fuchsia", target_arch = "aarch64")
-        ))] {
-            pub type c_char = u8;
-            pub type NonZero_c_char = core::num::NonZeroU8;
-        } else {
-            // On every other target, c_char is signed.
-            pub type c_char = i8;
-            pub type NonZero_c_char = core::num::NonZeroI8;
-        }
-    }
+alias_core_ffi! {
+    c_char c_schar c_uchar
+    c_short c_ushort
+    c_int c_uint
+    c_long c_ulong
+    c_longlong c_ulonglong
+    c_float
+    c_double
+    c_void
 }
diff --git a/library/std/src/os/raw/schar.md b/library/std/src/os/raw/schar.md
deleted file mode 100644
index 69879c9f17f..00000000000
--- a/library/std/src/os/raw/schar.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Equivalent to C's `signed char` type.
-
-This type will always be [`i8`], but is included for completeness. It is defined as being a signed integer the same size as a C [`char`].
-
-[`char`]: c_char
diff --git a/library/std/src/os/raw/short.md b/library/std/src/os/raw/short.md
deleted file mode 100644
index 3d1e53d1325..00000000000
--- a/library/std/src/os/raw/short.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Equivalent to C's `signed short` (`short`) type.
-
-This type will almost always be [`i16`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer with at least 16 bits; some systems may define it as `i32`, for example.
-
-[`char`]: c_char
diff --git a/library/std/src/os/raw/uchar.md b/library/std/src/os/raw/uchar.md
deleted file mode 100644
index b633bb7f8da..00000000000
--- a/library/std/src/os/raw/uchar.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Equivalent to C's `unsigned char` type.
-
-This type will always be [`u8`], but is included for completeness. It is defined as being an unsigned integer the same size as a C [`char`].
-
-[`char`]: c_char
diff --git a/library/std/src/os/raw/uint.md b/library/std/src/os/raw/uint.md
deleted file mode 100644
index f3abea35937..00000000000
--- a/library/std/src/os/raw/uint.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Equivalent to C's `unsigned int` type.
-
-This type will almost always be [`u32`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as an [`int`]; some systems define it as a [`u16`], for example.
-
-[`int`]: c_int
diff --git a/library/std/src/os/raw/ulong.md b/library/std/src/os/raw/ulong.md
deleted file mode 100644
index 4ab304e6577..00000000000
--- a/library/std/src/os/raw/ulong.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Equivalent to C's `unsigned long` type.
-
-This type will always be [`u32`] or [`u64`]. Most notably, many Linux-based systems assume an `u64`, but Windows assumes `u32`. The C standard technically only requires that this type be an unsigned integer with the size of a [`long`], although in practice, no system would have a `ulong` that is neither a `u32` nor `u64`.
-
-[`long`]: c_long
diff --git a/library/std/src/os/raw/ulonglong.md b/library/std/src/os/raw/ulonglong.md
deleted file mode 100644
index a27d70e1753..00000000000
--- a/library/std/src/os/raw/ulonglong.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Equivalent to C's `unsigned long long` type.
-
-This type will almost always be [`u64`], but may differ on some systems. The C standard technically only requires that this type be an unsigned integer with the size of a [`long long`], although in practice, no system would have a `long long` that is not a `u64`, as most systems do not have a standardised [`u128`] type.
-
-[`long long`]: c_longlong
diff --git a/library/std/src/os/raw/ushort.md b/library/std/src/os/raw/ushort.md
deleted file mode 100644
index 6928e51b352..00000000000
--- a/library/std/src/os/raw/ushort.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Equivalent to C's `unsigned short` type.
-
-This type will almost always be [`u16`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as a [`short`].
-
-[`short`]: c_short
diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs
index 8df6c54a414..d378d591ba3 100644
--- a/library/std/src/os/windows/io/handle.rs
+++ b/library/std/src/os/windows/io/handle.rs
@@ -28,6 +28,10 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 /// And, it *may* have the value `NULL` (0), which can occur when consoles are
 /// detached from processes, or when `windows_subsystem` is used.
 ///
+/// This type's `.to_owned()` implementation returns another `BorrowedHandle`
+/// rather than an `OwnedHandle`. It just makes a trivial copy of the raw
+/// handle, which is then borrowed under the same lifetime.
+///
 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
 #[derive(Copy, Clone)]
 #[repr(transparent)]
@@ -131,7 +135,7 @@ impl BorrowedHandle<'_> {
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
     #[unstable(feature = "io_safety", issue = "87074")]
-    pub unsafe fn borrow_raw_handle(handle: RawHandle) -> Self {
+    pub unsafe fn borrow_raw(handle: RawHandle) -> Self {
         Self { handle, _phantom: PhantomData }
     }
 }
@@ -210,29 +214,13 @@ impl IntoRawHandle for OwnedHandle {
 }
 
 impl FromRawHandle for OwnedHandle {
-    /// Constructs a new instance of `Self` from the given raw handle.
-    ///
-    /// # Safety
-    ///
-    /// The resource pointed to by `handle` must be open and suitable for
-    /// assuming ownership. The resource must not require any cleanup other
-    /// than `CloseHandle`.
-    ///
-    /// In particular, it must not be used with handles to open registry
-    /// keys which need to be closed with [`RegCloseKey`] instead.
-    ///
-    /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
-    /// sometimes a valid handle value. See [here] for the full story.
-    ///
-    /// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
-    /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
     unsafe fn from_raw_handle(handle: RawHandle) -> Self {
         Self { handle }
     }
 }
 
-impl FromRawHandle for HandleOrNull {
+impl HandleOrNull {
     /// Constructs a new instance of `Self` from the given `RawHandle` returned
     /// from a Windows API that uses null to indicate failure, such as
     /// `CreateThread`.
@@ -242,18 +230,18 @@ impl FromRawHandle for HandleOrNull {
     ///
     /// # Safety
     ///
-    /// The resource pointed to by `handle` must be either open and otherwise
-    /// unowned, or null. Note that not all Windows APIs use null for errors;
-    /// see [here] for the full story.
+    /// The passed `handle` value must either satisfy the safety requirements
+    /// of [`FromRawHandle::from_raw_handle`], or be null. Note that not all
+    /// Windows APIs use null for errors; see [here] for the full story.
     ///
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
-    unsafe fn from_raw_handle(handle: RawHandle) -> Self {
+    pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
         Self(OwnedHandle::from_raw_handle(handle))
     }
 }
 
-impl FromRawHandle for HandleOrInvalid {
+impl HandleOrInvalid {
     /// Constructs a new instance of `Self` from the given `RawHandle` returned
     /// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate
     /// failure, such as `CreateFileW`.
@@ -263,14 +251,14 @@ impl FromRawHandle for HandleOrInvalid {
     ///
     /// # Safety
     ///
-    /// The resource pointed to by `handle` must be either open and otherwise
-    /// unowned, null, or equal to `INVALID_HANDLE_VALUE` (-1). Note that not
-    /// all Windows APIs use `INVALID_HANDLE_VALUE` for errors; see [here] for
-    /// the full story.
+    /// The passed `handle` value must either satisfy the safety requirements
+    /// of [`FromRawHandle::from_raw_handle`], or be
+    /// `INVALID_HANDLE_VALUE` (-1). Note that not all Windows APIs use
+    /// `INVALID_HANDLE_VALUE` for errors; see [here] for the full story.
     ///
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
-    unsafe fn from_raw_handle(handle: RawHandle) -> Self {
+    pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
         Self(OwnedHandle::from_raw_handle(handle))
     }
 }
@@ -345,7 +333,7 @@ impl AsHandle for OwnedHandle {
         // Safety: `OwnedHandle` and `BorrowedHandle` have the same validity
         // invariants, and the `BorrowdHandle` is bounded by the lifetime
         // of `&self`.
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -373,49 +361,49 @@ impl From<OwnedHandle> for fs::File {
 impl AsHandle for crate::io::Stdin {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl<'a> AsHandle for crate::io::StdinLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl AsHandle for crate::io::Stdout {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl<'a> AsHandle for crate::io::StdoutLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl AsHandle for crate::io::Stderr {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl<'a> AsHandle for crate::io::StderrLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl AsHandle for crate::process::ChildStdin {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -429,7 +417,7 @@ impl From<crate::process::ChildStdin> for OwnedHandle {
 impl AsHandle for crate::process::ChildStdout {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -443,7 +431,7 @@ impl From<crate::process::ChildStdout> for OwnedHandle {
 impl AsHandle for crate::process::ChildStderr {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -457,7 +445,7 @@ impl From<crate::process::ChildStderr> for OwnedHandle {
 impl<T> AsHandle for crate::thread::JoinHandle<T> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs
index c7f122048a1..48c5fd358d9 100644
--- a/library/std/src/os/windows/io/raw.rs
+++ b/library/std/src/os/windows/io/raw.rs
@@ -5,6 +5,8 @@
 use crate::fs;
 use crate::io;
 use crate::net;
+#[cfg(doc)]
+use crate::os::windows::io::{AsHandle, AsSocket};
 use crate::os::windows::io::{OwnedHandle, OwnedSocket};
 use crate::os::windows::raw;
 use crate::sys;
@@ -22,7 +24,15 @@ pub type RawSocket = raw::SOCKET;
 /// Extracts raw handles.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsRawHandle {
-    /// Extracts the raw handle, without taking any ownership.
+    /// Extracts the raw handle.
+    ///
+    /// This function is typically used to **borrow** an owned handle.
+    /// When used in this way, this method does **not** pass ownership of the
+    /// raw handle to the caller, and the handle is only guaranteed
+    /// to be valid while the original object has not yet been destroyed.
+    ///
+    /// However, borrowing is not strictly required. See [`AsHandle::as_handle`]
+    /// for an API which strictly borrows a handle.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn as_raw_handle(&self) -> RawHandle;
 }
@@ -32,15 +42,28 @@ pub trait AsRawHandle {
 pub trait FromRawHandle {
     /// Constructs a new I/O object from the specified raw handle.
     ///
-    /// This function will **consume ownership** of the handle given,
-    /// passing responsibility for closing the handle to the returned
-    /// object.
+    /// This function is typically used to **consume ownership** of the handle
+    /// given, passing responsibility for closing the handle to the returned
+    /// object. When used in this way, the returned object
+    /// will take responsibility for closing it when the object goes out of
+    /// scope.
+    ///
+    /// However, consuming ownership is not strictly required. Use a
+    /// `From<OwnedHandle>::from` implementation for an API which strictly
+    /// consumes ownership.
+    ///
+    /// # Safety
     ///
-    /// This function is also unsafe as the primitives currently returned
-    /// have the contract that they are the sole owner of the file
-    /// descriptor they are wrapping. Usage of this function could
-    /// accidentally allow violating this contract which can cause memory
-    /// unsafety in code that relies on it being true.
+    /// The `handle` passed in must:
+    ///   - be a valid an open handle,
+    ///   - be a handle for a resource that may be freed via [`CloseHandle`]
+    ///     (as opposed to `RegCloseKey` or other close functions).
+    ///
+    /// Note that the handle *may* have the value `INVALID_HANDLE_VALUE` (-1),
+    /// which is sometimes a valid handle value. See [here] for the full story.
+    ///
+    /// [`CloseHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
+    /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[stable(feature = "from_raw_os", since = "1.1.0")]
     unsafe fn from_raw_handle(handle: RawHandle) -> Self;
 }
@@ -51,9 +74,13 @@ pub trait FromRawHandle {
 pub trait IntoRawHandle {
     /// Consumes this object, returning the raw underlying handle.
     ///
-    /// This function **transfers ownership** of the underlying handle to the
-    /// caller. Callers are then the unique owners of the handle and must close
-    /// it once it's no longer needed.
+    /// This function is typically used to **transfer ownership** of the underlying
+    /// handle to the caller. When used in this way, callers are then the unique
+    /// owners of the handle and must close it once it's no longer needed.
+    ///
+    /// However, transferring ownership is not strictly required. Use a
+    /// `Into<OwnedHandle>::into` implementation for an API which strictly
+    /// transfers ownership.
     #[stable(feature = "into_raw_os", since = "1.4.0")]
     fn into_raw_handle(self) -> RawHandle;
 }
@@ -130,7 +157,15 @@ impl IntoRawHandle for fs::File {
 /// Extracts raw sockets.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsRawSocket {
-    /// Extracts the underlying raw socket from this object.
+    /// Extracts the raw socket.
+    ///
+    /// This function is typically used to **borrow** an owned socket.
+    /// When used in this way, this method does **not** pass ownership of the
+    /// raw socket to the caller, and the socket is only guaranteed
+    /// to be valid while the original object has not yet been destroyed.
+    ///
+    /// However, borrowing is not strictly required. See [`AsSocket::as_socket`]
+    /// for an API which strictly borrows a socket.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn as_raw_socket(&self) -> RawSocket;
 }
@@ -138,16 +173,25 @@ pub trait AsRawSocket {
 /// Creates I/O objects from raw sockets.
 #[stable(feature = "from_raw_os", since = "1.1.0")]
 pub trait FromRawSocket {
-    /// Creates a new I/O object from the given raw socket.
+    /// Constructs a new I/O object from the specified raw socket.
+    ///
+    /// This function is typically used to **consume ownership** of the socket
+    /// given, passing responsibility for closing the socket to the returned
+    /// object. When used in this way, the returned object
+    /// will take responsibility for closing it when the object goes out of
+    /// scope.
     ///
-    /// This function will **consume ownership** of the socket provided and
-    /// it will be closed when the returned object goes out of scope.
+    /// However, consuming ownership is not strictly required. Use a
+    /// `From<OwnedSocket>::from` implementation for an API which strictly
+    /// consumes ownership.
     ///
-    /// This function is also unsafe as the primitives currently returned
-    /// have the contract that they are the sole owner of the file
-    /// descriptor they are wrapping. Usage of this function could
-    /// accidentally allow violating this contract which can cause memory
-    /// unsafety in code that relies on it being true.
+    /// # Safety
+    ///
+    /// The `socket` passed in must:
+    ///   - be a valid an open socket,
+    ///   - be a socket that may be freed via [`closesocket`].
+    ///
+    /// [`closesocket`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket
     #[stable(feature = "from_raw_os", since = "1.1.0")]
     unsafe fn from_raw_socket(sock: RawSocket) -> Self;
 }
@@ -158,9 +202,13 @@ pub trait FromRawSocket {
 pub trait IntoRawSocket {
     /// Consumes this object, returning the raw underlying socket.
     ///
-    /// This function **transfers ownership** of the underlying socket to the
-    /// caller. Callers are then the unique owners of the socket and must close
-    /// it once it's no longer needed.
+    /// This function is typically used to **transfer ownership** of the underlying
+    /// socket to the caller. When used in this way, callers are then the unique
+    /// owners of the socket and must close it once it's no longer needed.
+    ///
+    /// However, transferring ownership is not strictly required. Use a
+    /// `Into<OwnedSocket>::into` implementation for an API which strictly
+    /// transfers ownership.
     #[stable(feature = "into_raw_os", since = "1.4.0")]
     fn into_raw_socket(self) -> RawSocket;
 }
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index 2f13eb77a1b..a6b979cc22b 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -21,6 +21,10 @@ use crate::sys::cvt;
 /// so it can be used in FFI in places where a socket is passed as an argument,
 /// it is not captured or consumed, and it never has the value
 /// `INVALID_SOCKET`.
+///
+/// This type's `.to_owned()` implementation returns another `BorrowedSocket`
+/// rather than an `OwnedSocket`. It just makes a trivial copy of the raw
+/// socket, which is then borrowed under the same lifetime.
 #[derive(Copy, Clone)]
 #[repr(transparent)]
 #[rustc_layout_scalar_valid_range_start(0)]
@@ -67,7 +71,7 @@ impl BorrowedSocket<'_> {
     /// `INVALID_SOCKET`.
     #[inline]
     #[unstable(feature = "io_safety", issue = "87074")]
-    pub unsafe fn borrow_raw_socket(socket: RawSocket) -> Self {
+    pub unsafe fn borrow_raw(socket: RawSocket) -> Self {
         debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket);
         Self { socket, _phantom: PhantomData }
     }
@@ -168,13 +172,6 @@ impl IntoRawSocket for OwnedSocket {
 }
 
 impl FromRawSocket for OwnedSocket {
-    /// Constructs a new instance of `Self` from the given raw socket.
-    ///
-    /// # Safety
-    ///
-    /// The resource pointed to by `socket` must be open and suitable for
-    /// assuming ownership. The resource must not require cleanup other than
-    /// `closesocket`.
     #[inline]
     unsafe fn from_raw_socket(socket: RawSocket) -> Self {
         debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket);
@@ -239,14 +236,14 @@ impl AsSocket for OwnedSocket {
         // Safety: `OwnedSocket` and `BorrowedSocket` have the same validity
         // invariants, and the `BorrowdSocket` is bounded by the lifetime
         // of `&self`.
-        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
+        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
     }
 }
 
 impl AsSocket for crate::net::TcpStream {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
-        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
+        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
     }
 }
 
@@ -267,7 +264,7 @@ impl From<OwnedSocket> for crate::net::TcpStream {
 impl AsSocket for crate::net::TcpListener {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
-        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
+        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
     }
 }
 
@@ -288,7 +285,7 @@ impl From<OwnedSocket> for crate::net::TcpListener {
 impl AsSocket for crate::net::UdpSocket {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
-        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
+        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
     }
 }
 
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index b268ef5c364..0b6cdb923bd 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -384,11 +384,8 @@ pub fn current_exe() -> io::Result<PathBuf> {
     if let Ok(path) = crate::fs::read_link("/proc/self/path/a.out") {
         Ok(path)
     } else {
-        extern "C" {
-            fn getexecname() -> *const c_char;
-        }
         unsafe {
-            let path = getexecname();
+            let path = libc::getexecname();
             if path.is_null() {
                 Err(io::Error::last_os_error())
             } else {
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 9fc2d9fce4d..07a0339c066 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -3,11 +3,11 @@ use crate::fmt;
 use crate::io::{self, Error, ErrorKind};
 use crate::mem;
 use crate::num::NonZeroI32;
-use crate::os::raw::NonZero_c_int;
 use crate::ptr;
 use crate::sys;
 use crate::sys::cvt;
 use crate::sys::process::process_common::*;
+use core::ffi::NonZero_c_int;
 
 #[cfg(target_os = "linux")]
 use crate::os::linux::process::PidFd;
diff --git a/library/std/src/sys/unix/process/process_unsupported.rs b/library/std/src/sys/unix/process/process_unsupported.rs
index 7d549d060fd..bbabdf787d9 100644
--- a/library/std/src/sys/unix/process/process_unsupported.rs
+++ b/library/std/src/sys/unix/process/process_unsupported.rs
@@ -3,12 +3,12 @@ use crate::fmt;
 use crate::io;
 use crate::io::ErrorKind;
 use crate::num::NonZeroI32;
-use crate::os::raw::NonZero_c_int;
 use crate::sys;
 use crate::sys::cvt;
 use crate::sys::pipe::AnonPipe;
 use crate::sys::process::process_common::*;
 use crate::sys::unix::unsupported::*;
+use core::ffi::NonZero_c_int;
 
 use libc::{c_int, pid_t};
 
diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs
index c6714d3aae2..56ed6cfeb6a 100644
--- a/library/std/src/sys/unix/process/process_vxworks.rs
+++ b/library/std/src/sys/unix/process/process_vxworks.rs
@@ -2,11 +2,11 @@ use crate::convert::{TryFrom, TryInto};
 use crate::fmt;
 use crate::io::{self, Error, ErrorKind};
 use crate::num::NonZeroI32;
-use crate::os::raw::NonZero_c_int;
 use crate::sys;
 use crate::sys::cvt;
 use crate::sys::process::process_common::*;
 use crate::sys_common::thread;
+use core::ffi::NonZero_c_int;
 use libc::RTP_ID;
 use libc::{self, c_char, c_int};
 
diff --git a/library/std/src/sys/unix/stdio.rs b/library/std/src/sys/unix/stdio.rs
index b359987595d..e4d83ba0ffd 100644
--- a/library/std/src/sys/unix/stdio.rs
+++ b/library/std/src/sys/unix/stdio.rs
@@ -96,7 +96,7 @@ pub fn panic_output() -> Option<impl io::Write> {
 impl AsFd for io::Stdin {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDIN_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDIN_FILENO) }
     }
 }
 
@@ -104,7 +104,7 @@ impl AsFd for io::Stdin {
 impl<'a> AsFd for io::StdinLock<'a> {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDIN_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDIN_FILENO) }
     }
 }
 
@@ -112,7 +112,7 @@ impl<'a> AsFd for io::StdinLock<'a> {
 impl AsFd for io::Stdout {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDOUT_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDOUT_FILENO) }
     }
 }
 
@@ -120,7 +120,7 @@ impl AsFd for io::Stdout {
 impl<'a> AsFd for io::StdoutLock<'a> {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDOUT_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDOUT_FILENO) }
     }
 }
 
@@ -128,7 +128,7 @@ impl<'a> AsFd for io::StdoutLock<'a> {
 impl AsFd for io::Stderr {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDERR_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDERR_FILENO) }
     }
 }
 
@@ -136,6 +136,6 @@ impl AsFd for io::Stderr {
 impl<'a> AsFd for io::StderrLock<'a> {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDERR_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDERR_FILENO) }
     }
 }
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index cf8cf5ad49f..ff01ce27333 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -279,10 +279,15 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
         ))] {
             #[cfg(any(target_os = "android", target_os = "linux"))]
             {
+                let quota = cgroup2_quota().max(1);
                 let mut set: libc::cpu_set_t = unsafe { mem::zeroed() };
-                if unsafe { libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
-                    let count = unsafe { libc::CPU_COUNT(&set) };
-                    return Ok(unsafe { NonZeroUsize::new_unchecked(count as usize) });
+                unsafe {
+                    if libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) == 0 {
+                        let count = libc::CPU_COUNT(&set) as usize;
+                        let count = count.min(quota);
+                        // SAFETY: affinity mask can't be empty and the quota gets clamped to a minimum of 1
+                        return Ok(NonZeroUsize::new_unchecked(count));
+                    }
                 }
             }
             match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
@@ -368,6 +373,80 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
     }
 }
 
+/// Returns cgroup CPU quota in core-equivalents, rounded down, or usize::MAX if the quota cannot
+/// be determined or is not set.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+fn cgroup2_quota() -> usize {
+    use crate::ffi::OsString;
+    use crate::fs::{try_exists, File};
+    use crate::io::Read;
+    use crate::os::unix::ffi::OsStringExt;
+    use crate::path::PathBuf;
+
+    let mut quota = usize::MAX;
+
+    let _: Option<()> = try {
+        let mut buf = Vec::with_capacity(128);
+        // find our place in the cgroup hierarchy
+        File::open("/proc/self/cgroup").ok()?.read_to_end(&mut buf).ok()?;
+        let cgroup_path = buf
+            .split(|&c| c == b'\n')
+            .filter_map(|line| {
+                let mut fields = line.splitn(3, |&c| c == b':');
+                // expect cgroupv2 which has an empty 2nd field
+                if fields.nth(1) != Some(b"") {
+                    return None;
+                }
+                let path = fields.last()?;
+                // skip leading slash
+                Some(path[1..].to_owned())
+            })
+            .next()?;
+        let cgroup_path = PathBuf::from(OsString::from_vec(cgroup_path));
+
+        let mut path = PathBuf::with_capacity(128);
+        let mut read_buf = String::with_capacity(20);
+
+        let cgroup_mount = "/sys/fs/cgroup";
+
+        path.push(cgroup_mount);
+        path.push(&cgroup_path);
+
+        path.push("cgroup.controllers");
+
+        // skip if we're not looking at cgroup2
+        if matches!(try_exists(&path), Err(_) | Ok(false)) {
+            return usize::MAX;
+        };
+
+        path.pop();
+
+        while path.starts_with(cgroup_mount) {
+            path.push("cpu.max");
+
+            read_buf.clear();
+
+            if File::open(&path).and_then(|mut f| f.read_to_string(&mut read_buf)).is_ok() {
+                let raw_quota = read_buf.lines().next()?;
+                let mut raw_quota = raw_quota.split(' ');
+                let limit = raw_quota.next()?;
+                let period = raw_quota.next()?;
+                match (limit.parse::<usize>(), period.parse::<usize>()) {
+                    (Ok(limit), Ok(period)) => {
+                        quota = quota.min(limit / period);
+                    }
+                    _ => {}
+                }
+            }
+
+            path.pop(); // pop filename
+            path.pop(); // pop dir
+        }
+    };
+
+    quota
+}
+
 #[cfg(all(
     not(target_os = "linux"),
     not(target_os = "freebsd"),
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index c7b6290693e..2affd7e75b0 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -5,9 +5,9 @@
 #![unstable(issue = "none", feature = "windows_c")]
 
 use crate::mem;
-use crate::os::raw::NonZero_c_ulong;
 use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort};
 use crate::ptr;
+use core::ffi::NonZero_c_ulong;
 
 use libc::{c_void, size_t, wchar_t};
 
diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs
index aa6400aeefa..5de12313784 100644
--- a/library/std/src/sys/windows/net.rs
+++ b/library/std/src/sys/windows/net.rs
@@ -407,11 +407,11 @@ impl Socket {
     }
 
     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
-        net::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BYTE)
+        net::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BOOL)
     }
 
     pub fn nodelay(&self) -> io::Result<bool> {
-        let raw: c::BYTE = net::getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?;
+        let raw: c::BOOL = net::getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?;
         Ok(raw != 0)
     }
 
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 70b29d4a92e..3b7cdd55a08 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -58,21 +58,36 @@ cfg_if::cfg_if! {
 // sockaddr and misc bindings
 ////////////////////////////////////////////////////////////////////////////////
 
-pub fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int, payload: T) -> io::Result<()> {
+pub fn setsockopt<T>(
+    sock: &Socket,
+    level: c_int,
+    option_name: c_int,
+    option_value: T,
+) -> io::Result<()> {
     unsafe {
-        let payload = &payload as *const T as *const c_void;
-        cvt(c::setsockopt(sock.as_raw(), opt, val, payload, mem::size_of::<T>() as c::socklen_t))?;
+        cvt(c::setsockopt(
+            sock.as_raw(),
+            level,
+            option_name,
+            &option_value as *const T as *const _,
+            mem::size_of::<T>() as c::socklen_t,
+        ))?;
         Ok(())
     }
 }
 
-pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int, val: c_int) -> io::Result<T> {
+pub fn getsockopt<T: Copy>(sock: &Socket, level: c_int, option_name: c_int) -> io::Result<T> {
     unsafe {
-        let mut slot: T = mem::zeroed();
-        let mut len = mem::size_of::<T>() as c::socklen_t;
-        cvt(c::getsockopt(sock.as_raw(), opt, val, &mut slot as *mut _ as *mut _, &mut len))?;
-        assert_eq!(len as usize, mem::size_of::<T>());
-        Ok(slot)
+        let mut option_value: T = mem::zeroed();
+        let mut option_len = mem::size_of::<T>() as c::socklen_t;
+        cvt(c::getsockopt(
+            sock.as_raw(),
+            level,
+            option_name,
+            &mut option_value as *mut T as *mut _,
+            &mut option_len,
+        ))?;
+        Ok(option_value)
     }
 }
 
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 1be3ed757ba..2464a0e2e47 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -177,7 +177,7 @@ macro_rules! thread_local {
 macro_rules! __thread_local_inner {
     // used to generate the `LocalKey` value for const-initialized thread locals
     (@key $t:ty, const $init:expr) => {{
-        #[cfg_attr(not(windows), inline)] // see comments below
+        #[cfg_attr(not(windows), inline(always))] // see comments below
         unsafe fn __getit() -> $crate::option::Option<&'static $t> {
             const INIT_EXPR: $t = $init;
 
@@ -297,7 +297,7 @@ macro_rules! __thread_local_inner {
             // gets the pessimistic path for now where it's never inlined.
             //
             // The issue of "should enable on Windows sometimes" is #84933
-            #[cfg_attr(not(windows), inline)]
+            #[cfg_attr(not(windows), inline(always))]
             unsafe fn __getit() -> $crate::option::Option<&'static $t> {
                 #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
                 static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index f8d790c3785..09d1e714ab6 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -1482,7 +1482,7 @@ fn _assert_sync_and_send() {
 ///
 /// Parallelism is a resource. A given machine provides a certain capacity for
 /// parallelism, i.e., a bound on the number of computations it can perform
-/// simultaneously. This number often corresponds to the amount of CPUs or
+/// simultaneously. This number often corresponds to the amount of CPUs a
 /// computer has, but it may diverge in various cases.
 ///
 /// Host environments such as VMs or container orchestrators may want to
@@ -1524,7 +1524,10 @@ fn _assert_sync_and_send() {
 ///
 /// On Linux:
 /// - It may overcount the amount of parallelism available when limited by a
-///   process-wide affinity mask, or when affected by cgroup limits.
+///   process-wide affinity mask or cgroup quotas and cgroup2 fs or `sched_getaffinity()` can't be
+///   queried, e.g. due to sandboxing.
+/// - It may undercount the amount of parallelism if the current thread's affinity mask
+///   does not reflect the process' cpuset, e.g. due to pinned threads.
 ///
 /// On all targets:
 /// - It may overcount the amount of parallelism available when running in a VM