about summary refs log tree commit diff
path: root/library/core
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-04-02 22:22:18 +0000
committerGitHub <noreply@github.com>2025-04-02 22:22:18 +0000
commit5103bdeb29d7aa4d7ad4d811893c76baa8a98ab7 (patch)
treec989d04f4bcd32bcd93ed62208af68e1dbe36b6d /library/core
parent4858c3fe7d1a9a7484db4998199f6deb1e05185a (diff)
parente435ba32d85057070dba3f07fa8afd96799a0cfb (diff)
Merge pull request #4245 from RalfJung/rustup
Rustup
Diffstat (limited to 'library/core')
-rw-r--r--library/core/src/cell.rs10
-rw-r--r--library/core/src/cmp.rs134
-rw-r--r--library/core/src/ffi/primitives.rs28
-rw-r--r--library/core/src/fmt/float.rs6
-rw-r--r--library/core/src/fmt/mod.rs394
-rw-r--r--library/core/src/fmt/rt.rs15
-rw-r--r--library/core/src/internal_macros.rs77
-rw-r--r--library/core/src/intrinsics/mod.rs1
-rw-r--r--library/core/src/iter/adapters/flatten.rs55
-rw-r--r--library/core/src/iter/sources/repeat_n.rs59
-rw-r--r--library/core/src/iter/traits/accum.rs4
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/macros/mod.rs2
-rw-r--r--library/core/src/net/ip_addr.rs2
-rw-r--r--library/core/src/num/f32.rs23
-rw-r--r--library/core/src/pin.rs1
-rw-r--r--library/core/src/primitive_docs.rs8
-rw-r--r--library/core/src/ptr/const_ptr.rs3
-rw-r--r--library/core/src/slice/sort/select.rs8
-rw-r--r--library/core/src/slice/sort/stable/mod.rs16
-rw-r--r--library/core/src/slice/sort/unstable/mod.rs9
-rw-r--r--library/core/src/slice/sort/unstable/quicksort.rs9
-rw-r--r--library/core/src/sync/atomic.rs3
-rw-r--r--library/core/src/tuple.rs24
24 files changed, 482 insertions, 410 deletions
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 1a320b316a4..e789601a409 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -495,7 +495,7 @@ impl<T> Cell<T> {
     /// ```
     #[inline]
     #[stable(feature = "move_cell", since = "1.17.0")]
-    #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+    #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_confusables("swap")]
     pub const fn replace(&self, val: T) -> T {
         // SAFETY: This can cause data races if called from a separate thread,
@@ -537,7 +537,7 @@ impl<T: Copy> Cell<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+    #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn get(&self) -> T {
         // SAFETY: This can cause data races if called from a separate thread,
         // but `Cell` is `!Sync` so this won't happen.
@@ -617,7 +617,7 @@ impl<T: ?Sized> Cell<T> {
     /// ```
     #[inline]
     #[stable(feature = "cell_get_mut", since = "1.11.0")]
-    #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+    #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn get_mut(&mut self) -> &mut T {
         self.value.get_mut()
     }
@@ -637,7 +637,7 @@ impl<T: ?Sized> Cell<T> {
     /// ```
     #[inline]
     #[stable(feature = "as_cell", since = "1.37.0")]
-    #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+    #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn from_mut(t: &mut T) -> &Cell<T> {
         // SAFETY: `&mut` ensures unique access.
         unsafe { &*(t as *mut T as *const Cell<T>) }
@@ -695,7 +695,7 @@ impl<T> Cell<[T]> {
     /// assert_eq!(slice_cell.len(), 3);
     /// ```
     #[stable(feature = "as_cell", since = "1.37.0")]
-    #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+    #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn as_slice_of_cells(&self) -> &[Cell<T>] {
         // SAFETY: `Cell<T>` has the same memory layout as `T`.
         unsafe { &*(self as *const Cell<[T]> as *const [Cell<T>]) }
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 25bd17d5802..0dc2cc72e06 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -29,6 +29,7 @@ mod bytewise;
 pub(crate) use bytewise::BytewiseEq;
 
 use self::Ordering::*;
+use crate::ops::ControlFlow;
 
 /// Trait for comparisons using the equality operator.
 ///
@@ -1435,6 +1436,67 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     fn ge(&self, other: &Rhs) -> bool {
         self.partial_cmp(other).is_some_and(Ordering::is_ge)
     }
+
+    /// If `self == other`, returns `ControlFlow::Continue(())`.
+    /// Otherwise, returns `ControlFlow::Break(self < other)`.
+    ///
+    /// This is useful for chaining together calls when implementing a lexical
+    /// `PartialOrd::lt`, as it allows types (like primitives) which can cheaply
+    /// check `==` and `<` separately to do rather than needing to calculate
+    /// (then optimize out) the three-way `Ordering` result.
+    #[inline]
+    #[must_use]
+    // Added to improve the behaviour of tuples; not necessarily stabilization-track.
+    #[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
+    #[doc(hidden)]
+    fn __chaining_lt(&self, other: &Rhs) -> ControlFlow<bool> {
+        default_chaining_impl(self, other, Ordering::is_lt)
+    }
+
+    /// Same as `__chaining_lt`, but for `<=` instead of `<`.
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
+    #[doc(hidden)]
+    fn __chaining_le(&self, other: &Rhs) -> ControlFlow<bool> {
+        default_chaining_impl(self, other, Ordering::is_le)
+    }
+
+    /// Same as `__chaining_lt`, but for `>` instead of `<`.
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
+    #[doc(hidden)]
+    fn __chaining_gt(&self, other: &Rhs) -> ControlFlow<bool> {
+        default_chaining_impl(self, other, Ordering::is_gt)
+    }
+
+    /// Same as `__chaining_lt`, but for `>=` instead of `<`.
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
+    #[doc(hidden)]
+    fn __chaining_ge(&self, other: &Rhs) -> ControlFlow<bool> {
+        default_chaining_impl(self, other, Ordering::is_ge)
+    }
+}
+
+fn default_chaining_impl<T: ?Sized, U: ?Sized>(
+    lhs: &T,
+    rhs: &U,
+    p: impl FnOnce(Ordering) -> bool,
+) -> ControlFlow<bool>
+where
+    T: PartialOrd<U>,
+{
+    // It's important that this only call `partial_cmp` once, not call `eq` then
+    // one of the relational operators.  We don't want to `bcmp`-then-`memcp` a
+    // `String`, for example, or similarly for other data structures (#108157).
+    match <T as PartialOrd<U>>::partial_cmp(lhs, rhs) {
+        Some(Equal) => ControlFlow::Continue(()),
+        Some(c) => ControlFlow::Break(p(c)),
+        None => ControlFlow::Break(false),
+    }
 }
 
 /// Derive macro generating an impl of the trait [`PartialOrd`].
@@ -1741,15 +1803,16 @@ where
 mod impls {
     use crate::cmp::Ordering::{self, Equal, Greater, Less};
     use crate::hint::unreachable_unchecked;
+    use crate::ops::ControlFlow::{self, Break, Continue};
 
     macro_rules! partial_eq_impl {
         ($($t:ty)*) => ($(
             #[stable(feature = "rust1", since = "1.0.0")]
             impl PartialEq for $t {
                 #[inline]
-                fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
+                fn eq(&self, other: &Self) -> bool { *self == *other }
                 #[inline]
-                fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
+                fn ne(&self, other: &Self) -> bool { *self != *other }
             }
         )*)
     }
@@ -1779,12 +1842,51 @@ mod impls {
 
     eq_impl! { () bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
+    #[rustfmt::skip]
+    macro_rules! partial_ord_methods_primitive_impl {
+        () => {
+            #[inline(always)]
+            fn lt(&self, other: &Self) -> bool { *self <  *other }
+            #[inline(always)]
+            fn le(&self, other: &Self) -> bool { *self <= *other }
+            #[inline(always)]
+            fn gt(&self, other: &Self) -> bool { *self >  *other }
+            #[inline(always)]
+            fn ge(&self, other: &Self) -> bool { *self >= *other }
+
+            // These implementations are the same for `Ord` or `PartialOrd` types
+            // because if either is NAN the `==` test will fail so we end up in
+            // the `Break` case and the comparison will correctly return `false`.
+
+            #[inline]
+            fn __chaining_lt(&self, other: &Self) -> ControlFlow<bool> {
+                let (lhs, rhs) = (*self, *other);
+                if lhs == rhs { Continue(()) } else { Break(lhs < rhs) }
+            }
+            #[inline]
+            fn __chaining_le(&self, other: &Self) -> ControlFlow<bool> {
+                let (lhs, rhs) = (*self, *other);
+                if lhs == rhs { Continue(()) } else { Break(lhs <= rhs) }
+            }
+            #[inline]
+            fn __chaining_gt(&self, other: &Self) -> ControlFlow<bool> {
+                let (lhs, rhs) = (*self, *other);
+                if lhs == rhs { Continue(()) } else { Break(lhs > rhs) }
+            }
+            #[inline]
+            fn __chaining_ge(&self, other: &Self) -> ControlFlow<bool> {
+                let (lhs, rhs) = (*self, *other);
+                if lhs == rhs { Continue(()) } else { Break(lhs >= rhs) }
+            }
+        };
+    }
+
     macro_rules! partial_ord_impl {
         ($($t:ty)*) => ($(
             #[stable(feature = "rust1", since = "1.0.0")]
             impl PartialOrd for $t {
                 #[inline]
-                fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
+                fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
                     match (*self <= *other, *self >= *other) {
                         (false, false) => None,
                         (false, true) => Some(Greater),
@@ -1792,14 +1894,8 @@ mod impls {
                         (true, true) => Some(Equal),
                     }
                 }
-                #[inline(always)]
-                fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
-                #[inline(always)]
-                fn le(&self, other: &$t) -> bool { (*self) <= (*other) }
-                #[inline(always)]
-                fn ge(&self, other: &$t) -> bool { (*self) >= (*other) }
-                #[inline(always)]
-                fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
+
+                partial_ord_methods_primitive_impl!();
             }
         )*)
     }
@@ -1818,6 +1914,8 @@ mod impls {
         fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
             Some(self.cmp(other))
         }
+
+        partial_ord_methods_primitive_impl!();
     }
 
     partial_ord_impl! { f16 f32 f64 f128 }
@@ -1827,23 +1925,17 @@ mod impls {
             #[stable(feature = "rust1", since = "1.0.0")]
             impl PartialOrd for $t {
                 #[inline]
-                fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
+                fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
                     Some(crate::intrinsics::three_way_compare(*self, *other))
                 }
-                #[inline(always)]
-                fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
-                #[inline(always)]
-                fn le(&self, other: &$t) -> bool { (*self) <= (*other) }
-                #[inline(always)]
-                fn ge(&self, other: &$t) -> bool { (*self) >= (*other) }
-                #[inline(always)]
-                fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
+
+                partial_ord_methods_primitive_impl!();
             }
 
             #[stable(feature = "rust1", since = "1.0.0")]
             impl Ord for $t {
                 #[inline]
-                fn cmp(&self, other: &$t) -> Ordering {
+                fn cmp(&self, other: &Self) -> Ordering {
                     crate::intrinsics::three_way_compare(*self, *other)
                 }
             }
diff --git a/library/core/src/ffi/primitives.rs b/library/core/src/ffi/primitives.rs
index 0a70eb4da55..351bf9f8314 100644
--- a/library/core/src/ffi/primitives.rs
+++ b/library/core/src/ffi/primitives.rs
@@ -35,7 +35,7 @@ type_alias! { "c_float.md", c_float = f32; }
 type_alias! { "c_double.md", c_double = f64; }
 
 mod c_char_definition {
-    cfg_if! {
+    crate::cfg_match! {
         // These are the targets on which c_char is unsigned. Usually the
         // signedness is the same for all target_os values on a given architecture
         // but there are some exceptions (see isSignedCharDefault() in clang).
@@ -105,7 +105,7 @@ mod c_char_definition {
         //   architecture defaults). As we only have a target for userspace apps so there are no
         //   special cases for L4Re below.
         //   https://github.com/rust-lang/rust/pull/132975#issuecomment-2484645240
-        if #[cfg(all(
+        all(
             not(windows),
             not(target_vendor = "apple"),
             not(target_os = "vita"),
@@ -122,24 +122,27 @@ mod c_char_definition {
                 target_arch = "s390x",
                 target_arch = "xtensa",
             )
-        ))] {
+        ) => {
             pub(super) type c_char = u8;
-        } else {
-            // On every other target, c_char is signed.
+        }
+        // On every other target, c_char is signed.
+        _ => {
             pub(super) type c_char = i8;
         }
     }
 }
 
 mod c_long_definition {
-    cfg_if! {
-        if #[cfg(any(
+    crate::cfg_match! {
+        any(
             all(target_pointer_width = "64", not(windows)),
             // wasm32 Linux ABI uses 64-bit long
-            all(target_arch = "wasm32", target_os = "linux")))] {
+            all(target_arch = "wasm32", target_os = "linux")
+        ) => {
             pub(super) type c_long = i64;
             pub(super) type c_ulong = u64;
-        } else {
+        }
+        _ => {
             // The minimal size of `long` in the C standard is 32 bits
             pub(super) type c_long = i32;
             pub(super) type c_ulong = u32;
@@ -169,11 +172,12 @@ pub type c_ptrdiff_t = isize;
 pub type c_ssize_t = isize;
 
 mod c_int_definition {
-    cfg_if! {
-        if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] {
+    crate::cfg_match! {
+        any(target_arch = "avr", target_arch = "msp430") => {
             pub(super) type c_int = i16;
             pub(super) type c_uint = u16;
-        } else {
+        }
+        _ => {
             pub(super) type c_int = i32;
             pub(super) type c_uint = u32;
         }
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index 4a43c12be9a..870ad9df4fd 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -86,7 +86,7 @@ where
         true => flt2dec::Sign::MinusPlus,
     };
 
-    if let Some(precision) = fmt.options.precision {
+    if let Some(precision) = fmt.options.get_precision() {
         float_to_decimal_common_exact(fmt, num, sign, precision)
     } else {
         let min_precision = 0;
@@ -162,7 +162,7 @@ where
         true => flt2dec::Sign::MinusPlus,
     };
 
-    if let Some(precision) = fmt.options.precision {
+    if let Some(precision) = fmt.options.get_precision() {
         // 1 integral digit + `precision` fractional digits = `precision + 1` total digits
         float_to_exponential_common_exact(fmt, num, sign, precision + 1, upper)
     } else {
@@ -180,7 +180,7 @@ where
         true => flt2dec::Sign::MinusPlus,
     };
 
-    if let Some(precision) = fmt.options.precision {
+    if let Some(precision) = fmt.options.get_precision() {
         // this behavior of {:.PREC?} predates exponential formatting for {:?}
         float_to_decimal_common_exact(fmt, num, sign, precision)
     } else {
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 48f36044471..30fd2d7815f 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -33,19 +33,6 @@ pub enum Alignment {
     Center,
 }
 
-#[doc(hidden)]
-#[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")]
-impl From<rt::Alignment> for Option<Alignment> {
-    fn from(value: rt::Alignment) -> Self {
-        match value {
-            rt::Alignment::Left => Some(Alignment::Left),
-            rt::Alignment::Right => Some(Alignment::Right),
-            rt::Alignment::Center => Some(Alignment::Center),
-            rt::Alignment::Unknown => None,
-        }
-    }
-}
-
 #[stable(feature = "debug_builders", since = "1.2.0")]
 pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
 #[unstable(feature = "debug_closure_helpers", issue = "117729")]
@@ -291,11 +278,52 @@ pub enum DebugAsHex {
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[unstable(feature = "formatting_options", issue = "118117")]
 pub struct FormattingOptions {
+    /// Flags, with the following bit fields:
+    ///
+    /// ```text
+    ///   31  30  29  28  27  26  25  24  23  22  21  20                              0
+    /// ┌───┬───────┬───┬───┬───┬───┬───┬───┬───┬───┬──────────────────────────────────┐
+    /// │ 1 │ align │ p │ w │ X?│ x?│'0'│ # │ - │ + │               fill               │
+    /// └───┴───────┴───┴───┴───┴───┴───┴───┴───┴───┴──────────────────────────────────┘
+    ///   │     │     │   │  └─┬───────────────────┘ └─┬──────────────────────────────┘
+    ///   │     │     │   │    │                       └─ The fill character (21 bits char).
+    ///   │     │     │   │    └─ The debug upper/lower hex, zero pad, alternate, and plus/minus flags.
+    ///   │     │     │   └─ Whether a width is set. (The value is stored separately.)
+    ///   │     │     └─ Whether a precision is set. (The value is stored separately.)
+    ///   │     ├─ 0: Align left. (<)
+    ///   │     ├─ 1: Align right. (>)
+    ///   │     ├─ 2: Align center. (^)
+    ///   │     └─ 3: Alignment not set. (default)
+    ///   └─ Always set.
+    ///      This makes it possible to distinguish formatting flags from
+    ///      a &str size when stored in (the upper bits of) the same field.
+    ///      (fmt::Arguments will make use of this property in the future.)
+    /// ```
+    // Note: This could use a special niche type with range 0x8000_0000..=0xfdd0ffff.
+    // It's unclear if that's useful, though.
     flags: u32,
-    fill: char,
-    align: Option<Alignment>,
-    width: Option<u16>,
-    precision: Option<u16>,
+    /// Width if width flag (bit 27) above is set. Otherwise, always 0.
+    width: u16,
+    /// Precision if precision flag (bit 28) above is set. Otherwise, always 0.
+    precision: u16,
+}
+
+// This needs to match with compiler/rustc_ast_lowering/src/format.rs.
+mod flags {
+    pub(super) const SIGN_PLUS_FLAG: u32 = 1 << 21;
+    pub(super) const SIGN_MINUS_FLAG: u32 = 1 << 22;
+    pub(super) const ALTERNATE_FLAG: u32 = 1 << 23;
+    pub(super) const SIGN_AWARE_ZERO_PAD_FLAG: u32 = 1 << 24;
+    pub(super) const DEBUG_LOWER_HEX_FLAG: u32 = 1 << 25;
+    pub(super) const DEBUG_UPPER_HEX_FLAG: u32 = 1 << 26;
+    pub(super) const WIDTH_FLAG: u32 = 1 << 27;
+    pub(super) const PRECISION_FLAG: u32 = 1 << 28;
+    pub(super) const ALIGN_BITS: u32 = 0b11 << 29;
+    pub(super) const ALIGN_LEFT: u32 = 0 << 29;
+    pub(super) const ALIGN_RIGHT: u32 = 1 << 29;
+    pub(super) const ALIGN_CENTER: u32 = 2 << 29;
+    pub(super) const ALIGN_UNKNOWN: u32 = 3 << 29;
+    pub(super) const ALWAYS_SET: u32 = 1 << 31;
 }
 
 impl FormattingOptions {
@@ -311,7 +339,11 @@ impl FormattingOptions {
     /// - no [`DebugAsHex`] output mode.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn new() -> Self {
-        Self { flags: 0, fill: ' ', align: None, width: None, precision: None }
+        Self {
+            flags: ' ' as u32 | flags::ALIGN_UNKNOWN | flags::ALWAYS_SET,
+            width: 0,
+            precision: 0,
+        }
     }
 
     /// Sets or removes the sign (the `+` or the `-` flag).
@@ -324,13 +356,12 @@ impl FormattingOptions {
     /// - `-`: Currently not used
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn sign(&mut self, sign: Option<Sign>) -> &mut Self {
-        self.flags =
-            self.flags & !(1 << rt::Flag::SignMinus as u32 | 1 << rt::Flag::SignPlus as u32);
-        match sign {
-            None => {}
-            Some(Sign::Plus) => self.flags |= 1 << rt::Flag::SignPlus as u32,
-            Some(Sign::Minus) => self.flags |= 1 << rt::Flag::SignMinus as u32,
-        }
+        let sign = match sign {
+            None => 0,
+            Some(Sign::Plus) => flags::SIGN_PLUS_FLAG,
+            Some(Sign::Minus) => flags::SIGN_MINUS_FLAG,
+        };
+        self.flags = self.flags & !(flags::SIGN_PLUS_FLAG | flags::SIGN_MINUS_FLAG) | sign;
         self
     }
     /// Sets or unsets the `0` flag.
@@ -339,9 +370,9 @@ impl FormattingOptions {
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self {
         if sign_aware_zero_pad {
-            self.flags |= 1 << rt::Flag::SignAwareZeroPad as u32
+            self.flags |= flags::SIGN_AWARE_ZERO_PAD_FLAG;
         } else {
-            self.flags &= !(1 << rt::Flag::SignAwareZeroPad as u32)
+            self.flags &= !flags::SIGN_AWARE_ZERO_PAD_FLAG;
         }
         self
     }
@@ -356,9 +387,9 @@ impl FormattingOptions {
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn alternate(&mut self, alternate: bool) -> &mut Self {
         if alternate {
-            self.flags |= 1 << rt::Flag::Alternate as u32
+            self.flags |= flags::ALTERNATE_FLAG;
         } else {
-            self.flags &= !(1 << rt::Flag::Alternate as u32)
+            self.flags &= !flags::ALTERNATE_FLAG;
         }
         self
     }
@@ -370,7 +401,7 @@ impl FormattingOptions {
     /// printed around it.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn fill(&mut self, fill: char) -> &mut Self {
-        self.fill = fill;
+        self.flags = self.flags & (u32::MAX << 21) | fill as u32;
         self
     }
     /// Sets or removes the alignment.
@@ -379,7 +410,13 @@ impl FormattingOptions {
     /// positioned if it is smaller than the width of the formatter.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn align(&mut self, align: Option<Alignment>) -> &mut Self {
-        self.align = align;
+        let align: u32 = match align {
+            Some(Alignment::Left) => flags::ALIGN_LEFT,
+            Some(Alignment::Right) => flags::ALIGN_RIGHT,
+            Some(Alignment::Center) => flags::ALIGN_CENTER,
+            None => flags::ALIGN_UNKNOWN,
+        };
+        self.flags = self.flags & !flags::ALIGN_BITS | align;
         self
     }
     /// Sets or removes the width.
@@ -390,7 +427,13 @@ impl FormattingOptions {
     /// will be used to take up the required space.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn width(&mut self, width: Option<u16>) -> &mut Self {
-        self.width = width;
+        if let Some(width) = width {
+            self.flags |= flags::WIDTH_FLAG;
+            self.width = width;
+        } else {
+            self.flags &= !flags::WIDTH_FLAG;
+            self.width = 0;
+        }
         self
     }
     /// Sets or removes the precision.
@@ -404,77 +447,85 @@ impl FormattingOptions {
     /// decimal point should be printed.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn precision(&mut self, precision: Option<u16>) -> &mut Self {
-        self.precision = precision;
+        if let Some(precision) = precision {
+            self.flags |= flags::PRECISION_FLAG;
+            self.precision = precision;
+        } else {
+            self.flags &= !flags::PRECISION_FLAG;
+            self.precision = 0;
+        }
         self
     }
     /// Specifies whether the [`Debug`] trait should use lower-/upper-case
     /// hexadecimal or normal integers
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self {
-        self.flags = self.flags
-            & !(1 << rt::Flag::DebugUpperHex as u32 | 1 << rt::Flag::DebugLowerHex as u32);
-        match debug_as_hex {
-            None => {}
-            Some(DebugAsHex::Upper) => self.flags |= 1 << rt::Flag::DebugUpperHex as u32,
-            Some(DebugAsHex::Lower) => self.flags |= 1 << rt::Flag::DebugLowerHex as u32,
-        }
+        let debug_as_hex = match debug_as_hex {
+            None => 0,
+            Some(DebugAsHex::Lower) => flags::DEBUG_LOWER_HEX_FLAG,
+            Some(DebugAsHex::Upper) => flags::DEBUG_UPPER_HEX_FLAG,
+        };
+        self.flags = self.flags & !(flags::DEBUG_LOWER_HEX_FLAG | flags::DEBUG_UPPER_HEX_FLAG)
+            | debug_as_hex;
         self
     }
 
     /// Returns the current sign (the `+` or the `-` flag).
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_sign(&self) -> Option<Sign> {
-        const SIGN_PLUS_BITFIELD: u32 = 1 << rt::Flag::SignPlus as u32;
-        const SIGN_MINUS_BITFIELD: u32 = 1 << rt::Flag::SignMinus as u32;
-        match self.flags & ((1 << rt::Flag::SignPlus as u32) | (1 << rt::Flag::SignMinus as u32)) {
-            SIGN_PLUS_BITFIELD => Some(Sign::Plus),
-            SIGN_MINUS_BITFIELD => Some(Sign::Minus),
-            0 => None,
-            _ => panic!("Invalid sign bits set in flags"),
+        if self.flags & flags::SIGN_PLUS_FLAG != 0 {
+            Some(Sign::Plus)
+        } else if self.flags & flags::SIGN_MINUS_FLAG != 0 {
+            Some(Sign::Minus)
+        } else {
+            None
         }
     }
     /// Returns the current `0` flag.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_sign_aware_zero_pad(&self) -> bool {
-        self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0
+        self.flags & flags::SIGN_AWARE_ZERO_PAD_FLAG != 0
     }
     /// Returns the current `#` flag.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_alternate(&self) -> bool {
-        self.flags & (1 << rt::Flag::Alternate as u32) != 0
+        self.flags & flags::ALTERNATE_FLAG != 0
     }
     /// Returns the current fill character.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_fill(&self) -> char {
-        self.fill
+        // SAFETY: We only ever put a valid `char` in the lower 21 bits of the flags field.
+        unsafe { char::from_u32_unchecked(self.flags & 0x1FFFFF) }
     }
     /// Returns the current alignment.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_align(&self) -> Option<Alignment> {
-        self.align
+        match self.flags & flags::ALIGN_BITS {
+            flags::ALIGN_LEFT => Some(Alignment::Left),
+            flags::ALIGN_RIGHT => Some(Alignment::Right),
+            flags::ALIGN_CENTER => Some(Alignment::Center),
+            _ => None,
+        }
     }
     /// Returns the current width.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_width(&self) -> Option<u16> {
-        self.width
+        if self.flags & flags::WIDTH_FLAG != 0 { Some(self.width) } else { None }
     }
     /// Returns the current precision.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_precision(&self) -> Option<u16> {
-        self.precision
+        if self.flags & flags::PRECISION_FLAG != 0 { Some(self.precision) } else { None }
     }
     /// Returns the current precision.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_debug_as_hex(&self) -> Option<DebugAsHex> {
-        const DEBUG_UPPER_BITFIELD: u32 = 1 << rt::Flag::DebugUpperHex as u32;
-        const DEBUG_LOWER_BITFIELD: u32 = 1 << rt::Flag::DebugLowerHex as u32;
-        match self.flags
-            & ((1 << rt::Flag::DebugUpperHex as u32) | (1 << rt::Flag::DebugLowerHex as u32))
-        {
-            DEBUG_UPPER_BITFIELD => Some(DebugAsHex::Upper),
-            DEBUG_LOWER_BITFIELD => Some(DebugAsHex::Lower),
-            0 => None,
-            _ => panic!("Invalid hex debug bits set in flags"),
+        if self.flags & flags::DEBUG_LOWER_HEX_FLAG != 0 {
+            Some(DebugAsHex::Lower)
+        } else if self.flags & flags::DEBUG_UPPER_HEX_FLAG != 0 {
+            Some(DebugAsHex::Upper)
+        } else {
+            None
         }
     }
 
@@ -485,27 +536,6 @@ impl FormattingOptions {
     pub fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> {
         Formatter { options: self, buf: write }
     }
-
-    #[doc(hidden)]
-    #[unstable(
-        feature = "fmt_internals",
-        reason = "internal routines only exposed for testing",
-        issue = "none"
-    )]
-    /// Flags for formatting
-    pub fn flags(&mut self, flags: u32) {
-        self.flags = flags
-    }
-    #[doc(hidden)]
-    #[unstable(
-        feature = "fmt_internals",
-        reason = "internal routines only exposed for testing",
-        issue = "none"
-    )]
-    /// Flags for formatting
-    pub fn get_flags(&self) -> u32 {
-        self.flags
-    }
 }
 
 #[unstable(feature = "formatting_options", issue = "118117")]
@@ -1479,15 +1509,25 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
 }
 
 unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argument<'_>]) -> Result {
-    fmt.options.fill = arg.fill;
-    fmt.options.align = arg.align.into();
-    fmt.options.flags = arg.flags;
-    // SAFETY: arg and args come from the same Arguments,
-    // which guarantees the indexes are always within bounds.
-    unsafe {
-        fmt.options.width = getcount(args, &arg.width);
-        fmt.options.precision = getcount(args, &arg.precision);
-    }
+    let (width, precision) =
+        // SAFETY: arg and args come from the same Arguments,
+        // which guarantees the indexes are always within bounds.
+        unsafe { (getcount(args, &arg.width), getcount(args, &arg.precision)) };
+
+    #[cfg(bootstrap)]
+    let options =
+        *FormattingOptions { flags: flags::ALWAYS_SET | arg.flags << 21, width: 0, precision: 0 }
+            .align(match arg.align {
+                rt::Alignment::Left => Some(Alignment::Left),
+                rt::Alignment::Right => Some(Alignment::Right),
+                rt::Alignment::Center => Some(Alignment::Center),
+                rt::Alignment::Unknown => None,
+            })
+            .fill(arg.fill)
+            .width(width)
+            .precision(precision);
+    #[cfg(not(bootstrap))]
+    let options = FormattingOptions { flags: arg.flags, width, precision };
 
     // Extract the correct argument
     debug_assert!(arg.position < args.len());
@@ -1495,17 +1535,18 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argume
     // which guarantees its index is always within bounds.
     let value = unsafe { args.get_unchecked(arg.position) };
 
+    // Set all the formatting options.
+    fmt.options = options;
+
     // Then actually do some printing
     // SAFETY: this is a placeholder argument.
     unsafe { value.fmt(fmt) }
 }
 
+#[cfg(bootstrap)]
 unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<u16> {
     match *cnt {
-        #[cfg(bootstrap)]
         rt::Count::Is(n) => Some(n as u16),
-        #[cfg(not(bootstrap))]
-        rt::Count::Is(n) => Some(n),
         rt::Count::Implied => None,
         rt::Count::Param(i) => {
             debug_assert!(i < args.len());
@@ -1516,6 +1557,20 @@ unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<u16> {
     }
 }
 
+#[cfg(not(bootstrap))]
+unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> u16 {
+    match *cnt {
+        rt::Count::Is(n) => n,
+        rt::Count::Implied => 0,
+        rt::Count::Param(i) => {
+            debug_assert!(i < args.len());
+            // SAFETY: cnt and args come from the same Arguments,
+            // which guarantees this index is always within bounds.
+            unsafe { args.get_unchecked(i).as_u16().unwrap_unchecked() }
+        }
+    }
+}
+
 /// Padding after the end of something. Returned by `Formatter::padding`.
 #[must_use = "don't forget to write the post padding"]
 pub(crate) struct PostPadding {
@@ -1629,40 +1684,28 @@ impl<'a> Formatter<'a> {
         }
 
         // The `width` field is more of a `min-width` parameter at this point.
-        match self.options.width {
-            // If there's no minimum length requirements then we can just
-            // write the bytes.
-            None => {
-                write_prefix(self, sign, prefix)?;
-                self.buf.write_str(buf)
-            }
-            // Check if we're over the minimum width, if so then we can also
-            // just write the bytes.
-            Some(min) if width >= usize::from(min) => {
-                write_prefix(self, sign, prefix)?;
-                self.buf.write_str(buf)
-            }
+        let min = self.options.width;
+        if width >= usize::from(min) {
+            // We're over the minimum width, so then we can just write the bytes.
+            write_prefix(self, sign, prefix)?;
+            self.buf.write_str(buf)
+        } else if self.sign_aware_zero_pad() {
             // The sign and prefix goes before the padding if the fill character
             // is zero
-            Some(min) if self.sign_aware_zero_pad() => {
-                let old_fill = crate::mem::replace(&mut self.options.fill, '0');
-                let old_align =
-                    crate::mem::replace(&mut self.options.align, Some(Alignment::Right));
-                write_prefix(self, sign, prefix)?;
-                let post_padding = self.padding(min - width as u16, Alignment::Right)?;
-                self.buf.write_str(buf)?;
-                post_padding.write(self)?;
-                self.options.fill = old_fill;
-                self.options.align = old_align;
-                Ok(())
-            }
+            let old_options = self.options;
+            self.options.fill('0').align(Some(Alignment::Right));
+            write_prefix(self, sign, prefix)?;
+            let post_padding = self.padding(min - width as u16, Alignment::Right)?;
+            self.buf.write_str(buf)?;
+            post_padding.write(self)?;
+            self.options = old_options;
+            Ok(())
+        } else {
             // Otherwise, the sign and prefix goes after the padding
-            Some(min) => {
-                let post_padding = self.padding(min - width as u16, Alignment::Right)?;
-                write_prefix(self, sign, prefix)?;
-                self.buf.write_str(buf)?;
-                post_padding.write(self)
-            }
+            let post_padding = self.padding(min - width as u16, Alignment::Right)?;
+            write_prefix(self, sign, prefix)?;
+            self.buf.write_str(buf)?;
+            post_padding.write(self)
         }
     }
 
@@ -1698,13 +1741,13 @@ impl<'a> Formatter<'a> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pad(&mut self, s: &str) -> Result {
         // Make sure there's a fast path up front.
-        if self.options.width.is_none() && self.options.precision.is_none() {
+        if self.options.flags & (flags::WIDTH_FLAG | flags::PRECISION_FLAG) == 0 {
             return self.buf.write_str(s);
         }
 
         // The `precision` field can be interpreted as a maximum width for the
         // string being formatted.
-        let (s, char_count) = if let Some(max_char_count) = self.options.precision {
+        let (s, char_count) = if let Some(max_char_count) = self.options.get_precision() {
             let mut iter = s.char_indices();
             let remaining = match iter.advance_by(usize::from(max_char_count)) {
                 Ok(()) => 0,
@@ -1720,12 +1763,11 @@ impl<'a> Formatter<'a> {
         };
 
         // The `width` field is more of a minimum width parameter at this point.
-        if let Some(width) = self.options.width
-            && char_count < usize::from(width)
-        {
+        if char_count < usize::from(self.options.width) {
             // If we're under the minimum width, then fill up the minimum width
             // with the specified string + some alignment.
-            let post_padding = self.padding(width - char_count as u16, Alignment::Left)?;
+            let post_padding =
+                self.padding(self.options.width - char_count as u16, Alignment::Left)?;
             self.buf.write_str(s)?;
             post_padding.write(self)
         } else {
@@ -1744,19 +1786,20 @@ impl<'a> Formatter<'a> {
         padding: u16,
         default: Alignment,
     ) -> result::Result<PostPadding, Error> {
-        let align = self.align().unwrap_or(default);
+        let align = self.options.get_align().unwrap_or(default);
+        let fill = self.options.get_fill();
 
-        let (pre_pad, post_pad) = match align {
-            Alignment::Left => (0, padding),
-            Alignment::Right => (padding, 0),
-            Alignment::Center => (padding / 2, (padding + 1) / 2),
+        let padding_left = match align {
+            Alignment::Left => 0,
+            Alignment::Right => padding,
+            Alignment::Center => padding / 2,
         };
 
-        for _ in 0..pre_pad {
-            self.buf.write_char(self.options.fill)?;
+        for _ in 0..padding_left {
+            self.buf.write_char(fill)?;
         }
 
-        Ok(PostPadding::new(self.options.fill, post_pad))
+        Ok(PostPadding::new(fill, padding - padding_left))
     }
 
     /// Takes the formatted parts and applies the padding.
@@ -1768,12 +1811,16 @@ impl<'a> Formatter<'a> {
     ///
     /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
     unsafe fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
-        if let Some(mut width) = self.options.width {
+        if self.options.width == 0 {
+            // this is the common case and we take a shortcut
+            // SAFETY: Per the precondition.
+            unsafe { self.write_formatted_parts(formatted) }
+        } else {
             // for the sign-aware zero padding, we render the sign first and
             // behave as if we had no sign from the beginning.
             let mut formatted = formatted.clone();
-            let old_fill = self.options.fill;
-            let old_align = self.options.align;
+            let mut width = self.options.width;
+            let old_options = self.options;
             if self.sign_aware_zero_pad() {
                 // a sign always goes first
                 let sign = formatted.sign;
@@ -1782,8 +1829,7 @@ impl<'a> Formatter<'a> {
                 // remove the sign from the formatted parts
                 formatted.sign = "";
                 width = width.saturating_sub(sign.len() as u16);
-                self.options.fill = '0';
-                self.options.align = Some(Alignment::Right);
+                self.options.fill('0').align(Some(Alignment::Right));
             }
 
             // remaining parts go through the ordinary padding process.
@@ -1800,13 +1846,8 @@ impl<'a> Formatter<'a> {
                 }
                 post_padding.write(self)
             };
-            self.options.fill = old_fill;
-            self.options.align = old_align;
+            self.options = old_options;
             ret
-        } else {
-            // this is the common case and we take a shortcut
-            // SAFETY: Per the precondition.
-            unsafe { self.write_formatted_parts(formatted) }
         }
     }
 
@@ -1927,7 +1968,9 @@ impl<'a> Formatter<'a> {
                 or `sign_aware_zero_pad` methods instead"
     )]
     pub fn flags(&self) -> u32 {
-        self.options.flags
+        // Extract the debug upper/lower hex, zero pad, alternate, and plus/minus flags
+        // to stay compatible with older versions of Rust.
+        self.options.flags >> 21 & 0x3F
     }
 
     /// Returns the character used as 'fill' whenever there is alignment.
@@ -1960,7 +2003,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn fill(&self) -> char {
-        self.options.fill
+        self.options.get_fill()
     }
 
     /// Returns a flag indicating what form of alignment was requested.
@@ -1995,7 +2038,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags_align", since = "1.28.0")]
     pub fn align(&self) -> Option<Alignment> {
-        self.options.align
+        self.options.get_align()
     }
 
     /// Returns the optionally specified integer width that the output should be.
@@ -2025,7 +2068,11 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn width(&self) -> Option<usize> {
-        self.options.width.map(|x| x as usize)
+        if self.options.flags & flags::WIDTH_FLAG == 0 {
+            None
+        } else {
+            Some(self.options.width as usize)
+        }
     }
 
     /// Returns the optionally specified precision for numeric types.
@@ -2056,7 +2103,11 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn precision(&self) -> Option<usize> {
-        self.options.precision.map(|x| x as usize)
+        if self.options.flags & flags::PRECISION_FLAG == 0 {
+            None
+        } else {
+            Some(self.options.precision as usize)
+        }
     }
 
     /// Determines if the `+` flag was specified.
@@ -2088,7 +2139,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_plus(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::SignPlus as u32) != 0
+        self.options.flags & flags::SIGN_PLUS_FLAG != 0
     }
 
     /// Determines if the `-` flag was specified.
@@ -2117,7 +2168,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_minus(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::SignMinus as u32) != 0
+        self.options.flags & flags::SIGN_MINUS_FLAG != 0
     }
 
     /// Determines if the `#` flag was specified.
@@ -2145,7 +2196,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn alternate(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::Alternate as u32) != 0
+        self.options.flags & flags::ALTERNATE_FLAG != 0
     }
 
     /// Determines if the `0` flag was specified.
@@ -2171,17 +2222,16 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_aware_zero_pad(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0
+        self.options.flags & flags::SIGN_AWARE_ZERO_PAD_FLAG != 0
     }
 
     // FIXME: Decide what public API we want for these two flags.
     // https://github.com/rust-lang/rust/issues/48584
     fn debug_lower_hex(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0
+        self.options.flags & flags::DEBUG_LOWER_HEX_FLAG != 0
     }
-
     fn debug_upper_hex(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0
+        self.options.flags & flags::DEBUG_UPPER_HEX_FLAG != 0
     }
 
     /// Creates a [`DebugStruct`] builder designed to assist with creation of
@@ -2761,7 +2811,7 @@ impl Debug for char {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Display for char {
     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
-        if f.options.width.is_none() && f.options.precision.is_none() {
+        if f.options.flags & (flags::WIDTH_FLAG | flags::PRECISION_FLAG) == 0 {
             f.write_char(*self)
         } else {
             f.pad(self.encode_utf8(&mut [0; MAX_LEN_UTF8]))
@@ -2792,26 +2842,24 @@ impl<T: ?Sized> Pointer for *const T {
 ///
 /// [problematic]: https://github.com/rust-lang/rust/issues/95489
 pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Result {
-    let old_width = f.options.width;
-    let old_flags = f.options.flags;
+    let old_options = f.options;
 
     // The alternate flag is already treated by LowerHex as being special-
     // it denotes whether to prefix with 0x. We use it to work out whether
     // or not to zero extend, and then unconditionally set it to get the
     // prefix.
-    if f.alternate() {
-        f.options.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32);
+    if f.options.get_alternate() {
+        f.options.sign_aware_zero_pad(true);
 
-        if f.options.width.is_none() {
-            f.options.width = Some((usize::BITS / 4) as u16 + 2);
+        if f.options.get_width().is_none() {
+            f.options.width(Some((usize::BITS / 4) as u16 + 2));
         }
     }
-    f.options.flags |= 1 << (rt::Flag::Alternate as u32);
+    f.options.alternate(true);
 
     let ret = LowerHex::fmt(&ptr_addr, f);
 
-    f.options.width = old_width;
-    f.options.flags = old_flags;
+    f.options = old_options;
 
     ret
 }
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index 080fc6ddfc9..0b04ebccae2 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -11,13 +11,16 @@ use crate::ptr::NonNull;
 #[derive(Copy, Clone)]
 pub struct Placeholder {
     pub position: usize,
+    #[cfg(bootstrap)]
     pub fill: char,
+    #[cfg(bootstrap)]
     pub align: Alignment,
     pub flags: u32,
     pub precision: Count,
     pub width: Count,
 }
 
+#[cfg(bootstrap)]
 impl Placeholder {
     #[inline]
     pub const fn new(
@@ -32,6 +35,7 @@ impl Placeholder {
     }
 }
 
+#[cfg(bootstrap)]
 #[lang = "format_alignment"]
 #[derive(Copy, Clone, PartialEq, Eq)]
 pub enum Alignment {
@@ -58,17 +62,6 @@ pub enum Count {
     Implied,
 }
 
-// This needs to match the order of flags in compiler/rustc_ast_lowering/src/format.rs.
-#[derive(Copy, Clone)]
-pub(super) enum Flag {
-    SignPlus,
-    SignMinus,
-    Alternate,
-    SignAwareZeroPad,
-    DebugLowerHex,
-    DebugUpperHex,
-}
-
 #[derive(Copy, Clone)]
 enum ArgumentType<'a> {
     Placeholder {
diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs
index fe4fa80263c..2aaefba2468 100644
--- a/library/core/src/internal_macros.rs
+++ b/library/core/src/internal_macros.rs
@@ -120,80 +120,3 @@ macro_rules! impl_fn_for_zst {
         )+
     }
 }
-
-/// A macro for defining `#[cfg]` if-else statements.
-///
-/// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade
-/// of `#[cfg]` cases, emitting the implementation which matches first.
-///
-/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code without having to
-/// rewrite each clause multiple times.
-///
-/// # Example
-///
-/// ```ignore(cannot-test-this-because-non-exported-macro)
-/// cfg_if! {
-///     if #[cfg(unix)] {
-///         fn foo() { /* unix specific functionality */ }
-///     } else if #[cfg(target_pointer_width = "32")] {
-///         fn foo() { /* non-unix, 32-bit functionality */ }
-///     } else {
-///         fn foo() { /* fallback implementation */ }
-///     }
-/// }
-///
-/// # fn main() {}
-/// ```
-// This is a copy of `cfg_if!` from the `cfg_if` crate.
-// The recursive invocations should use $crate if this is ever exported.
-macro_rules! cfg_if {
-    // match if/else chains with a final `else`
-    (
-        $(
-            if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
-        ) else+
-        else { $( $e_tokens:tt )* }
-    ) => {
-        cfg_if! {
-            @__items () ;
-            $(
-                (( $i_meta ) ( $( $i_tokens )* )) ,
-            )+
-            (() ( $( $e_tokens )* )) ,
-        }
-    };
-
-    // Internal and recursive macro to emit all the items
-    //
-    // Collects all the previous cfgs in a list at the beginning, so they can be
-    // negated. After the semicolon is all the remaining items.
-    (@__items ( $( $_:meta , )* ) ; ) => {};
-    (
-        @__items ( $( $no:meta , )* ) ;
-        (( $( $yes:meta )? ) ( $( $tokens:tt )* )) ,
-        $( $rest:tt , )*
-    ) => {
-        // Emit all items within one block, applying an appropriate #[cfg]. The
-        // #[cfg] will require all `$yes` matchers specified and must also negate
-        // all previous matchers.
-        #[cfg(all(
-            $( $yes , )?
-            not(any( $( $no ),* ))
-        ))]
-        cfg_if! { @__identity $( $tokens )* }
-
-        // Recurse to emit all other items in `$rest`, and when we do so add all
-        // our `$yes` matchers to the list of `$no` matchers as future emissions
-        // will have to negate everything we just matched as well.
-        cfg_if! {
-            @__items ( $( $no , )* $( $yes , )? ) ;
-            $( $rest , )*
-        }
-    };
-
-    // Internal macro to make __apply work out right for different match types,
-    // because of how macros match/expand stuff.
-    (@__identity $( $tokens:tt )* ) => {
-        $( $tokens )*
-    };
-}
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index cf03c07b6a5..81e59a1f349 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -3002,6 +3002,7 @@ pub const fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discrimina
 
 /// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the
 /// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs.
+/// Returns `1` if unwinding occurred and `catch_fn` was called; returns `0` otherwise.
 ///
 /// `catch_fn` must not unwind.
 ///
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 9b9353b800a..a820045521b 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -172,61 +172,6 @@ where
     }
 }
 
-/// Marker trait for iterators/iterables which have a statically known upper
-/// bound of the number of items they can produce.
-///
-/// # Safety
-///
-/// Implementations must not yield more elements than indicated by UPPER_BOUND if it is `Some`.
-/// Used in specializations.  Implementations must not be conditional on lifetimes or
-/// user-implementable traits.
-#[rustc_specialization_trait]
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe trait BoundedSize {
-    const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(1);
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for Option<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for option::IntoIter<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T, U> BoundedSize for Result<T, U> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for result::IntoIter<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for Once<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for OnceWith<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T, const N: usize> BoundedSize for [T; N] {
-    const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(N);
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T, const N: usize> BoundedSize for array::IntoIter<T, N> {
-    const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(N);
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize, P> BoundedSize for Filter<I, P> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize, P> BoundedSize for FilterMap<I, P> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize, F> BoundedSize for Map<I, F> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize> BoundedSize for Copied<I> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize> BoundedSize for Cloned<I> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-
 /// An iterator that flattens one level of nesting in an iterator of things
 /// that can be turned into iterators.
 ///
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index cc089c617c0..ada37b9af4c 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -1,7 +1,8 @@
 use crate::fmt;
 use crate::iter::{FusedIterator, TrustedLen, UncheckedIterator};
-use crate::mem::{self, MaybeUninit};
+use crate::mem::MaybeUninit;
 use crate::num::NonZero;
+use crate::ops::{NeverShortCircuit, Try};
 
 /// Creates a new iterator that repeats a single element a given number of times.
 ///
@@ -95,10 +96,10 @@ impl<A> RepeatN<A> {
     fn take_element(&mut self) -> Option<A> {
         if self.count > 0 {
             self.count = 0;
-            let element = mem::replace(&mut self.element, MaybeUninit::uninit());
             // SAFETY: We just set count to zero so it won't be dropped again,
             // and it used to be non-zero so it hasn't already been dropped.
-            unsafe { Some(element.assume_init()) }
+            let element = unsafe { self.element.assume_init_read() };
+            Some(element)
         } else {
             None
         }
@@ -169,6 +170,39 @@ impl<A: Clone> Iterator for RepeatN<A> {
         }
     }
 
+    fn try_fold<B, F, R>(&mut self, mut acc: B, mut f: F) -> R
+    where
+        F: FnMut(B, A) -> R,
+        R: Try<Output = B>,
+    {
+        if self.count > 0 {
+            while self.count > 1 {
+                self.count -= 1;
+                // SAFETY: the count was larger than 1, so the element is
+                // initialized and hasn't been dropped.
+                acc = f(acc, unsafe { self.element.assume_init_ref().clone() })?;
+            }
+
+            // We could just set the count to zero directly, but doing it this
+            // way should make it easier for the optimizer to fold this tail
+            // into the loop when `clone()` is equivalent to copying.
+            self.count -= 1;
+            // SAFETY: we just set the count to zero from one, so the element
+            // is still initialized, has not been dropped yet and will not be
+            // accessed by future calls.
+            f(acc, unsafe { self.element.assume_init_read() })
+        } else {
+            try { acc }
+        }
+    }
+
+    fn fold<B, F>(mut self, init: B, f: F) -> B
+    where
+        F: FnMut(B, A) -> B,
+    {
+        self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
+    }
+
     #[inline]
     fn last(mut self) -> Option<A> {
         self.take_element()
@@ -203,6 +237,23 @@ impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
     fn nth_back(&mut self, n: usize) -> Option<A> {
         self.nth(n)
     }
+
+    #[inline]
+    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
+    where
+        F: FnMut(B, A) -> R,
+        R: Try<Output = B>,
+    {
+        self.try_fold(init, f)
+    }
+
+    #[inline]
+    fn rfold<B, F>(self, init: B, f: F) -> B
+    where
+        F: FnMut(B, A) -> B,
+    {
+        self.fold(init, f)
+    }
 }
 
 #[stable(feature = "iter_repeat_n", since = "1.82.0")]
@@ -220,7 +271,7 @@ impl<A: Clone> UncheckedIterator for RepeatN<A> {
             // SAFETY: the check above ensured that the count used to be non-zero,
             // so element hasn't been dropped yet, and we just lowered the count to
             // zero so it won't be dropped later, and thus it's okay to take it here.
-            unsafe { mem::replace(&mut self.element, MaybeUninit::uninit()).assume_init() }
+            unsafe { self.element.assume_init_read() }
         } else {
             // SAFETY: the count is non-zero, so it must have not been dropped yet.
             let element = unsafe { self.element.assume_init_ref() };
diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs
index 5b7d95c2f65..12e2b8b393a 100644
--- a/library/core/src/iter/traits/accum.rs
+++ b/library/core/src/iter/traits/accum.rs
@@ -10,7 +10,7 @@ use crate::num::Wrapping;
 /// [`sum()`]: Iterator::sum
 /// [`FromIterator`]: iter::FromIterator
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
-#[rustc_on_unimplemented(
+#[diagnostic::on_unimplemented(
     message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
     label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
 )]
@@ -31,7 +31,7 @@ pub trait Sum<A = Self>: Sized {
 /// [`product()`]: Iterator::product
 /// [`FromIterator`]: iter::FromIterator
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
-#[rustc_on_unimplemented(
+#[diagnostic::on_unimplemented(
     message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
     label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
 )]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index e1ca69edcbb..dc06aa4c38d 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -100,6 +100,7 @@
 #![feature(bigint_helper_methods)]
 #![feature(bstr)]
 #![feature(bstr_internals)]
+#![feature(cfg_match)]
 #![feature(closure_track_caller)]
 #![feature(const_carrying_mul_add)]
 #![feature(const_eval_select)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index fa0d882181a..5f200b31d1a 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1744,7 +1744,7 @@ pub(crate) mod builtin {
     }
 
     /// Provide a list of type aliases and other opaque-type-containing type definitions.
-    /// This list will be used in the body of the item it is applied to to define opaque
+    /// This list will be used in the body of the item it is applied to define opaque
     /// types' hidden types.
     /// Can only be applied to things that have bodies.
     #[unstable(
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index 7aa5ed60d04..2f027be6928 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -1623,6 +1623,8 @@ impl Ipv6Addr {
             // IANA says N/A.
             || matches!(self.segments(), [0x2002, _, _, _, _, _, _, _])
             || self.is_documentation()
+            // Segment Routing (SRv6) SIDs (`5f00::/16`)
+            || matches!(self.segments(), [0x5f00, ..])
             || self.is_unique_local()
             || self.is_unicast_link_local())
     }
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 79d864e1b19..53373584d55 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -14,7 +14,7 @@
 use crate::convert::FloatToInt;
 use crate::num::FpCategory;
 use crate::panic::const_assert;
-use crate::{intrinsics, mem};
+use crate::{cfg_match, intrinsics, mem};
 
 /// The radix or base of the internal representation of `f32`.
 /// Use [`f32::RADIX`] instead.
@@ -996,21 +996,22 @@ impl f32 {
     #[stable(feature = "num_midpoint", since = "1.85.0")]
     #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
     pub const fn midpoint(self, other: f32) -> f32 {
-        cfg_if! {
+        cfg_match! {
             // Allow faster implementation that have known good 64-bit float
             // implementations. Falling back to the branchy code on targets that don't
             // have 64-bit hardware floats or buggy implementations.
             // https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114
-            if #[cfg(any(
-                    target_arch = "x86_64",
-                    target_arch = "aarch64",
-                    all(any(target_arch = "riscv32", target_arch = "riscv64"), target_feature = "d"),
-                    all(target_arch = "arm", target_feature = "vfp2"),
-                    target_arch = "wasm32",
-                    target_arch = "wasm64",
-                ))] {
+            any(
+                target_arch = "x86_64",
+                target_arch = "aarch64",
+                all(any(target_arch = "riscv32", target_arch = "riscv64"), target_feature = "d"),
+                all(target_arch = "arm", target_feature = "vfp2"),
+                target_arch = "wasm32",
+                target_arch = "wasm64",
+            ) => {
                 ((self as f64 + other as f64) / 2.0) as f32
-            } else {
+            }
+            _ => {
                 const LO: f32 = f32::MIN_POSITIVE * 2.;
                 const HI: f32 = f32::MAX / 2.;
 
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 7fcd19f67ee..bc097bf198d 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1943,6 +1943,7 @@ unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {}
 #[stable(feature = "pin_macro", since = "1.68.0")]
 #[rustc_macro_transparency = "semitransparent"]
 #[allow_internal_unstable(unsafe_pin_internals)]
+#[cfg_attr(not(bootstrap), rustc_macro_edition_2021)]
 pub macro pin($value:expr $(,)?) {
     // This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's
     // review such a hypothetical macro (that any user-code could define):
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 89c856fe107..ba4c849837e 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -127,15 +127,13 @@ mod prim_bool {}
 /// [`Result<String, !>`] which we can unpack like this:
 ///
 /// ```
-/// #![feature(exhaustive_patterns)]
 /// use std::str::FromStr;
 /// let Ok(s) = String::from_str("hello");
 /// ```
 ///
-/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns`
-/// feature is present this means we can exhaustively match on [`Result<T, !>`] by just taking the
-/// [`Ok`] variant. This illustrates another behavior of `!` - it can be used to "delete" certain
-/// enum variants from generic types like `Result`.
+/// Since the [`Err`] variant contains a `!`, it can never occur. This means we can exhaustively
+/// match on [`Result<T, !>`] by just taking the [`Ok`] variant. This illustrates another behavior
+/// of `!` - it can be used to "delete" certain enum variants from generic types like `Result`.
 ///
 /// ## Infinite loops
 ///
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 7d0839aff3f..71a84aff246 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -386,7 +386,8 @@ impl<T: ?Sized> *const T {
     /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
     ///   [allocated object], and the entire memory range between `self` and the result must be in
     ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
-    ///   of the address space.
+    ///   of the address space. Note that "range" here refers to a half-open range as usual in Rust,
+    ///   i.e., `self..result` for non-negative offsets and `result..self` for negative offsets.
     ///
     /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
     /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
diff --git a/library/core/src/slice/sort/select.rs b/library/core/src/slice/sort/select.rs
index 3358c03d30a..c4808b1065d 100644
--- a/library/core/src/slice/sort/select.rs
+++ b/library/core/src/slice/sort/select.rs
@@ -6,6 +6,7 @@
 //! for pivot selection. Using this as a fallback ensures O(n) worst case running time with
 //! better performance than one would get using heapsort as fallback.
 
+use crate::cfg_match;
 use crate::mem::{self, SizedTypeProperties};
 #[cfg(not(feature = "optimize_for_size"))]
 use crate::slice::sort::shared::pivot::choose_pivot;
@@ -41,10 +42,11 @@ where
         let min_idx = min_index(v, &mut is_less).unwrap();
         v.swap(min_idx, index);
     } else {
-        cfg_if! {
-            if #[cfg(feature = "optimize_for_size")] {
+        cfg_match! {
+            feature = "optimize_for_size" => {
                 median_of_medians(v, &mut is_less, index);
-            } else {
+            }
+            _ => {
                 partition_at_index_loop(v, index, None, &mut is_less);
             }
         }
diff --git a/library/core/src/slice/sort/stable/mod.rs b/library/core/src/slice/sort/stable/mod.rs
index 090367cdaba..a36e5f7801d 100644
--- a/library/core/src/slice/sort/stable/mod.rs
+++ b/library/core/src/slice/sort/stable/mod.rs
@@ -2,12 +2,12 @@
 
 #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
 use crate::cmp;
-use crate::intrinsics;
 use crate::mem::{MaybeUninit, SizedTypeProperties};
 #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
 use crate::slice::sort::shared::smallsort::{
     SMALL_SORT_GENERAL_SCRATCH_LEN, StableSmallSortTypeImpl, insertion_sort_shift_left,
 };
+use crate::{cfg_match, intrinsics};
 
 pub(crate) mod merge;
 
@@ -39,17 +39,18 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool, BufT: BufGuard<T>>(v: &mut [T], is_less
         return;
     }
 
-    cfg_if! {
-        if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] {
+    cfg_match! {
+        any(feature = "optimize_for_size", target_pointer_width = "16") => {
             // Unlike driftsort, mergesort only requires len / 2,
             // not len - len / 2.
             let alloc_len = len / 2;
 
-            cfg_if! {
-                if #[cfg(target_pointer_width = "16")] {
+            cfg_match! {
+                target_pointer_width = "16" => {
                     let mut heap_buf = BufT::with_capacity(alloc_len);
                     let scratch = heap_buf.as_uninit_slice_mut();
-                } else {
+                }
+                _ => {
                     // For small inputs 4KiB of stack storage suffices, which allows us to avoid
                     // calling the (de-)allocator. Benchmarks showed this was quite beneficial.
                     let mut stack_buf = AlignedStorage::<T, 4096>::new();
@@ -65,7 +66,8 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool, BufT: BufGuard<T>>(v: &mut [T], is_less
             }
 
             tiny::mergesort(v, scratch, is_less);
-        } else {
+        }
+        _ => {
             // More advanced sorting methods than insertion sort are faster if called in
             // a hot loop for small inputs, but for general-purpose code the small
             // binary size of insertion sort is more important. The instruction cache in
diff --git a/library/core/src/slice/sort/unstable/mod.rs b/library/core/src/slice/sort/unstable/mod.rs
index 2eb653c4601..b6c2e05a06a 100644
--- a/library/core/src/slice/sort/unstable/mod.rs
+++ b/library/core/src/slice/sort/unstable/mod.rs
@@ -1,11 +1,11 @@
 //! This module contains the entry points for `slice::sort_unstable`.
 
-use crate::intrinsics;
 use crate::mem::SizedTypeProperties;
 #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
 use crate::slice::sort::shared::find_existing_run;
 #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
 use crate::slice::sort::shared::smallsort::insertion_sort_shift_left;
+use crate::{cfg_match, intrinsics};
 
 pub(crate) mod heapsort;
 pub(crate) mod quicksort;
@@ -30,10 +30,11 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], is_less: &mut F) {
         return;
     }
 
-    cfg_if! {
-        if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] {
+    cfg_match! {
+        any(feature = "optimize_for_size", target_pointer_width = "16") => {
             heapsort::heapsort(v, is_less);
-        } else {
+        }
+        _ => {
             // More advanced sorting methods than insertion sort are faster if called in
             // a hot loop for small inputs, but for general-purpose code the small
             // binary size of insertion sort is more important. The instruction cache in
diff --git a/library/core/src/slice/sort/unstable/quicksort.rs b/library/core/src/slice/sort/unstable/quicksort.rs
index 68a16118716..7e6cfb55990 100644
--- a/library/core/src/slice/sort/unstable/quicksort.rs
+++ b/library/core/src/slice/sort/unstable/quicksort.rs
@@ -9,7 +9,7 @@ use crate::slice::sort::shared::pivot::choose_pivot;
 use crate::slice::sort::shared::smallsort::UnstableSmallSortTypeImpl;
 #[cfg(not(feature = "optimize_for_size"))]
 use crate::slice::sort::unstable::heapsort;
-use crate::{intrinsics, ptr};
+use crate::{cfg_match, intrinsics, ptr};
 
 /// Sorts `v` recursively.
 ///
@@ -142,10 +142,11 @@ const fn inst_partition<T, F: FnMut(&T, &T) -> bool>() -> fn(&mut [T], &T, &mut
     if size_of::<T>() <= MAX_BRANCHLESS_PARTITION_SIZE {
         // Specialize for types that are relatively cheap to copy, where branchless optimizations
         // have large leverage e.g. `u64` and `String`.
-        cfg_if! {
-            if #[cfg(feature = "optimize_for_size")] {
+        cfg_match! {
+            feature = "optimize_for_size" => {
                 partition_lomuto_branchless_simple::<T, F>
-            } else {
+            }
+            _ => {
                 partition_lomuto_branchless_cyclic::<T, F>
             }
         }
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 88bee622031..9b1b13e7129 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -469,6 +469,7 @@ impl AtomicBool {
     ///
     /// [valid]: crate::ptr#safety
     /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+    #[inline]
     #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
     pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool {
@@ -1389,6 +1390,7 @@ impl<T> AtomicPtr<T> {
     ///
     /// [valid]: crate::ptr#safety
     /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+    #[inline]
     #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
     pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> {
@@ -2525,6 +2527,7 @@ macro_rules! atomic_int {
             ///
             /// [valid]: crate::ptr#safety
             /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+            #[inline]
             #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
             #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
             pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type {
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index 206b5b9e2c2..d754bb90343 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -2,6 +2,7 @@
 
 use crate::cmp::Ordering::{self, *};
 use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy};
+use crate::ops::ControlFlow::{Break, Continue};
 
 // Recursive macro for implementing n-ary tuple functions and operations
 //
@@ -80,19 +81,19 @@ macro_rules! tuple_impls {
                 }
                 #[inline]
                 fn lt(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(lt, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+                    lexical_ord!(lt, __chaining_lt, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
                 }
                 #[inline]
                 fn le(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(le, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+                    lexical_ord!(le, __chaining_le, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
                 }
                 #[inline]
                 fn ge(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(ge, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+                    lexical_ord!(ge, __chaining_ge, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
                 }
                 #[inline]
                 fn gt(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(gt, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+                    lexical_ord!(gt, __chaining_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
                 }
             }
         }
@@ -171,15 +172,16 @@ macro_rules! maybe_tuple_doc {
 // `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, opt_is_lt, a1, b1,
 // a2, b2, a3, b3)` (and similarly for `lexical_cmp`)
 //
-// `$ne_rel` is only used to determine the result after checking that they're
-// not equal, so `lt` and `le` can both just use `Less`.
+// `$chain_rel` is the chaining method from `PartialOrd` to use for all but the
+// final value, to produce better results for simple primitives.
 macro_rules! lexical_ord {
-    ($rel: ident, $ne_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{
-        let c = PartialOrd::partial_cmp(&$a, &$b);
-        if c != Some(Equal) { c == Some($ne_rel) }
-        else { lexical_ord!($rel, $ne_rel, $($rest_a, $rest_b),+) }
+    ($rel: ident, $chain_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{
+        match PartialOrd::$chain_rel(&$a, &$b) {
+            Break(val) => val,
+            Continue(()) => lexical_ord!($rel, $chain_rel, $($rest_a, $rest_b),+),
+        }
     }};
-    ($rel: ident, $ne_rel: ident, $a:expr, $b:expr) => {
+    ($rel: ident, $chain_rel: ident, $a:expr, $b:expr) => {
         // Use the specific method for the last element
         PartialOrd::$rel(&$a, &$b)
     };