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/alloc.rs5
-rw-r--r--library/std/src/backtrace.rs44
-rw-r--r--library/std/src/backtrace/tests.rs5
-rw-r--r--library/std/src/collections/hash/map.rs32
-rw-r--r--library/std/src/collections/hash/set.rs19
-rw-r--r--library/std/src/error.rs2
-rw-r--r--library/std/src/f32.rs35
-rw-r--r--library/std/src/f64.rs35
-rw-r--r--library/std/src/ffi/c_str.rs14
-rw-r--r--library/std/src/ffi/os_str.rs1
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/keyword_docs.rs3
-rw-r--r--library/std/src/lib.rs10
-rw-r--r--library/std/src/macros.rs2
-rw-r--r--library/std/src/net/ip.rs49
-rw-r--r--library/std/src/panicking.rs10
-rw-r--r--library/std/src/path.rs1
-rw-r--r--library/std/src/prelude/v1.rs8
-rw-r--r--library/std/src/primitive_docs.rs21
-rw-r--r--library/std/src/sync/mpsc/blocking.rs6
-rw-r--r--library/std/src/sync/mpsc/oneshot.rs14
-rw-r--r--library/std/src/sync/mpsc/shared.rs11
-rw-r--r--library/std/src/sync/mpsc/stream.rs9
-rw-r--r--library/std/src/sync/once.rs18
-rw-r--r--library/std/src/sys/sgx/abi/mod.rs8
-rw-r--r--library/std/src/sys/sgx/waitqueue/spin_mutex.rs2
-rw-r--r--library/std/src/sys/unix/ext/net/ancillary.rs6
-rw-r--r--library/std/src/sys/unix/ext/process.rs56
-rw-r--r--library/std/src/sys/unix/fd.rs9
-rw-r--r--library/std/src/sys/unix/fd/tests.rs2
-rw-r--r--library/std/src/sys/unix/process/process_fuchsia.rs44
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs18
-rw-r--r--library/std/src/sys/unix/time.rs2
-rw-r--r--library/std/src/sys/unix/weak.rs2
-rw-r--r--library/std/src/sys/windows/ext/process.rs16
-rw-r--r--library/std/src/sys/windows/mutex.rs6
-rw-r--r--library/std/src/sys/windows/thread_parker.rs2
-rw-r--r--library/std/src/sys_common/condvar/check.rs6
-rw-r--r--library/std/src/sys_common/fs.rs10
-rw-r--r--library/std/src/sys_common/thread_local_key.rs8
-rw-r--r--library/std/src/sys_common/thread_parker/futex.rs2
41 files changed, 361 insertions, 194 deletions
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 8491ff40033..843ef09a584 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -166,8 +166,9 @@ impl System {
         match old_layout.size() {
             0 => self.alloc_impl(new_layout, zeroed),
 
-            // SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size`
-            // as required by safety conditions. Other conditions must be upheld by the caller
+            // SAFETY: `new_size` is non-zero as `new_size` is greater than or equal to `old_size`
+            // as required by safety conditions and the `old_size == 0` case was handled in the
+            // previous match arm. Other conditions must be upheld by the caller
             old_size if old_layout.align() == new_layout.align() => unsafe {
                 let new_size = new_layout.size();
 
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 7e8e0a621e3..95e18ef2a65 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -95,11 +95,12 @@ mod tests;
 // a backtrace or actually symbolizing it.
 
 use crate::backtrace_rs::{self, BytesOrWideString};
+use crate::cell::UnsafeCell;
 use crate::env;
 use crate::ffi::c_void;
 use crate::fmt;
 use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-use crate::sync::Mutex;
+use crate::sync::Once;
 use crate::sys_common::backtrace::{lock, output_filename};
 use crate::vec::Vec;
 
@@ -132,7 +133,7 @@ pub enum BacktraceStatus {
 enum Inner {
     Unsupported,
     Disabled,
-    Captured(Mutex<Capture>),
+    Captured(LazilyResolvedCapture),
 }
 
 struct Capture {
@@ -171,12 +172,11 @@ enum BytesOrWide {
 
 impl fmt::Debug for Backtrace {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut capture = match &self.inner {
+        let capture = match &self.inner {
             Inner::Unsupported => return fmt.write_str("<unsupported>"),
             Inner::Disabled => return fmt.write_str("<disabled>"),
-            Inner::Captured(c) => c.lock().unwrap(),
+            Inner::Captured(c) => c.force(),
         };
-        capture.resolve();
 
         let frames = &capture.frames[capture.actual_start..];
 
@@ -331,7 +331,7 @@ impl Backtrace {
         let inner = if frames.is_empty() {
             Inner::Unsupported
         } else {
-            Inner::Captured(Mutex::new(Capture {
+            Inner::Captured(LazilyResolvedCapture::new(Capture {
                 actual_start: actual_start.unwrap_or(0),
                 frames,
                 resolved: false,
@@ -355,12 +355,11 @@ impl Backtrace {
 
 impl fmt::Display for Backtrace {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut capture = match &self.inner {
+        let capture = match &self.inner {
             Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
             Inner::Disabled => return fmt.write_str("disabled backtrace"),
-            Inner::Captured(c) => c.lock().unwrap(),
+            Inner::Captured(c) => c.force(),
         };
-        capture.resolve();
 
         let full = fmt.alternate();
         let (frames, style) = if full {
@@ -404,6 +403,33 @@ impl fmt::Display for Backtrace {
     }
 }
 
+struct LazilyResolvedCapture {
+    sync: Once,
+    capture: UnsafeCell<Capture>,
+}
+
+impl LazilyResolvedCapture {
+    fn new(capture: Capture) -> Self {
+        LazilyResolvedCapture { sync: Once::new(), capture: UnsafeCell::new(capture) }
+    }
+
+    fn force(&self) -> &Capture {
+        self.sync.call_once(|| {
+            // SAFETY: This exclusive reference can't overlap with any others
+            // `Once` guarantees callers will block until this closure returns
+            // `Once` also guarantees only a single caller will enter this closure
+            unsafe { &mut *self.capture.get() }.resolve();
+        });
+
+        // SAFETY: This shared reference can't overlap with the exclusive reference above
+        unsafe { &*self.capture.get() }
+    }
+}
+
+// SAFETY: Access to the inner value is synchronized using a thread-safe `Once`
+// So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too
+unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {}
+
 impl Capture {
     fn resolve(&mut self) {
         // If we're already resolved, nothing to do!
diff --git a/library/std/src/backtrace/tests.rs b/library/std/src/backtrace/tests.rs
index f5f74d1eb9a..31cf0f70218 100644
--- a/library/std/src/backtrace/tests.rs
+++ b/library/std/src/backtrace/tests.rs
@@ -3,7 +3,7 @@ use super::*;
 #[test]
 fn test_debug() {
     let backtrace = Backtrace {
-        inner: Inner::Captured(Mutex::new(Capture {
+        inner: Inner::Captured(LazilyResolvedCapture::new(Capture {
             actual_start: 1,
             resolved: true,
             frames: vec![
@@ -54,4 +54,7 @@ fn test_debug() {
     \n]";
 
     assert_eq!(format!("{:#?}", backtrace), expected);
+
+    // Format the backtrace a second time, just to make sure lazily resolved state is stable
+    assert_eq!(format!("{:#?}", backtrace), expected);
 }
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 27d90e66137..0680b1fc329 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -195,7 +195,6 @@ use crate::sys;
 /// // use the values stored in map
 /// ```
 
-#[derive(Clone)]
 #[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_type")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashMap<K, V, S = RandomState> {
@@ -449,6 +448,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// a.insert(1, "a");
     /// assert_eq!(a.len(), 1);
     /// ```
+    #[doc(alias = "length")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
         self.base.len()
@@ -1030,6 +1030,24 @@ where
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+impl<K, V, S> Clone for HashMap<K, V, S>
+where
+    K: Clone,
+    V: Clone,
+    S: Clone,
+{
+    #[inline]
+    fn clone(&self) -> Self {
+        Self { base: self.base.clone() }
+    }
+
+    #[inline]
+    fn clone_from(&mut self, other: &Self) {
+        self.base.clone_from(&other.base);
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> PartialEq for HashMap<K, V, S>
 where
     K: Eq + Hash,
@@ -2219,14 +2237,16 @@ impl<'a, K, V> Entry<'a, K, V> {
         }
     }
 
-    /// Ensures a value is in the entry by inserting, if empty, the result of the default function,
-    /// which takes the key as its argument, and returns a mutable reference to the value in the
-    /// entry.
+    /// Ensures a value is in the entry by inserting, if empty, the result of the default function.
+    /// This method allows for generating key-derived values for insertion by providing the default
+    /// function a reference to the key that was moved during the `.entry(key)` method call.
+    ///
+    /// The reference to the moved key is provided so that cloning or copying the key is
+    /// unnecessary, unlike with `.or_insert_with(|| ... )`.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(or_insert_with_key)]
     /// use std::collections::HashMap;
     ///
     /// let mut map: HashMap<&str, usize> = HashMap::new();
@@ -2236,7 +2256,7 @@ impl<'a, K, V> Entry<'a, K, V> {
     /// assert_eq!(map["poneyland"], 9);
     /// ```
     #[inline]
-    #[unstable(feature = "or_insert_with_key", issue = "71024")]
+    #[stable(feature = "or_insert_with_key", since = "1.50.0")]
     pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 3299fd12e02..f49e5801c35 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -106,7 +106,6 @@ use super::map::{map_try_reserve_error, RandomState};
 /// [`HashMap`]: crate::collections::HashMap
 /// [`RefCell`]: crate::cell::RefCell
 /// [`Cell`]: crate::cell::Cell
-#[derive(Clone)]
 #[cfg_attr(not(test), rustc_diagnostic_item = "hashset_type")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashSet<T, S = RandomState> {
@@ -200,6 +199,7 @@ impl<T, S> HashSet<T, S> {
     /// v.insert(1);
     /// assert_eq!(v.len(), 1);
     /// ```
+    #[doc(alias = "length")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
@@ -933,6 +933,23 @@ where
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+impl<T, S> Clone for HashSet<T, S>
+where
+    T: Clone,
+    S: Clone,
+{
+    #[inline]
+    fn clone(&self) -> Self {
+        Self { base: self.base.clone() }
+    }
+
+    #[inline]
+    fn clone_from(&mut self, other: &Self) {
+        self.base.clone_from(&other.base);
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> PartialEq for HashSet<T, S>
 where
     T: Eq + Hash,
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 0044e59d697..ca83c409822 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -42,8 +42,6 @@ use crate::string;
 /// via [`Error::source()`]. This makes it possible for the high-level
 /// module to provide its own errors while also revealing some of the
 /// implementation for debugging via `source` chains.
-///
-/// [`Result<T, E>`]: Result
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Error: Debug + Display {
     /// The lower-level source of this error, if any.
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 48c77bd13e0..c30458c0545 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -879,39 +879,4 @@ impl f32 {
     pub fn atanh(self) -> f32 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
-
-    /// Restrict a value to a certain interval unless it is NaN.
-    ///
-    /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
-    /// less than `min`. Otherwise this returns `self`.
-    ///
-    /// Note that this function returns NaN if the initial value was NaN as
-    /// well.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// assert!((-3.0f32).clamp(-2.0, 1.0) == -2.0);
-    /// assert!((0.0f32).clamp(-2.0, 1.0) == 0.0);
-    /// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0);
-    /// assert!((f32::NAN).clamp(-2.0, 1.0).is_nan());
-    /// ```
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    #[stable(feature = "clamp", since = "1.50.0")]
-    #[inline]
-    pub fn clamp(self, min: f32, max: f32) -> f32 {
-        assert!(min <= max);
-        let mut x = self;
-        if x < min {
-            x = min;
-        }
-        if x > max {
-            x = max;
-        }
-        x
-    }
 }
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index e823ac43fdd..f4cc53979d1 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -882,41 +882,6 @@ impl f64 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
 
-    /// Restrict a value to a certain interval unless it is NaN.
-    ///
-    /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
-    /// less than `min`. Otherwise this returns `self`.
-    ///
-    /// Note that this function returns NaN if the initial value was NaN as
-    /// well.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// assert!((-3.0f64).clamp(-2.0, 1.0) == -2.0);
-    /// assert!((0.0f64).clamp(-2.0, 1.0) == 0.0);
-    /// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0);
-    /// assert!((f64::NAN).clamp(-2.0, 1.0).is_nan());
-    /// ```
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    #[stable(feature = "clamp", since = "1.50.0")]
-    #[inline]
-    pub fn clamp(self, min: f64, max: f64) -> f64 {
-        assert!(min <= max);
-        let mut x = self;
-        if x < min {
-            x = min;
-        }
-        if x > max {
-            x = max;
-        }
-        x
-    }
-
     // Solaris/Illumos requires a wrapper around log, log2, and log10 functions
     // because of their non-standard behavior (e.g., log(-n) returns -Inf instead
     // of expected NaN).
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 60b642a6dba..230ef0b23db 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -86,7 +86,7 @@ use crate::sys;
 /// use std::ffi::CString;
 /// use std::os::raw::c_char;
 ///
-/// extern {
+/// extern "C" {
 ///     fn my_printer(s: *const c_char);
 /// }
 ///
@@ -144,7 +144,7 @@ pub struct CString {
 /// use std::ffi::CStr;
 /// use std::os::raw::c_char;
 ///
-/// extern { fn my_string() -> *const c_char; }
+/// extern "C" { fn my_string() -> *const c_char; }
 ///
 /// unsafe {
 ///     let slice = CStr::from_ptr(my_string());
@@ -159,7 +159,7 @@ pub struct CString {
 /// use std::os::raw::c_char;
 ///
 /// fn work(data: &CStr) {
-///     extern { fn work_with(data: *const c_char); }
+///     extern "C" { fn work_with(data: *const c_char); }
 ///
 ///     unsafe { work_with(data.as_ptr()) }
 /// }
@@ -174,7 +174,7 @@ pub struct CString {
 /// use std::ffi::CStr;
 /// use std::os::raw::c_char;
 ///
-/// extern { fn my_string() -> *const c_char; }
+/// extern "C" { fn my_string() -> *const c_char; }
 ///
 /// fn my_string_safe() -> String {
 ///     unsafe {
@@ -359,7 +359,7 @@ impl CString {
     /// use std::ffi::CString;
     /// use std::os::raw::c_char;
     ///
-    /// extern { fn puts(s: *const c_char); }
+    /// extern "C" { fn puts(s: *const c_char); }
     ///
     /// let to_print = CString::new("Hello!").expect("CString::new failed");
     /// unsafe {
@@ -465,7 +465,7 @@ impl CString {
     /// use std::ffi::CString;
     /// use std::os::raw::c_char;
     ///
-    /// extern {
+    /// extern "C" {
     ///     fn some_extern_function(s: *mut c_char);
     /// }
     ///
@@ -1147,7 +1147,7 @@ impl CStr {
     /// use std::ffi::CStr;
     /// use std::os::raw::c_char;
     ///
-    /// extern {
+    /// extern "C" {
     ///     fn my_string() -> *const c_char;
     /// }
     ///
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 5d93016cadb..2eef4d58507 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -653,6 +653,7 @@ impl OsStr {
     /// let os_str = OsStr::new("foo");
     /// assert_eq!(os_str.len(), 3);
     /// ```
+    #[doc(alias = "length")]
     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
     pub fn len(&self) -> usize {
         self.inner.inner.len()
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index dfbf6c3f244..7ad9e446c59 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -240,7 +240,6 @@
 //!
 //! [`File`]: crate::fs::File
 //! [`TcpStream`]: crate::net::TcpStream
-//! [`Vec<T>`]: Vec
 //! [`io::stdout`]: stdout
 //! [`io::Result`]: self::Result
 //! [`?` operator]: ../../book/appendix-02-operators.html
@@ -1984,7 +1983,6 @@ pub trait BufRead: Read {
     /// also yielded an error.
     ///
     /// [`io::Result`]: self::Result
-    /// [`Vec<u8>`]: Vec
     /// [`read_until`]: BufRead::read_until
     ///
     /// # Examples
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 8174cf5c373..6b06539a094 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -401,7 +401,7 @@ mod enum_keyword {}
 ///
 /// ```rust
 /// #[no_mangle]
-/// pub extern fn callable_from_c(x: i32) -> bool {
+/// pub extern "C" fn callable_from_c(x: i32) -> bool {
 ///     x % 3 == 0
 /// }
 /// ```
@@ -2196,6 +2196,7 @@ mod where_keyword {}
 
 // 2018 Edition keywords
 
+#[doc(alias = "promise")]
 #[doc(keyword = "async")]
 //
 /// Return a [`Future`] instead of blocking the current thread.
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 39b0ca63301..15ef5d1619b 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -175,7 +175,7 @@
 //! [`str`]: prim@str
 //! [`mpsc`]: sync::mpsc
 //! [`std::cmp`]: cmp
-//! [`std::slice`]: slice
+//! [`std::slice`]: mod@slice
 //! [`use std::env`]: env/index.html
 //! [`use`]: ../book/ch07-02-defining-modules-to-control-scope-and-privacy.html
 //! [crates.io]: https://crates.io
@@ -185,7 +185,8 @@
 //! [other]: #what-is-in-the-standard-library-documentation
 //! [primitive types]: ../book/ch03-02-data-types.html
 //! [rust-discord]: https://discord.gg/rust-lang
-
+#![cfg_attr(not(bootstrap), doc = "[array]: prim@array")]
+#![cfg_attr(not(bootstrap), doc = "[slice]: prim@slice")]
 #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
 #![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
 #![doc(
@@ -288,8 +289,7 @@
 #![feature(nll)]
 #![feature(nonnull_slice_from_raw_parts)]
 #![feature(once_cell)]
-#![cfg_attr(bootstrap, feature(optin_builtin_traits))]
-#![cfg_attr(not(bootstrap), feature(auto_traits))]
+#![feature(auto_traits)]
 #![feature(or_patterns)]
 #![feature(panic_info_message)]
 #![feature(panic_internals)]
@@ -304,11 +304,9 @@
 #![feature(rustc_private)]
 #![feature(shrink_to)]
 #![feature(slice_concat_ext)]
-#![feature(slice_fill)]
 #![feature(slice_internals)]
 #![feature(slice_ptr_get)]
 #![feature(slice_ptr_len)]
-#![feature(slice_strip)]
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(stdsimd)]
diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs
index de072e83dfc..5a70aa070e8 100644
--- a/library/std/src/macros.rs
+++ b/library/std/src/macros.rs
@@ -8,7 +8,7 @@
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable(libstd_sys_internals)]
-#[cfg_attr(not(any(bootstrap, test)), rustc_diagnostic_item = "std_panic_macro")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")]
 macro_rules! panic {
     () => ({ $crate::panic!("explicit panic") });
     ($msg:expr $(,)?) => ({ $crate::rt::begin_panic($msg) });
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index 87bbd33bc01..d33b772633d 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -148,7 +148,7 @@ impl IpAddr {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
     /// ```
-    #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ip_shared", since = "1.12.0")]
     pub const fn is_unspecified(&self) -> bool {
         match self {
@@ -170,7 +170,7 @@ impl IpAddr {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
     /// ```
-    #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ip_shared", since = "1.12.0")]
     pub const fn is_loopback(&self) -> bool {
         match self {
@@ -215,7 +215,7 @@ impl IpAddr {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
     /// ```
-    #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ip_shared", since = "1.12.0")]
     pub const fn is_multicast(&self) -> bool {
         match self {
@@ -301,8 +301,8 @@ impl Ipv4Addr {
     ///
     /// let addr = Ipv4Addr::new(127, 0, 0, 1);
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     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.
@@ -358,7 +358,7 @@ impl Ipv4Addr {
     /// let addr = Ipv4Addr::new(127, 0, 0, 1);
     /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn octets(&self) -> [u8; 4] {
         // This returns the order we want because s_addr is stored in big-endian.
@@ -380,8 +380,8 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
     /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
     /// ```
-    #[stable(feature = "ip_shared", since = "1.12.0")]
     #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
+    #[stable(feature = "ip_shared", since = "1.12.0")]
     pub const fn is_unspecified(&self) -> bool {
         self.inner.s_addr == 0
     }
@@ -400,7 +400,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
     /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub const fn is_loopback(&self) -> bool {
         self.octets()[0] == 127
@@ -429,7 +429,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
     /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub const fn is_private(&self) -> bool {
         match self.octets() {
@@ -455,7 +455,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
     /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub const fn is_link_local(&self) -> bool {
         matches!(self.octets(), [169, 254, ..])
@@ -675,7 +675,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
     /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub const fn is_multicast(&self) -> bool {
         self.octets()[0] >= 224 && self.octets()[0] <= 239
@@ -695,7 +695,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
     /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub const fn is_broadcast(&self) -> bool {
         u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
@@ -721,7 +721,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
     /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub const fn is_documentation(&self) -> bool {
         match self.octets() {
@@ -751,7 +751,7 @@ impl Ipv4Addr {
     ///     Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767)
     /// );
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
         let [a, b, c, d] = self.octets();
@@ -774,7 +774,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
     ///            Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767));
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
         let [a, b, c, d] = self.octets();
@@ -1043,9 +1043,9 @@ impl Ipv6Addr {
     ///
     /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
     #[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")]
     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(),
@@ -1061,6 +1061,8 @@ impl Ipv6Addr {
             inner: c::in6_addr {
                 // All elements in `addr16` are big endian.
                 // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
+                // rustc_allow_const_fn_unstable: the transmute could be written as stable const
+                // code, but that leads to worse code generation (#75085)
                 s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
             },
         }
@@ -1102,11 +1104,14 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
     ///            [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[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")]
     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]`.
+        // rustc_allow_const_fn_unstable: the transmute could be written as stable const code, but
+        // that leads to worse code generation (#75085)
         let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
         // We want native endian u16
         [
@@ -1135,7 +1140,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub const fn is_unspecified(&self) -> bool {
         u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
@@ -1155,7 +1160,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub const fn is_loopback(&self) -> bool {
         u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
@@ -1465,7 +1470,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub const fn is_multicast(&self) -> bool {
         (self.segments()[0] & 0xff00) == 0xff00
@@ -1520,7 +1525,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
     ///            Some(Ipv4Addr::new(0, 0, 0, 1)));
     /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
         if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
@@ -1540,8 +1545,8 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
     ///            [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
     /// ```
-    #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
     #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
+    #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
     pub const fn octets(&self) -> [u8; 16] {
         self.inner.s6_addr
     }
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 8ba3feccb6b..6cd572cbe87 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -44,11 +44,11 @@ use realstd::io::set_output_capture;
 extern "C" {
     fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
 
-    /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings.
-    /// It cannot be `Box<dyn BoxMeUp>` because the other end of this call does not depend
-    /// on liballoc, and thus cannot use `Box`.
+    /// `payload` is passed through another layer of raw pointers as `&mut dyn Trait` is not
+    /// FFI-safe. `BoxMeUp` lazily performs allocation only when needed (this avoids allocations
+    /// when using the "abort" panic runtime).
     #[unwind(allowed)]
-    fn __rust_start_panic(payload: usize) -> u32;
+    fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32;
 }
 
 /// This function is called by the panic runtime if FFI code catches a Rust
@@ -637,7 +637,7 @@ pub fn rust_panic_without_hook(payload: Box<dyn Any + Send>) -> ! {
 fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! {
     let code = unsafe {
         let obj = &mut msg as *mut &mut dyn BoxMeUp;
-        __rust_start_panic(obj as usize)
+        __rust_start_panic(obj)
     };
     rtabort!("failed to initiate panic, error {}", code)
 }
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 8a75c1d6058..243761e3897 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1775,7 +1775,6 @@ impl Path {
     /// Any non-Unicode sequences are replaced with
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
     ///
-    /// [`Cow<str>`]: Cow
     /// [U+FFFD]: super::char::REPLACEMENT_CHARACTER
     ///
     /// # Examples
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index 0fbd6b62f18..26302d0ecf2 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -41,17 +41,17 @@ pub use crate::result::Result::{self, Err, Ok};
 pub use core::prelude::v1::{
     asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
     format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, log_syntax,
-    module_path, option_env, stringify, trace_macros,
+    module_path, option_env, stringify, trace_macros, Clone, Copy, Debug, Default, Eq, Hash, Ord,
+    PartialEq, PartialOrd,
 };
 
-// FIXME: Attribute and derive macros are not documented because for them rustdoc generates
+// FIXME: Attribute and internal derive macros are not documented because for them rustdoc generates
 // dead links which fail link checker testing.
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated)]
 #[doc(hidden)]
 pub use core::prelude::v1::{
-    bench, global_allocator, test, test_case, Clone, Copy, Debug, Default, Eq, Hash, Ord,
-    PartialEq, PartialOrd, RustcDecodable, RustcEncodable,
+    bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
 };
 
 #[unstable(
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 7aca5451ebc..876b2b8a3f6 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -11,8 +11,9 @@
 /// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc.,
 /// which allow us to perform boolean operations using `&`, `|` and `!`.
 ///
-/// `if` always demands a `bool` value. [`assert!`], which is an important macro in testing,
-/// checks whether an expression returns `true` and panics if it isn't.
+/// `if` requires a `bool` value as its conditional. [`assert!`], which is an
+/// important macro in testing, checks whether an expression is `true` and panics
+/// if it isn't.
 ///
 /// ```
 /// let bool_val = true & false | false;
@@ -25,7 +26,7 @@
 ///
 /// # Examples
 ///
-/// A trivial example of the usage of `bool`,
+/// A trivial example of the usage of `bool`:
 ///
 /// ```
 /// let praise_the_borrow_checker = true;
@@ -122,9 +123,9 @@ mod prim_bool {}
 /// `!`, if we have to call [`String::from_str`] for some reason the result will be a
 /// [`Result<String, !>`] which we can unpack like this:
 ///
-/// ```ignore (string-from-str-error-type-is-not-never-yet)
-/// #[feature(exhaustive_patterns)]
-/// // NOTE: this does not work today!
+/// ```
+/// #![feature(exhaustive_patterns)]
+/// use std::str::FromStr;
 /// let Ok(s) = String::from_str("hello");
 /// ```
 ///
@@ -184,9 +185,6 @@ mod prim_bool {}
 /// because `!` coerces to `Result<!, ConnectionError>` automatically.
 ///
 /// [`String::from_str`]: str::FromStr::from_str
-/// [`Result<String, !>`]: Result
-/// [`Result<T, !>`]: Result
-/// [`Result<!, E>`]: Result
 /// [`String`]: string::String
 /// [`FromStr`]: str::FromStr
 ///
@@ -478,8 +476,10 @@ mod prim_unit {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_pointer {}
 
+#[doc(alias = "[]")]
+#[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases
+#[doc(alias = "[T; N]")]
 #[doc(primitive = "array")]
-//
 /// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and the
 /// non-negative compile-time constant size, `N`.
 ///
@@ -924,6 +924,7 @@ mod prim_usize {}
 
 #[doc(primitive = "reference")]
 #[doc(alias = "&")]
+#[doc(alias = "&mut")]
 //
 /// References, both shared and mutable.
 ///
diff --git a/library/std/src/sync/mpsc/blocking.rs b/library/std/src/sync/mpsc/blocking.rs
index d34de6a4fac..4c852b8ee81 100644
--- a/library/std/src/sync/mpsc/blocking.rs
+++ b/library/std/src/sync/mpsc/blocking.rs
@@ -36,7 +36,11 @@ pub fn tokens() -> (WaitToken, SignalToken) {
 
 impl SignalToken {
     pub fn signal(&self) -> bool {
-        let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
+        let wake = self
+            .inner
+            .woken
+            .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
+            .is_ok();
         if wake {
             self.inner.thread.unpark();
         }
diff --git a/library/std/src/sync/mpsc/oneshot.rs b/library/std/src/sync/mpsc/oneshot.rs
index 75f5621fa12..3dcf03f579a 100644
--- a/library/std/src/sync/mpsc/oneshot.rs
+++ b/library/std/src/sync/mpsc/oneshot.rs
@@ -129,7 +129,7 @@ impl<T> Packet<T> {
             let ptr = unsafe { signal_token.cast_to_usize() };
 
             // race with senders to enter the blocking state
-            if self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) == EMPTY {
+            if self.state.compare_exchange(EMPTY, ptr, Ordering::SeqCst, Ordering::SeqCst).is_ok() {
                 if let Some(deadline) = deadline {
                     let timed_out = !wait_token.wait_max_until(deadline);
                     // Try to reset the state
@@ -161,7 +161,12 @@ impl<T> Packet<T> {
                 // the state changes under our feet we'd rather just see that state
                 // change.
                 DATA => {
-                    self.state.compare_and_swap(DATA, EMPTY, Ordering::SeqCst);
+                    let _ = self.state.compare_exchange(
+                        DATA,
+                        EMPTY,
+                        Ordering::SeqCst,
+                        Ordering::SeqCst,
+                    );
                     match (&mut *self.data.get()).take() {
                         Some(data) => Ok(data),
                         None => unreachable!(),
@@ -264,7 +269,10 @@ impl<T> Packet<T> {
 
             // If we've got a blocked thread, then use an atomic to gain ownership
             // of it (may fail)
-            ptr => self.state.compare_and_swap(ptr, EMPTY, Ordering::SeqCst),
+            ptr => self
+                .state
+                .compare_exchange(ptr, EMPTY, Ordering::SeqCst, Ordering::SeqCst)
+                .unwrap_or_else(|x| x),
         };
 
         // Now that we've got ownership of our state, figure out what to do
diff --git a/library/std/src/sync/mpsc/shared.rs b/library/std/src/sync/mpsc/shared.rs
index 898654f21f2..0c32e636a56 100644
--- a/library/std/src/sync/mpsc/shared.rs
+++ b/library/std/src/sync/mpsc/shared.rs
@@ -385,8 +385,15 @@ impl<T> Packet<T> {
         self.port_dropped.store(true, Ordering::SeqCst);
         let mut steals = unsafe { *self.steals.get() };
         while {
-            let cnt = self.cnt.compare_and_swap(steals, DISCONNECTED, Ordering::SeqCst);
-            cnt != DISCONNECTED && cnt != steals
+            match self.cnt.compare_exchange(
+                steals,
+                DISCONNECTED,
+                Ordering::SeqCst,
+                Ordering::SeqCst,
+            ) {
+                Ok(_) => false,
+                Err(old) => old != DISCONNECTED,
+            }
         } {
             // See the discussion in 'try_recv' for why we yield
             // control of this thread.
diff --git a/library/std/src/sync/mpsc/stream.rs b/library/std/src/sync/mpsc/stream.rs
index 9f7c1af8951..a652f24c58a 100644
--- a/library/std/src/sync/mpsc/stream.rs
+++ b/library/std/src/sync/mpsc/stream.rs
@@ -322,12 +322,15 @@ impl<T> Packet<T> {
         // (because there is a bounded number of senders).
         let mut steals = unsafe { *self.queue.consumer_addition().steals.get() };
         while {
-            let cnt = self.queue.producer_addition().cnt.compare_and_swap(
+            match self.queue.producer_addition().cnt.compare_exchange(
                 steals,
                 DISCONNECTED,
                 Ordering::SeqCst,
-            );
-            cnt != DISCONNECTED && cnt != steals
+                Ordering::SeqCst,
+            ) {
+                Ok(_) => false,
+                Err(old) => old != DISCONNECTED,
+            }
         } {
             while self.queue.pop().is_some() {
                 steals += 1;
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index de5ddf1daf2..6a330834489 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -65,7 +65,7 @@
 //       must do so with Release ordering to make the result available.
 //     - `wait` inserts `Waiter` nodes as a pointer in `state_and_queue`, and
 //       needs to make the nodes available with Release ordering. The load in
-//       its `compare_and_swap` can be Relaxed because it only has to compare
+//       its `compare_exchange` can be Relaxed because it only has to compare
 //       the atomic, not to read other data.
 //     - `WaiterQueue::Drop` must see the `Waiter` nodes, so it must load
 //       `state_and_queue` with Acquire ordering.
@@ -110,7 +110,7 @@ use crate::thread::{self, Thread};
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Once {
-    // `state_and_queue` is actually an a pointer to a `Waiter` with extra state
+    // `state_and_queue` is actually a pointer to a `Waiter` with extra state
     // bits, so we add the `PhantomData` appropriately.
     state_and_queue: AtomicUsize,
     _marker: marker::PhantomData<*const Waiter>,
@@ -395,12 +395,13 @@ impl Once {
                 }
                 POISONED | INCOMPLETE => {
                     // Try to register this thread as the one RUNNING.
-                    let old = self.state_and_queue.compare_and_swap(
+                    let exchange_result = self.state_and_queue.compare_exchange(
                         state_and_queue,
                         RUNNING,
                         Ordering::Acquire,
+                        Ordering::Acquire,
                     );
-                    if old != state_and_queue {
+                    if let Err(old) = exchange_result {
                         state_and_queue = old;
                         continue;
                     }
@@ -452,8 +453,13 @@ fn wait(state_and_queue: &AtomicUsize, mut current_state: usize) {
 
         // Try to slide in the node at the head of the linked list, making sure
         // that another thread didn't just replace the head of the linked list.
-        let old = state_and_queue.compare_and_swap(current_state, me | RUNNING, Ordering::Release);
-        if old != current_state {
+        let exchange_result = state_and_queue.compare_exchange(
+            current_state,
+            me | RUNNING,
+            Ordering::Release,
+            Ordering::Relaxed,
+        );
+        if let Err(old) = exchange_result {
             current_state = old;
             continue;
         }
diff --git a/library/std/src/sys/sgx/abi/mod.rs b/library/std/src/sys/sgx/abi/mod.rs
index a0eb12c3d15..a5e45303476 100644
--- a/library/std/src/sys/sgx/abi/mod.rs
+++ b/library/std/src/sys/sgx/abi/mod.rs
@@ -36,20 +36,20 @@ unsafe extern "C" fn tcs_init(secondary: bool) {
     }
 
     // Try to atomically swap UNINIT with BUSY. The returned state can be:
-    match RELOC_STATE.compare_and_swap(UNINIT, BUSY, Ordering::Acquire) {
+    match RELOC_STATE.compare_exchange(UNINIT, BUSY, Ordering::Acquire, Ordering::Acquire) {
         // This thread just obtained the lock and other threads will observe BUSY
-        UNINIT => {
+        Ok(_) => {
             reloc::relocate_elf_rela();
             RELOC_STATE.store(DONE, Ordering::Release);
         }
         // We need to wait until the initialization is done.
-        BUSY => {
+        Err(BUSY) => {
             while RELOC_STATE.load(Ordering::Acquire) == BUSY {
                 core::hint::spin_loop();
             }
         }
         // Initialization is done.
-        DONE => {}
+        Err(DONE) => {}
         _ => unreachable!(),
     }
 }
diff --git a/library/std/src/sys/sgx/waitqueue/spin_mutex.rs b/library/std/src/sys/sgx/waitqueue/spin_mutex.rs
index d99ce895da5..9140041c584 100644
--- a/library/std/src/sys/sgx/waitqueue/spin_mutex.rs
+++ b/library/std/src/sys/sgx/waitqueue/spin_mutex.rs
@@ -42,7 +42,7 @@ impl<T> SpinMutex<T> {
 
     #[inline(always)]
     pub fn try_lock(&self) -> Option<SpinMutexGuard<'_, T>> {
-        if !self.lock.compare_and_swap(false, true, Ordering::Acquire) {
+        if self.lock.compare_exchange(false, true, Ordering::Acquire, Ordering::Acquire).is_ok() {
             Some(SpinMutexGuard { mutex: self })
         } else {
             None
diff --git a/library/std/src/sys/unix/ext/net/ancillary.rs b/library/std/src/sys/unix/ext/net/ancillary.rs
index 2c91ba70dd0..0964b6335aa 100644
--- a/library/std/src/sys/unix/ext/net/ancillary.rs
+++ b/library/std/src/sys/unix/ext/net/ancillary.rs
@@ -360,7 +360,11 @@ impl<'a> AncillaryData<'a> {
     fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result<Self, AncillaryError> {
         unsafe {
             cfg_if::cfg_if! {
-                if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
+                if #[cfg(any(
+                        target_os = "android",
+                        all(target_os = "linux", target_env = "gnu"),
+                        all(target_os = "linux", target_env = "uclibc"),
+                   ))] {
                     let cmsg_len_zero = libc::CMSG_LEN(0) as libc::size_t;
                 } else if #[cfg(any(
                               target_os = "dragonfly",
diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs
index 3615a8a5ee8..f4c67b225e6 100644
--- a/library/std/src/sys/unix/ext/process.rs
+++ b/library/std/src/sys/unix/ext/process.rs
@@ -9,6 +9,14 @@ use crate::process;
 use crate::sys;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 
+mod private {
+    /// This trait being unreachable from outside the crate
+    /// prevents other implementations of the `ExitStatusExt` trait,
+    /// which allows potentially adding more trait methods in the future.
+    #[stable(feature = "none", since = "1.51.0")]
+    pub trait Sealed {}
+}
+
 /// Unix-specific extensions to the [`process::Command`] builder.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait CommandExt {
@@ -163,18 +171,48 @@ impl CommandExt for process::Command {
 }
 
 /// Unix-specific extensions to [`process::ExitStatus`].
+///
+/// This trait is sealed: it cannot be implemented outside the standard library.
+/// This is so that future additional methods are not breaking changes.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub trait ExitStatusExt {
+pub trait ExitStatusExt: private::Sealed {
     /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
     /// a process.
     #[stable(feature = "exit_status_from", since = "1.12.0")]
     fn from_raw(raw: i32) -> Self;
 
     /// If the process was terminated by a signal, returns that signal.
+    ///
+    /// In other words, if `WIFSIGNALED`, this returns `WTERMSIG`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn signal(&self) -> Option<i32>;
+
+    /// If the process was terminated by a signal, says whether it dumped core.
+    #[unstable(feature = "unix_process_wait_more", issue = "80695")]
+    fn core_dumped(&self) -> bool;
+
+    /// If the process was stopped by a signal, returns that signal.
+    ///
+    /// In other words, if `WIFSTOPPED`, this returns `WSTOPSIG`.  This is only possible if the status came from
+    /// a `wait` system call which was passed `WUNTRACED`, was then converted into an `ExitStatus`.
+    #[unstable(feature = "unix_process_wait_more", issue = "80695")]
+    fn stopped_signal(&self) -> Option<i32>;
+
+    /// Whether the process was continued from a stopped status.
+    ///
+    /// Ie, `WIFCONTINUED`.  This is only possible if the status came from a `wait` system call
+    /// which was passed `WCONTINUED`, was then converted into an `ExitStatus`.
+    #[unstable(feature = "unix_process_wait_more", issue = "80695")]
+    fn continued(&self) -> bool;
+
+    /// Returns the underlying raw `wait` status.
+    #[unstable(feature = "unix_process_wait_more", issue = "80695")]
+    fn into_raw(self) -> i32;
 }
 
+#[stable(feature = "none", since = "1.51.0")]
+impl private::Sealed for process::ExitStatus {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ExitStatusExt for process::ExitStatus {
     fn from_raw(raw: i32) -> Self {
@@ -184,6 +222,22 @@ impl ExitStatusExt for process::ExitStatus {
     fn signal(&self) -> Option<i32> {
         self.as_inner().signal()
     }
+
+    fn core_dumped(&self) -> bool {
+        self.as_inner().core_dumped()
+    }
+
+    fn stopped_signal(&self) -> Option<i32> {
+        self.as_inner().stopped_signal()
+    }
+
+    fn continued(&self) -> bool {
+        self.as_inner().continued()
+    }
+
+    fn into_raw(self) -> i32 {
+        self.as_inner().into_raw().into()
+    }
 }
 
 #[stable(feature = "process_extensions", since = "1.2.0")]
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs
index d3a279a2355..821851a6c65 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -12,6 +12,11 @@ use crate::sys_common::AsInner;
 use libc::{c_int, c_void};
 
 #[derive(Debug)]
+#[rustc_layout_scalar_valid_range_start(0)]
+// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
+// 32-bit c_int. Below is -2, in two's complement, but that only works out
+// because c_int is 32 bits.
+#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
 pub struct FileDesc {
     fd: c_int,
 }
@@ -63,7 +68,9 @@ const fn max_iov() -> usize {
 
 impl FileDesc {
     pub fn new(fd: c_int) -> FileDesc {
-        FileDesc { fd }
+        assert_ne!(fd, -1i32);
+        // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
+        unsafe { FileDesc { fd } }
     }
 
     pub fn raw(&self) -> c_int {
diff --git a/library/std/src/sys/unix/fd/tests.rs b/library/std/src/sys/unix/fd/tests.rs
index a932043cbc6..c9520485c3c 100644
--- a/library/std/src/sys/unix/fd/tests.rs
+++ b/library/std/src/sys/unix/fd/tests.rs
@@ -3,7 +3,7 @@ use core::mem::ManuallyDrop;
 
 #[test]
 fn limit_vector_count() {
-    let stdout = ManuallyDrop::new(FileDesc { fd: 1 });
+    let stdout = ManuallyDrop::new(unsafe { FileDesc { fd: 1 } });
     let bufs = (0..1500).map(|_| IoSlice::new(&[])).collect::<Vec<_>>();
     assert!(stdout.write_vectored(&bufs).is_ok());
 }
diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs
index b64636c3f3d..0d4703d7f50 100644
--- a/library/std/src/sys/unix/process/process_fuchsia.rs
+++ b/library/std/src/sys/unix/process/process_fuchsia.rs
@@ -245,6 +245,50 @@ impl ExitStatus {
     pub fn signal(&self) -> Option<i32> {
         None
     }
+
+    // FIXME: The actually-Unix implementation in process_unix.rs uses WSTOPSIG, WCOREDUMP et al.
+    // I infer from the implementation of `success`, `code` and `signal` above that these are not
+    // available on Fuchsia.
+    //
+    // It does not appear that Fuchsia is Unix-like enough to implement ExitStatus (or indeed many
+    // other things from std::os::unix) properly.  This veneer is always going to be a bodge.  So
+    // while I don't know if these implementations are actually correct, I think they will do for
+    // now at least.
+    pub fn core_dumped(&self) -> bool {
+        false
+    }
+    pub fn stopped_signal(&self) -> Option<i32> {
+        None
+    }
+    pub fn continued(&self) -> bool {
+        false
+    }
+
+    pub fn into_raw(&self) -> c_int {
+        // We don't know what someone who calls into_raw() will do with this value, but it should
+        // have the conventional Unix representation.  Despite the fact that this is not
+        // standardised in SuS or POSIX, all Unix systems encode the signal and exit status the
+        // same way.  (Ie the WIFEXITED, WEXITSTATUS etc. macros have identical behaviour on every
+        // Unix.)
+        //
+        // The caller of `std::os::unix::into_raw` is probably wanting a Unix exit status, and may
+        // do their own shifting and masking, or even pass the status to another computer running a
+        // different Unix variant.
+        //
+        // The other view would be to say that the caller on Fuchsia ought to know that `into_raw`
+        // will give a raw Fuchsia status (whatever that is - I don't know, personally).  That is
+        // not possible here becaause we must return a c_int because that's what Unix (including
+        // SuS and POSIX) say a wait status is, but Fuchsia apparently uses a u64, so it won't
+        // necessarily fit.
+        //
+        // It seems to me that that the right answer would be to provide std::os::fuchsia with its
+        // own ExitStatusExt, rather that trying to provide a not very convincing imitation of
+        // Unix.  Ie, std::os::unix::process:ExitStatusExt ought not to exist on Fuchsia.  But
+        // fixing this up that is beyond the scope of my efforts now.
+        let exit_status_as_if_unix: u8 = self.0.try_into().expect("Fuchsia process return code bigger than 8 bits, but std::os::unix::ExitStatusExt::into_raw() was called to try to convert the value into a traditional Unix-style wait status, which cannot represent values greater than 255.");
+        let wait_status_as_if_unix = (exit_status_as_if_unix as c_int) << 8;
+        wait_status_as_if_unix
+    }
 }
 
 /// Converts a raw `c_int` to a type-safe `ExitStatus` by wrapping it without copying.
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index a590c744356..945b43678a9 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -479,7 +479,23 @@ impl ExitStatus {
     }
 
     pub fn signal(&self) -> Option<i32> {
-        if !self.exited() { Some(libc::WTERMSIG(self.0)) } else { None }
+        if libc::WIFSIGNALED(self.0) { Some(libc::WTERMSIG(self.0)) } else { None }
+    }
+
+    pub fn core_dumped(&self) -> bool {
+        libc::WIFSIGNALED(self.0) && libc::WCOREDUMP(self.0)
+    }
+
+    pub fn stopped_signal(&self) -> Option<i32> {
+        if libc::WIFSTOPPED(self.0) { Some(libc::WSTOPSIG(self.0)) } else { None }
+    }
+
+    pub fn continued(&self) -> bool {
+        libc::WIFCONTINUED(self.0)
+    }
+
+    pub fn into_raw(&self) -> c_int {
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index fac4b05ad0b..23a5c81c005 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -237,7 +237,7 @@ mod inner {
         // `denom` field.
         //
         // Encoding this as a single `AtomicU64` allows us to use `Relaxed`
-        // operations, as we are only interested in in the effects on a single
+        // operations, as we are only interested in the effects on a single
         // memory location.
         static INFO_BITS: AtomicU64 = AtomicU64::new(0);
 
diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs
index e93a4972caa..432fe4c33bc 100644
--- a/library/std/src/sys/unix/weak.rs
+++ b/library/std/src/sys/unix/weak.rs
@@ -28,7 +28,7 @@ use crate::sync::atomic::{self, AtomicUsize, Ordering};
 
 macro_rules! weak {
     (fn $name:ident($($t:ty),*) -> $ret:ty) => (
-        static $name: crate::sys::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
+        static $name: crate::sys::weak::Weak<unsafe extern "C" fn($($t),*) -> $ret> =
             crate::sys::weak::Weak::new(concat!(stringify!($name), '\0'));
     )
 }
diff --git a/library/std/src/sys/windows/ext/process.rs b/library/std/src/sys/windows/ext/process.rs
index 61e4c6a1d17..7a92381d660 100644
--- a/library/std/src/sys/windows/ext/process.rs
+++ b/library/std/src/sys/windows/ext/process.rs
@@ -7,6 +7,14 @@ use crate::process;
 use crate::sys;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 
+mod private {
+    /// This trait being unreachable from outside the crate
+    /// prevents other implementations of the `ExitStatusExt` trait,
+    /// which allows potentially adding more trait methods in the future.
+    #[stable(feature = "none", since = "1.51.0")]
+    pub trait Sealed {}
+}
+
 #[stable(feature = "process_extensions", since = "1.2.0")]
 impl FromRawHandle for process::Stdio {
     unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio {
@@ -73,8 +81,11 @@ impl IntoRawHandle for process::ChildStderr {
 }
 
 /// Windows-specific extensions to [`process::ExitStatus`].
+///
+/// This trait is sealed: it cannot be implemented outside the standard library.
+/// This is so that future additional methods are not breaking changes.
 #[stable(feature = "exit_status_from", since = "1.12.0")]
-pub trait ExitStatusExt {
+pub trait ExitStatusExt: private::Sealed {
     /// Creates a new `ExitStatus` from the raw underlying `u32` return value of
     /// a process.
     #[stable(feature = "exit_status_from", since = "1.12.0")]
@@ -88,6 +99,9 @@ impl ExitStatusExt for process::ExitStatus {
     }
 }
 
+#[stable(feature = "none", since = "1.51.0")]
+impl private::Sealed for process::ExitStatus {}
+
 /// Windows-specific extensions to the [`process::Command`] builder.
 #[stable(feature = "windows_process_extensions", since = "1.16.0")]
 pub trait CommandExt {
diff --git a/library/std/src/sys/windows/mutex.rs b/library/std/src/sys/windows/mutex.rs
index fa51b006c34..d4cc56d4cb3 100644
--- a/library/std/src/sys/windows/mutex.rs
+++ b/library/std/src/sys/windows/mutex.rs
@@ -123,9 +123,9 @@ impl Mutex {
         let inner = box Inner { remutex: ReentrantMutex::uninitialized(), held: Cell::new(false) };
         inner.remutex.init();
         let inner = Box::into_raw(inner);
-        match self.lock.compare_and_swap(0, inner as usize, Ordering::SeqCst) {
-            0 => inner,
-            n => {
+        match self.lock.compare_exchange(0, inner as usize, Ordering::SeqCst, Ordering::SeqCst) {
+            Ok(_) => inner,
+            Err(n) => {
                 Box::from_raw(inner).remutex.destroy();
                 n as *const _
             }
diff --git a/library/std/src/sys/windows/thread_parker.rs b/library/std/src/sys/windows/thread_parker.rs
index 701c6e2e9be..9e4c9aa0a51 100644
--- a/library/std/src/sys/windows/thread_parker.rs
+++ b/library/std/src/sys/windows/thread_parker.rs
@@ -113,7 +113,7 @@ impl Parker {
                 // Wait for something to happen, assuming it's still set to PARKED.
                 c::WaitOnAddress(self.ptr(), &PARKED as *const _ as c::LPVOID, 1, c::INFINITE);
                 // Change NOTIFIED=>EMPTY but leave PARKED alone.
-                if self.state.compare_and_swap(NOTIFIED, EMPTY, Acquire) == NOTIFIED {
+                if self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Acquire).is_ok() {
                     // Actually woken up by unpark().
                     return;
                 } else {
diff --git a/library/std/src/sys_common/condvar/check.rs b/library/std/src/sys_common/condvar/check.rs
index fecb732b910..1578a2de60c 100644
--- a/library/std/src/sys_common/condvar/check.rs
+++ b/library/std/src/sys_common/condvar/check.rs
@@ -23,9 +23,9 @@ impl SameMutexCheck {
     }
     pub fn verify(&self, mutex: &MovableMutex) {
         let addr = mutex.raw() as *const mutex_imp::Mutex as usize;
-        match self.addr.compare_and_swap(0, addr, Ordering::SeqCst) {
-            0 => {}              // Stored the address
-            n if n == addr => {} // Lost a race to store the same address
+        match self.addr.compare_exchange(0, addr, Ordering::SeqCst, Ordering::SeqCst) {
+            Ok(_) => {}               // Stored the address
+            Err(n) if n == addr => {} // Lost a race to store the same address
             _ => panic!("attempted to use a condition variable with two mutexes"),
         }
     }
diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs
index e30e8018a31..6bdb26cd078 100644
--- a/library/std/src/sys_common/fs.rs
+++ b/library/std/src/sys_common/fs.rs
@@ -5,19 +5,21 @@ use crate::io::{self, Error, ErrorKind};
 use crate::path::Path;
 
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
-    if !from.is_file() {
+    let mut reader = fs::File::open(from)?;
+    let metadata = reader.metadata()?;
+
+    if !metadata.is_file() {
         return Err(Error::new(
             ErrorKind::InvalidInput,
             "the source path is not an existing regular file",
         ));
     }
 
-    let mut reader = fs::File::open(from)?;
     let mut writer = fs::File::create(to)?;
-    let perm = reader.metadata()?.permissions();
+    let perm = metadata.permissions();
 
     let ret = io::copy(&mut reader, &mut writer)?;
-    fs::set_permissions(to, perm)?;
+    writer.set_permissions(perm)?;
     Ok(ret)
 }
 
diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs
index dbcb7b36265..32cd5641665 100644
--- a/library/std/src/sys_common/thread_local_key.rs
+++ b/library/std/src/sys_common/thread_local_key.rs
@@ -168,7 +168,7 @@ impl StaticKey {
             return key;
         }
 
-        // POSIX allows the key created here to be 0, but the compare_and_swap
+        // POSIX allows the key created here to be 0, but the compare_exchange
         // below relies on using 0 as a sentinel value to check who won the
         // race to set the shared TLS key. As far as I know, there is no
         // guaranteed value that cannot be returned as a posix_key_create key,
@@ -186,11 +186,11 @@ impl StaticKey {
             key2
         };
         rtassert!(key != 0);
-        match self.key.compare_and_swap(0, key as usize, Ordering::SeqCst) {
+        match self.key.compare_exchange(0, key as usize, Ordering::SeqCst, Ordering::SeqCst) {
             // The CAS succeeded, so we've created the actual key
-            0 => key as usize,
+            Ok(_) => key as usize,
             // If someone beat us to the punch, use their key instead
-            n => {
+            Err(n) => {
                 imp::destroy(key);
                 n
             }
diff --git a/library/std/src/sys_common/thread_parker/futex.rs b/library/std/src/sys_common/thread_parker/futex.rs
index a5d4927dcc5..0132743b244 100644
--- a/library/std/src/sys_common/thread_parker/futex.rs
+++ b/library/std/src/sys_common/thread_parker/futex.rs
@@ -49,7 +49,7 @@ impl Parker {
             // Wait for something to happen, assuming it's still set to PARKED.
             futex_wait(&self.state, PARKED, None);
             // Change NOTIFIED=>EMPTY and return in that case.
-            if self.state.compare_and_swap(NOTIFIED, EMPTY, Acquire) == NOTIFIED {
+            if self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Acquire).is_ok() {
                 return;
             } else {
                 // Spurious wake up. We loop to try again.