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.rs1
-rw-r--r--library/std/src/collections/hash/set.rs1
-rw-r--r--library/std/src/ffi/os_str.rs2
-rw-r--r--library/std/src/fs.rs3
-rw-r--r--library/std/src/lazy/tests.rs5
-rw-r--r--library/std/src/lib.rs3
-rw-r--r--library/std/src/net/ip.rs69
-rw-r--r--library/std/src/os/linux/raw.rs16
-rw-r--r--library/std/src/prelude/v1.rs5
-rw-r--r--library/std/src/sync/once.rs20
-rw-r--r--library/std/src/sync/once/tests.rs4
-rw-r--r--library/std/src/sys/unix/os.rs19
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs6
-rw-r--r--library/std/src/sys/wasi/ext/fs.rs8
-rw-r--r--library/std/src/sys/wasm/thread.rs2
-rw-r--r--library/std/src/sys/windows/mutex.rs2
-rw-r--r--library/std/src/sys_common/rwlock.rs59
-rw-r--r--library/std/src/thread/mod.rs9
18 files changed, 193 insertions, 41 deletions
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 28a25572dd8..27f7191831d 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -859,6 +859,7 @@ where
     /// assert_eq!(map.remove(&1), Some("a"));
     /// assert_eq!(map.remove(&1), None);
     /// ```
+    #[doc(alias = "delete")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index b08510d6b01..912e975aa0a 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -874,6 +874,7 @@ where
     /// assert_eq!(set.remove(&2), true);
     /// assert_eq!(set.remove(&2), false);
     /// ```
+    #[doc(alias = "delete")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 21060182d60..c9c8f68cd9c 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -826,7 +826,7 @@ impl OsStr {
     /// assert!(!OsString::from("Ferrös").eq_ignore_ascii_case("FERRÖS"));
     /// ```
     #[unstable(feature = "osstring_ascii", issue = "70516")]
-    pub fn eq_ignore_ascii_case<S: ?Sized + AsRef<OsStr>>(&self, other: &S) -> bool {
+    pub fn eq_ignore_ascii_case<S: AsRef<OsStr>>(&self, other: S) -> bool {
         self.inner.eq_ignore_ascii_case(&other.as_ref().inner)
     }
 }
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index e2d4f2e6a56..43119c36cfe 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -1524,6 +1524,7 @@ impl AsInner<fs_imp::DirEntry> for DirEntry {
 ///     Ok(())
 /// }
 /// ```
+#[doc(alias = "delete")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
     fs_imp::unlink(path.as_ref())
@@ -1958,6 +1959,7 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///     Ok(())
 /// }
 /// ```
+#[doc(alias = "delete")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
     fs_imp::rmdir(path.as_ref())
@@ -1995,6 +1997,7 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///     Ok(())
 /// }
 /// ```
+#[doc(alias = "delete")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
     fs_imp::remove_dir_all(path.as_ref())
diff --git a/library/std/src/lazy/tests.rs b/library/std/src/lazy/tests.rs
index a170edbd997..83466eb0904 100644
--- a/library/std/src/lazy/tests.rs
+++ b/library/std/src/lazy/tests.rs
@@ -48,6 +48,7 @@ fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) ->
 }
 
 #[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
 fn sync_once_cell() {
     static ONCE_CELL: SyncOnceCell<i32> = SyncOnceCell::new();
 
@@ -81,6 +82,7 @@ fn sync_once_cell_get_unchecked() {
 }
 
 #[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
 fn sync_once_cell_drop() {
     static DROP_CNT: AtomicUsize = AtomicUsize::new(0);
     struct Dropper;
@@ -158,6 +160,7 @@ fn into_inner() {
 }
 
 #[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
 fn sync_lazy_new() {
     static CALLED: AtomicUsize = AtomicUsize::new(0);
     static SYNC_LAZY: SyncLazy<i32> = SyncLazy::new(|| {
@@ -204,6 +207,7 @@ fn sync_lazy_default() {
 }
 
 #[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
 fn static_sync_lazy() {
     static XS: SyncLazy<Vec<i32>> = SyncLazy::new(|| {
         let mut xs = Vec::new();
@@ -279,6 +283,7 @@ fn eval_once_macro() {
 }
 
 #[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
 fn sync_once_cell_does_not_leak_partially_constructed_boxes() {
     static ONCE_CELL: SyncOnceCell<String> = SyncOnceCell::new();
 
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index b6929f59395..961cff661e3 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -329,7 +329,6 @@
 #![feature(unwind_attributes)]
 #![feature(vec_into_raw_parts)]
 #![feature(vec_spare_capacity)]
-#![feature(wake_trait)]
 // NB: the above list is sorted to minimize merge conflicts.
 #![default_lib_allocator]
 
@@ -508,7 +507,7 @@ pub mod task {
     pub use core::task::*;
 
     #[doc(inline)]
-    #[unstable(feature = "wake_trait", issue = "69912")]
+    #[stable(feature = "wake_trait", since = "1.51.0")]
     pub use alloc::task::*;
 }
 
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index a8a4127d40a..2aa305d7f83 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -150,6 +150,7 @@ impl IpAddr {
     /// ```
     #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ip_shared", since = "1.12.0")]
+    #[inline]
     pub const fn is_unspecified(&self) -> bool {
         match self {
             IpAddr::V4(ip) => ip.is_unspecified(),
@@ -172,6 +173,7 @@ impl IpAddr {
     /// ```
     #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ip_shared", since = "1.12.0")]
+    #[inline]
     pub const fn is_loopback(&self) -> bool {
         match self {
             IpAddr::V4(ip) => ip.is_loopback(),
@@ -195,6 +197,7 @@ impl IpAddr {
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true);
     /// ```
     #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
+    #[inline]
     pub const fn is_global(&self) -> bool {
         match self {
             IpAddr::V4(ip) => ip.is_global(),
@@ -217,6 +220,7 @@ impl IpAddr {
     /// ```
     #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ip_shared", since = "1.12.0")]
+    #[inline]
     pub const fn is_multicast(&self) -> bool {
         match self {
             IpAddr::V4(ip) => ip.is_multicast(),
@@ -243,6 +247,7 @@ impl IpAddr {
     /// );
     /// ```
     #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
+    #[inline]
     pub const fn is_documentation(&self) -> bool {
         match self {
             IpAddr::V4(ip) => ip.is_documentation(),
@@ -265,6 +270,7 @@ impl IpAddr {
     /// ```
     #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
+    #[inline]
     pub const fn is_ipv4(&self) -> bool {
         matches!(self, IpAddr::V4(_))
     }
@@ -284,6 +290,7 @@ impl IpAddr {
     /// ```
     #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
+    #[inline]
     pub const fn is_ipv6(&self) -> bool {
         matches!(self, IpAddr::V6(_))
     }
@@ -303,6 +310,7 @@ impl Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
         // `s_addr` is stored as BE on all machine and the array is in BE order.
         // So the native endian conversion method is used so that it's never swapped.
@@ -360,6 +368,7 @@ impl Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub const fn octets(&self) -> [u8; 4] {
         // This returns the order we want because s_addr is stored in big-endian.
         self.inner.s_addr.to_ne_bytes()
@@ -382,6 +391,7 @@ impl Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
     #[stable(feature = "ip_shared", since = "1.12.0")]
+    #[inline]
     pub const fn is_unspecified(&self) -> bool {
         self.inner.s_addr == 0
     }
@@ -402,6 +412,7 @@ impl Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
+    #[inline]
     pub const fn is_loopback(&self) -> bool {
         self.octets()[0] == 127
     }
@@ -431,6 +442,7 @@ impl Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
+    #[inline]
     pub const fn is_private(&self) -> bool {
         match self.octets() {
             [10, ..] => true,
@@ -457,6 +469,7 @@ impl Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
+    #[inline]
     pub const fn is_link_local(&self) -> bool {
         matches!(self.octets(), [169, 254, ..])
     }
@@ -531,6 +544,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[inline]
     pub const fn is_global(&self) -> bool {
         // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
         // globally routable addresses in the 192.0.0.0/24 range.
@@ -568,6 +582,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[inline]
     pub const fn is_shared(&self) -> bool {
         self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
     }
@@ -600,6 +615,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[inline]
     pub const fn is_ietf_protocol_assignment(&self) -> bool {
         self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0
     }
@@ -623,6 +639,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[inline]
     pub const fn is_benchmarking(&self) -> bool {
         self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
     }
@@ -655,6 +672,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[inline]
     pub const fn is_reserved(&self) -> bool {
         self.octets()[0] & 240 == 240 && !self.is_broadcast()
     }
@@ -677,6 +695,7 @@ impl Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
+    #[inline]
     pub const fn is_multicast(&self) -> bool {
         self.octets()[0] >= 224 && self.octets()[0] <= 239
     }
@@ -697,6 +716,7 @@ impl Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
+    #[inline]
     pub const fn is_broadcast(&self) -> bool {
         u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
     }
@@ -723,6 +743,7 @@ impl Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
+    #[inline]
     pub const fn is_documentation(&self) -> bool {
         match self.octets() {
             [192, 0, 2, _] => true,
@@ -753,6 +774,7 @@ impl Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
         let [a, b, c, d] = self.octets();
         Ipv6Addr {
@@ -776,6 +798,7 @@ impl Ipv4Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
         let [a, b, c, d] = self.octets();
         Ipv6Addr {
@@ -817,6 +840,7 @@ impl From<Ipv4Addr> for IpAddr {
     ///     IpAddr::from(addr)
     /// )
     /// ```
+    #[inline]
     fn from(ipv4: Ipv4Addr) -> IpAddr {
         IpAddr::V4(ipv4)
     }
@@ -838,6 +862,7 @@ impl From<Ipv6Addr> for IpAddr {
     ///     IpAddr::from(addr)
     /// );
     /// ```
+    #[inline]
     fn from(ipv6: Ipv6Addr) -> IpAddr {
         IpAddr::V6(ipv6)
     }
@@ -875,6 +900,7 @@ impl fmt::Debug for Ipv4Addr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Clone for Ipv4Addr {
+    #[inline]
     fn clone(&self) -> Ipv4Addr {
         *self
     }
@@ -882,6 +908,7 @@ impl Clone for Ipv4Addr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialEq for Ipv4Addr {
+    #[inline]
     fn eq(&self, other: &Ipv4Addr) -> bool {
         self.inner.s_addr == other.inner.s_addr
     }
@@ -889,6 +916,7 @@ impl PartialEq for Ipv4Addr {
 
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialEq<Ipv4Addr> for IpAddr {
+    #[inline]
     fn eq(&self, other: &Ipv4Addr) -> bool {
         match self {
             IpAddr::V4(v4) => v4 == other,
@@ -899,6 +927,7 @@ impl PartialEq<Ipv4Addr> for IpAddr {
 
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialEq<IpAddr> for Ipv4Addr {
+    #[inline]
     fn eq(&self, other: &IpAddr) -> bool {
         match other {
             IpAddr::V4(v4) => self == v4,
@@ -912,6 +941,7 @@ impl Eq for Ipv4Addr {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl hash::Hash for Ipv4Addr {
+    #[inline]
     fn hash<H: hash::Hasher>(&self, s: &mut H) {
         // NOTE:
         // * hash in big endian order
@@ -923,6 +953,7 @@ impl hash::Hash for Ipv4Addr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialOrd for Ipv4Addr {
+    #[inline]
     fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
         Some(self.cmp(other))
     }
@@ -930,6 +961,7 @@ impl PartialOrd for Ipv4Addr {
 
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialOrd<Ipv4Addr> for IpAddr {
+    #[inline]
     fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
         match self {
             IpAddr::V4(v4) => v4.partial_cmp(other),
@@ -940,6 +972,7 @@ impl PartialOrd<Ipv4Addr> for IpAddr {
 
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialOrd<IpAddr> for Ipv4Addr {
+    #[inline]
     fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
         match other {
             IpAddr::V4(v4) => self.partial_cmp(v4),
@@ -950,6 +983,7 @@ impl PartialOrd<IpAddr> for Ipv4Addr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Ord for Ipv4Addr {
+    #[inline]
     fn cmp(&self, other: &Ipv4Addr) -> Ordering {
         // Compare as native endian
         u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
@@ -974,6 +1008,7 @@ impl From<Ipv4Addr> for u32 {
     /// let addr = Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe);
     /// assert_eq!(0xcafebabe, u32::from(addr));
     /// ```
+    #[inline]
     fn from(ip: Ipv4Addr) -> u32 {
         let ip = ip.octets();
         u32::from_be_bytes(ip)
@@ -992,6 +1027,7 @@ impl From<u32> for Ipv4Addr {
     /// let addr = Ipv4Addr::from(0xcafebabe);
     /// assert_eq!(Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe), addr);
     /// ```
+    #[inline]
     fn from(ip: u32) -> Ipv4Addr {
         Ipv4Addr::from(ip.to_be_bytes())
     }
@@ -1009,6 +1045,7 @@ impl From<[u8; 4]> for Ipv4Addr {
     /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
     /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
     /// ```
+    #[inline]
     fn from(octets: [u8; 4]) -> Ipv4Addr {
         Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
     }
@@ -1026,6 +1063,7 @@ impl From<[u8; 4]> for IpAddr {
     /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
     /// ```
+    #[inline]
     fn from(octets: [u8; 4]) -> IpAddr {
         IpAddr::V4(Ipv4Addr::from(octets))
     }
@@ -1046,6 +1084,7 @@ impl Ipv6Addr {
     #[rustc_allow_const_fn_unstable(const_fn_transmute)]
     #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
         let addr16 = [
             a.to_be(),
@@ -1107,6 +1146,7 @@ impl Ipv6Addr {
     #[rustc_allow_const_fn_unstable(const_fn_transmute)]
     #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub const fn segments(&self) -> [u16; 8] {
         // All elements in `s6_addr` must be big endian.
         // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
@@ -1142,6 +1182,7 @@ impl Ipv6Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
+    #[inline]
     pub const fn is_unspecified(&self) -> bool {
         u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
     }
@@ -1162,6 +1203,7 @@ impl Ipv6Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
+    #[inline]
     pub const fn is_loopback(&self) -> bool {
         u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
     }
@@ -1186,6 +1228,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[inline]
     pub const fn is_global(&self) -> bool {
         match self.multicast_scope() {
             Some(Ipv6MulticastScope::Global) => true,
@@ -1211,6 +1254,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[inline]
     pub const fn is_unique_local(&self) -> bool {
         (self.segments()[0] & 0xfe00) == 0xfc00
     }
@@ -1265,6 +1309,7 @@ impl Ipv6Addr {
     /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
     /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[inline]
     pub const fn is_unicast_link_local_strict(&self) -> bool {
         matches!(self.segments(), [0xfe80, 0, 0, 0, ..])
     }
@@ -1318,6 +1363,7 @@ impl Ipv6Addr {
     /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
     /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[inline]
     pub const fn is_unicast_link_local(&self) -> bool {
         (self.segments()[0] & 0xffc0) == 0xfe80
     }
@@ -1357,6 +1403,7 @@ impl Ipv6Addr {
     ///
     /// [RFC 3879]: https://tools.ietf.org/html/rfc3879
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[inline]
     pub const fn is_unicast_site_local(&self) -> bool {
         (self.segments()[0] & 0xffc0) == 0xfec0
     }
@@ -1379,6 +1426,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[inline]
     pub const fn is_documentation(&self) -> bool {
         (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
     }
@@ -1414,6 +1462,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[inline]
     pub const fn is_unicast_global(&self) -> bool {
         !self.is_multicast()
             && !self.is_loopback()
@@ -1439,6 +1488,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[inline]
     pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
         if self.is_multicast() {
             match self.segments()[0] & 0x000f {
@@ -1472,6 +1522,7 @@ impl Ipv6Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
+    #[inline]
     pub const fn is_multicast(&self) -> bool {
         (self.segments()[0] & 0xff00) == 0xff00
     }
@@ -1498,6 +1549,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[inline]
     pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
         match self.octets() {
             [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
@@ -1527,6 +1579,7 @@ impl Ipv6Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
         if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
             let [a, b] = ab.to_be_bytes();
@@ -1547,6 +1600,7 @@ impl Ipv6Addr {
     /// ```
     #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
     #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
+    #[inline]
     pub const fn octets(&self) -> [u8; 16] {
         self.inner.s6_addr
     }
@@ -1658,6 +1712,7 @@ impl fmt::Debug for Ipv6Addr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Clone for Ipv6Addr {
+    #[inline]
     fn clone(&self) -> Ipv6Addr {
         *self
     }
@@ -1665,6 +1720,7 @@ impl Clone for Ipv6Addr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialEq for Ipv6Addr {
+    #[inline]
     fn eq(&self, other: &Ipv6Addr) -> bool {
         self.inner.s6_addr == other.inner.s6_addr
     }
@@ -1672,6 +1728,7 @@ impl PartialEq for Ipv6Addr {
 
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialEq<IpAddr> for Ipv6Addr {
+    #[inline]
     fn eq(&self, other: &IpAddr) -> bool {
         match other {
             IpAddr::V4(_) => false,
@@ -1682,6 +1739,7 @@ impl PartialEq<IpAddr> for Ipv6Addr {
 
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialEq<Ipv6Addr> for IpAddr {
+    #[inline]
     fn eq(&self, other: &Ipv6Addr) -> bool {
         match self {
             IpAddr::V4(_) => false,
@@ -1695,6 +1753,7 @@ impl Eq for Ipv6Addr {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl hash::Hash for Ipv6Addr {
+    #[inline]
     fn hash<H: hash::Hasher>(&self, s: &mut H) {
         self.inner.s6_addr.hash(s)
     }
@@ -1702,6 +1761,7 @@ impl hash::Hash for Ipv6Addr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialOrd for Ipv6Addr {
+    #[inline]
     fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
         Some(self.cmp(other))
     }
@@ -1709,6 +1769,7 @@ impl PartialOrd for Ipv6Addr {
 
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialOrd<Ipv6Addr> for IpAddr {
+    #[inline]
     fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
         match self {
             IpAddr::V4(_) => Some(Ordering::Less),
@@ -1719,6 +1780,7 @@ impl PartialOrd<Ipv6Addr> for IpAddr {
 
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialOrd<IpAddr> for Ipv6Addr {
+    #[inline]
     fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
         match other {
             IpAddr::V4(_) => Some(Ordering::Greater),
@@ -1729,6 +1791,7 @@ impl PartialOrd<IpAddr> for Ipv6Addr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Ord for Ipv6Addr {
+    #[inline]
     fn cmp(&self, other: &Ipv6Addr) -> Ordering {
         self.segments().cmp(&other.segments())
     }
@@ -1760,6 +1823,7 @@ impl From<Ipv6Addr> for u128 {
     /// );
     /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
     /// ```
+    #[inline]
     fn from(ip: Ipv6Addr) -> u128 {
         let ip = ip.octets();
         u128::from_be_bytes(ip)
@@ -1782,6 +1846,7 @@ impl From<u128> for Ipv6Addr {
     ///     ),
     ///     addr);
     /// ```
+    #[inline]
     fn from(ip: u128) -> Ipv6Addr {
         Ipv6Addr::from(ip.to_be_bytes())
     }
@@ -1810,6 +1875,7 @@ impl From<[u8; 16]> for Ipv6Addr {
     ///     addr
     /// );
     /// ```
+    #[inline]
     fn from(octets: [u8; 16]) -> Ipv6Addr {
         let inner = c::in6_addr { s6_addr: octets };
         Ipv6Addr::from_inner(inner)
@@ -1839,6 +1905,7 @@ impl From<[u16; 8]> for Ipv6Addr {
     ///     addr
     /// );
     /// ```
+    #[inline]
     fn from(segments: [u16; 8]) -> Ipv6Addr {
         let [a, b, c, d, e, f, g, h] = segments;
         Ipv6Addr::new(a, b, c, d, e, f, g, h)
@@ -1868,6 +1935,7 @@ impl From<[u8; 16]> for IpAddr {
     ///     addr
     /// );
     /// ```
+    #[inline]
     fn from(octets: [u8; 16]) -> IpAddr {
         IpAddr::V6(Ipv6Addr::from(octets))
     }
@@ -1896,6 +1964,7 @@ impl From<[u16; 8]> for IpAddr {
     ///     addr
     /// );
     /// ```
+    #[inline]
     fn from(segments: [u16; 8]) -> IpAddr {
         IpAddr::V6(Ipv6Addr::from(segments))
     }
diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs
index 617c4098aa9..525102212c4 100644
--- a/library/std/src/os/linux/raw.rs
+++ b/library/std/src/os/linux/raw.rs
@@ -247,17 +247,17 @@ mod arch {
     use crate::os::raw::{c_int, c_long};
 
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type blkcnt_t = u64;
+    pub type blkcnt_t = i64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type blksize_t = u64;
+    pub type blksize_t = i32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub type ino_t = u64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type nlink_t = u64;
+    pub type nlink_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type off_t = u64;
+    pub type off_t = i64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type time_t = i64;
+    pub type time_t = c_long;
 
     #[repr(C)]
     #[derive(Clone)]
@@ -288,15 +288,15 @@ mod arch {
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_blocks: i64,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime: i64,
+        pub st_atime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_atime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime: i64,
+        pub st_mtime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_mtime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime: i64,
+        pub st_ctime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_ctime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index 26302d0ecf2..ef9aec54a4c 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -54,6 +54,11 @@ pub use core::prelude::v1::{
     bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
 };
 
+#[cfg(not(bootstrap))]
+#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+#[doc(hidden)]
+pub use core::prelude::v1::derive;
+
 #[unstable(
     feature = "cfg_accessible",
     issue = "64797",
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index 6a330834489..2e5f843fc43 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -125,7 +125,7 @@ unsafe impl Send for Once {}
 
 /// State yielded to [`Once::call_once_force()`]’s closure parameter. The state
 /// can be used to query the poison status of the [`Once`].
-#[unstable(feature = "once_poison", issue = "33577")]
+#[stable(feature = "once_poison", since = "1.51.0")]
 #[derive(Debug)]
 pub struct OnceState {
     poisoned: bool,
@@ -280,8 +280,6 @@ impl Once {
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_poison)]
-    ///
     /// use std::sync::Once;
     /// use std::thread;
     ///
@@ -301,13 +299,13 @@ impl Once {
     ///
     /// // call_once_force will still run and reset the poisoned state
     /// INIT.call_once_force(|state| {
-    ///     assert!(state.poisoned());
+    ///     assert!(state.is_poisoned());
     /// });
     ///
     /// // once any success happens, we stop propagating the poison
     /// INIT.call_once(|| {});
     /// ```
-    #[unstable(feature = "once_poison", issue = "33577")]
+    #[stable(feature = "once_poison", since = "1.51.0")]
     pub fn call_once_force<F>(&self, f: F)
     where
         F: FnOnce(&OnceState),
@@ -526,8 +524,6 @@ impl OnceState {
     /// A poisoned [`Once`]:
     ///
     /// ```
-    /// #![feature(once_poison)]
-    ///
     /// use std::sync::Once;
     /// use std::thread;
     ///
@@ -540,24 +536,22 @@ impl OnceState {
     /// assert!(handle.join().is_err());
     ///
     /// INIT.call_once_force(|state| {
-    ///     assert!(state.poisoned());
+    ///     assert!(state.is_poisoned());
     /// });
     /// ```
     ///
     /// An unpoisoned [`Once`]:
     ///
     /// ```
-    /// #![feature(once_poison)]
-    ///
     /// use std::sync::Once;
     ///
     /// static INIT: Once = Once::new();
     ///
     /// INIT.call_once_force(|state| {
-    ///     assert!(!state.poisoned());
+    ///     assert!(!state.is_poisoned());
     /// });
-    #[unstable(feature = "once_poison", issue = "33577")]
-    pub fn poisoned(&self) -> bool {
+    #[stable(feature = "once_poison", since = "1.51.0")]
+    pub fn is_poisoned(&self) -> bool {
         self.poisoned
     }
 
diff --git a/library/std/src/sync/once/tests.rs b/library/std/src/sync/once/tests.rs
index fae2752526e..0c35597e11c 100644
--- a/library/std/src/sync/once/tests.rs
+++ b/library/std/src/sync/once/tests.rs
@@ -69,7 +69,7 @@ fn poison_bad() {
     let mut called = false;
     O.call_once_force(|p| {
         called = true;
-        assert!(p.poisoned())
+        assert!(p.is_poisoned())
     });
     assert!(called);
 
@@ -92,7 +92,7 @@ fn wait_for_force_to_finish() {
     let (tx2, rx2) = channel();
     let t1 = thread::spawn(move || {
         O.call_once_force(|p| {
-            assert!(p.poisoned());
+            assert!(p.is_poisoned());
             tx1.send(()).unwrap();
             rx2.recv().unwrap();
         });
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index d5e14bec765..1d1118aa694 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -22,6 +22,7 @@ use crate::str;
 use crate::sys::cvt;
 use crate::sys::fd;
 use crate::sys_common::mutex::{StaticMutex, StaticMutexGuard};
+use crate::sys_common::rwlock::{RWLockReadGuard, StaticRWLock};
 use crate::vec;
 
 use libc::{c_char, c_int, c_void};
@@ -490,20 +491,20 @@ pub unsafe fn environ() -> *mut *const *const c_char {
     extern "C" {
         static mut environ: *const *const c_char;
     }
-    &mut environ
+    ptr::addr_of_mut!(environ)
 }
 
-pub unsafe fn env_lock() -> StaticMutexGuard {
-    // It is UB to attempt to acquire this mutex reentrantly!
-    static ENV_LOCK: StaticMutex = StaticMutex::new();
-    ENV_LOCK.lock()
+static ENV_LOCK: StaticRWLock = StaticRWLock::new();
+
+pub fn env_read_lock() -> RWLockReadGuard {
+    ENV_LOCK.read_with_guard()
 }
 
 /// Returns a vector of (variable, value) byte-vector pairs for all the
 /// environment variables of the current process.
 pub fn env() -> Env {
     unsafe {
-        let _guard = env_lock();
+        let _guard = env_read_lock();
         let mut environ = *environ();
         let mut result = Vec::new();
         if !environ.is_null() {
@@ -540,7 +541,7 @@ pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
     // always None as well
     let k = CString::new(k.as_bytes())?;
     unsafe {
-        let _guard = env_lock();
+        let _guard = env_read_lock();
         let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
         let ret = if s.is_null() {
             None
@@ -556,7 +557,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
     let v = CString::new(v.as_bytes())?;
 
     unsafe {
-        let _guard = env_lock();
+        let _guard = ENV_LOCK.write_with_guard();
         cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
     }
 }
@@ -565,7 +566,7 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
     let nbuf = CString::new(n.as_bytes())?;
 
     unsafe {
-        let _guard = env_lock();
+        let _guard = ENV_LOCK.write_with_guard();
         cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
     }
 }
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 2746f87468d..9e82df7755e 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -47,7 +47,7 @@ impl Command {
         // a lock any more because the parent won't do anything and the child is
         // in its own process.
         let result = unsafe {
-            let _env_lock = sys::os::env_lock();
+            let _env_lock = sys::os::env_read_lock();
             cvt(libc::fork())?
         };
 
@@ -124,7 +124,7 @@ impl Command {
                     // Similar to when forking, we want to ensure that access to
                     // the environment is synchronized, so make sure to grab the
                     // environment lock before we try to exec.
-                    let _lock = sys::os::env_lock();
+                    let _lock = sys::os::env_read_lock();
 
                     let Err(e) = self.do_exec(theirs, envp.as_ref());
                     e
@@ -404,7 +404,7 @@ impl Command {
             cvt_nz(libc::posix_spawnattr_setflags(attrs.0.as_mut_ptr(), flags as _))?;
 
             // Make sure we synchronize access to the global `environ` resource
-            let _env_lock = sys::os::env_lock();
+            let _env_lock = sys::os::env_read_lock();
             let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::os::environ() as *const _);
             cvt_nz(libc::posix_spawnp(
                 &mut p.pid,
diff --git a/library/std/src/sys/wasi/ext/fs.rs b/library/std/src/sys/wasi/ext/fs.rs
index 4f7cf6018d9..a8da003d550 100644
--- a/library/std/src/sys/wasi/ext/fs.rs
+++ b/library/std/src/sys/wasi/ext/fs.rs
@@ -514,3 +514,11 @@ pub fn symlink<P: AsRef<Path>, U: AsRef<Path>>(
         .fd()
         .symlink(osstr2str(old_path.as_ref().as_ref())?, osstr2str(new_path.as_ref().as_ref())?)
 }
+
+/// Create a symbolic link.
+///
+/// This is a convenience API similar to [`std::os::unix::fs::symlink`] and
+/// [`std::os::windows::fs::symlink_file`] and [`symlink_dir`](std::os::windows::fs::symlink_dir).
+pub fn symlink_path<P: AsRef<Path>, U: AsRef<Path>>(old_path: P, new_path: U) -> io::Result<()> {
+    crate::sys::fs::symlink(old_path.as_ref(), new_path.as_ref())
+}
diff --git a/library/std/src/sys/wasm/thread.rs b/library/std/src/sys/wasm/thread.rs
index 95a9230aa78..5eafb77da1d 100644
--- a/library/std/src/sys/wasm/thread.rs
+++ b/library/std/src/sys/wasm/thread.rs
@@ -86,7 +86,7 @@ pub fn my_id() -> u32 {
         if MY_ID == 0 {
             let mut cur = NEXT_ID.load(SeqCst);
             MY_ID = loop {
-                let next = cur.checked_add(1).unwrap_or_else(|| crate::arch::wasm32::unreachable());
+                let next = cur.checked_add(1).unwrap_or_else(|| crate::process::abort());
                 match NEXT_ID.compare_exchange(cur, next, SeqCst, SeqCst) {
                     Ok(_) => break next,
                     Err(i) => cur = i,
diff --git a/library/std/src/sys/windows/mutex.rs b/library/std/src/sys/windows/mutex.rs
index 72a0993d94d..12c5ea741f9 100644
--- a/library/std/src/sys/windows/mutex.rs
+++ b/library/std/src/sys/windows/mutex.rs
@@ -23,8 +23,6 @@ pub struct Mutex {
 }
 
 // Windows SRW Locks are movable (while not borrowed).
-// ReentrantMutexes (in Inner) are not, but those are stored indirectly through
-// a Box, so do not move when the Mutex it self is moved.
 pub type MovableMutex = Mutex;
 
 unsafe impl Send for Mutex {}
diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs
index 3705d641a1b..41e8ad77294 100644
--- a/library/std/src/sys_common/rwlock.rs
+++ b/library/std/src/sys_common/rwlock.rs
@@ -86,3 +86,62 @@ impl RWLock {
         self.0.destroy()
     }
 }
+
+// the cfg annotations only exist due to dead code warnings. the code itself is portable
+#[cfg(unix)]
+pub struct StaticRWLock(RWLock);
+
+#[cfg(unix)]
+impl StaticRWLock {
+    pub const fn new() -> StaticRWLock {
+        StaticRWLock(RWLock::new())
+    }
+
+    /// Acquires shared access to the underlying lock, blocking the current
+    /// thread to do so.
+    ///
+    /// The lock is automatically unlocked when the returned guard is dropped.
+    #[inline]
+    pub fn read_with_guard(&'static self) -> RWLockReadGuard {
+        // Safety: All methods require static references, therefore self
+        // cannot be moved between invocations.
+        unsafe {
+            self.0.read();
+        }
+        RWLockReadGuard(&self.0)
+    }
+
+    /// Acquires write access to the underlying lock, blocking the current thread
+    /// to do so.
+    ///
+    /// The lock is automatically unlocked when the returned guard is dropped.
+    #[inline]
+    pub fn write_with_guard(&'static self) -> RWLockWriteGuard {
+        // Safety: All methods require static references, therefore self
+        // cannot be moved between invocations.
+        unsafe {
+            self.0.write();
+        }
+        RWLockWriteGuard(&self.0)
+    }
+}
+
+#[cfg(unix)]
+pub struct RWLockReadGuard(&'static RWLock);
+
+#[cfg(unix)]
+impl Drop for RWLockReadGuard {
+    fn drop(&mut self) {
+        unsafe { self.0.read_unlock() }
+    }
+}
+
+#[cfg(unix)]
+pub struct RWLockWriteGuard(&'static RWLock);
+
+#[cfg(unix)]
+impl Drop for RWLockWriteGuard {
+    fn drop(&mut self) {
+        unsafe { self.0.write_unlock() }
+    }
+}
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 0d004a516f5..0ef848ff0c4 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -775,6 +775,15 @@ pub fn sleep_ms(ms: u32) {
 /// Platforms which do not support nanosecond precision for sleeping will
 /// have `dur` rounded up to the nearest granularity of time they can sleep for.
 ///
+/// Currently, specifying a zero duration on Unix platforms returns immediately
+/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows
+/// platforms the underlying [`Sleep`] syscall is always invoked.
+/// If the intention is to yield the current time-slice you may want to use
+/// [`yield_now`] instead.
+///
+/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep
+/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep
+///
 /// # Examples
 ///
 /// ```no_run