diff options
Diffstat (limited to 'library/core/src')
51 files changed, 886 insertions, 688 deletions
| diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 38393379a78..ceb9748e7fe 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -725,7 +725,7 @@ unsafe impl Send for TypeId {} unsafe impl Sync for TypeId {} #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_type_id", issue = "77125")] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl const PartialEq for TypeId { #[inline] fn eq(&self, other: &Self) -> bool { @@ -773,7 +773,7 @@ impl TypeId { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_type_id", issue = "77125")] + #[rustc_const_stable(feature = "const_type_id", since = "CURRENT_RUSTC_VERSION")] pub const fn of<T: ?Sized + 'static>() -> TypeId { const { intrinsics::type_id::<T>() } } diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index bb668d2a673..1ad2cca64a3 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -22,18 +22,16 @@ where { #[inline] fn eq(&self, other: &[U]) -> bool { - let b: Result<&[U; N], _> = other.try_into(); - match b { - Ok(b) => *self == *b, - Err(_) => false, + match other.as_array::<N>() { + Some(b) => *self == *b, + None => false, } } #[inline] fn ne(&self, other: &[U]) -> bool { - let b: Result<&[U; N], _> = other.try_into(); - match b { - Ok(b) => *self != *b, - Err(_) => true, + match other.as_array::<N>() { + Some(b) => *self != *b, + None => true, } } } @@ -45,18 +43,16 @@ where { #[inline] fn eq(&self, other: &[U; N]) -> bool { - let b: Result<&[T; N], _> = self.try_into(); - match b { - Ok(b) => *b == *other, - Err(_) => false, + match self.as_array::<N>() { + Some(b) => *b == *other, + None => false, } } #[inline] fn ne(&self, other: &[U; N]) -> bool { - let b: Result<&[T; N], _> = self.try_into(); - match b { - Ok(b) => *b != *other, - Err(_) => true, + match self.as_array::<N>() { + Some(b) => *b != *other, + None => true, } } } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 1c23218552a..b3a498570f9 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -378,7 +378,7 @@ impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] { #[rustc_const_unstable(feature = "const_index", issue = "143775")] impl<T, I, const N: usize> const Index<I> for [T; N] where - [T]: ~const Index<I>, + [T]: [const] Index<I>, { type Output = <[T] as Index<I>>::Output; @@ -392,7 +392,7 @@ where #[rustc_const_unstable(feature = "const_index", issue = "143775")] impl<T, I, const N: usize> const IndexMut<I> for [T; N] where - [T]: ~const IndexMut<I>, + [T]: [const] IndexMut<I>, { #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index d6d1bf2effa..c639d50cc3d 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -334,7 +334,7 @@ impl<T: Copy> Clone for Cell<T> { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_default", issue = "143894")] -impl<T: ~const Default> const Default for Cell<T> { +impl<T: [const] Default> const Default for Cell<T> { /// Creates a `Cell<T>`, with the `Default` value for T. #[inline] fn default() -> Cell<T> { @@ -1325,7 +1325,7 @@ impl<T: Clone> Clone for RefCell<T> { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_default", issue = "143894")] -impl<T: ~const Default> const Default for RefCell<T> { +impl<T: [const] Default> const Default for RefCell<T> { /// Creates a `RefCell<T>`, with the `Default` value for T. #[inline] fn default() -> RefCell<T> { @@ -2068,9 +2068,9 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> { /// implies exclusive access to its `T`: /// /// ```rust -/// #![forbid(unsafe_code)] // with exclusive accesses, -/// // `UnsafeCell` is a transparent no-op wrapper, -/// // so no need for `unsafe` here. +/// #![forbid(unsafe_code)] +/// // with exclusive accesses, `UnsafeCell` is a transparent no-op wrapper, so no need for +/// // `unsafe` here. /// use std::cell::UnsafeCell; /// /// let mut x: UnsafeCell<i32> = 42.into(); @@ -2333,7 +2333,7 @@ impl<T: ?Sized> UnsafeCell<T> { #[stable(feature = "unsafe_cell_default", since = "1.10.0")] #[rustc_const_unstable(feature = "const_default", issue = "143894")] -impl<T: ~const Default> const Default for UnsafeCell<T> { +impl<T: [const] Default> const Default for UnsafeCell<T> { /// Creates an `UnsafeCell`, with the `Default` value for T. fn default() -> UnsafeCell<T> { UnsafeCell::new(Default::default()) @@ -2438,7 +2438,7 @@ impl<T: ?Sized> SyncUnsafeCell<T> { #[unstable(feature = "sync_unsafe_cell", issue = "95439")] #[rustc_const_unstable(feature = "const_default", issue = "143894")] -impl<T: ~const Default> const Default for SyncUnsafeCell<T> { +impl<T: [const] Default> const Default for SyncUnsafeCell<T> { /// Creates an `SyncUnsafeCell`, with the `Default` value for T. fn default() -> SyncUnsafeCell<T> { SyncUnsafeCell::new(Default::default()) diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs index 1758e84ad7c..a1bd4c85717 100644 --- a/library/core/src/cell/lazy.rs +++ b/library/core/src/cell/lazy.rs @@ -15,6 +15,22 @@ enum State<T, F> { /// /// [`std::sync::LazyLock`]: ../../std/sync/struct.LazyLock.html /// +/// # Poisoning +/// +/// If the initialization closure passed to [`LazyCell::new`] panics, the cell will be poisoned. +/// Once the cell is poisoned, any threads that attempt to access this cell (via a dereference +/// or via an explicit call to [`force()`]) will panic. +/// +/// This concept is similar to that of poisoning in the [`std::sync::poison`] module. A key +/// difference, however, is that poisoning in `LazyCell` is _unrecoverable_. All future accesses of +/// the cell from other threads will panic, whereas a type in [`std::sync::poison`] like +/// [`std::sync::poison::Mutex`] allows recovery via [`PoisonError::into_inner()`]. +/// +/// [`force()`]: LazyCell::force +/// [`std::sync::poison`]: ../../std/sync/poison/index.html +/// [`std::sync::poison::Mutex`]: ../../std/sync/poison/struct.Mutex.html +/// [`PoisonError::into_inner()`]: ../../std/sync/poison/struct.PoisonError.html#method.into_inner +/// /// # Examples /// /// ``` @@ -64,6 +80,10 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. /// + /// # Panics + /// + /// Panics if the cell is poisoned. + /// /// # Examples /// /// ``` @@ -93,6 +113,15 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// /// This is equivalent to the `Deref` impl, but is explicit. /// + /// # Panics + /// + /// If the initialization closure panics (the one that is passed to the [`new()`] method), the + /// panic is propagated to the caller, and the cell becomes poisoned. This will cause all future + /// accesses of the cell (via [`force()`] or a dereference) to panic. + /// + /// [`new()`]: LazyCell::new + /// [`force()`]: LazyCell::force + /// /// # Examples /// /// ``` @@ -123,6 +152,15 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// Forces the evaluation of this lazy value and returns a mutable reference to /// the result. /// + /// # Panics + /// + /// If the initialization closure panics (the one that is passed to the [`new()`] method), the + /// panic is propagated to the caller, and the cell becomes poisoned. This will cause all future + /// accesses of the cell (via [`force()`] or a dereference) to panic. + /// + /// [`new()`]: LazyCell::new + /// [`force()`]: LazyCell::force + /// /// # Examples /// /// ``` @@ -219,7 +257,8 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { } impl<T, F> LazyCell<T, F> { - /// Returns a mutable reference to the value if initialized, or `None` if not. + /// Returns a mutable reference to the value if initialized. Otherwise (if uninitialized or + /// poisoned), returns `None`. /// /// # Examples /// @@ -245,7 +284,8 @@ impl<T, F> LazyCell<T, F> { } } - /// Returns a reference to the value if initialized, or `None` if not. + /// Returns a reference to the value if initialized. Otherwise (if uninitialized or poisoned), + /// returns `None`. /// /// # Examples /// @@ -278,6 +318,15 @@ impl<T, F> LazyCell<T, F> { #[stable(feature = "lazy_cell", since = "1.80.0")] impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> { type Target = T; + + /// # Panics + /// + /// If the initialization closure panics (the one that is passed to the [`new()`] method), the + /// panic is propagated to the caller, and the cell becomes poisoned. This will cause all future + /// accesses of the cell (via [`force()`] or a dereference) to panic. + /// + /// [`new()`]: LazyCell::new + /// [`force()`]: LazyCell::force #[inline] fn deref(&self) -> &T { LazyCell::force(self) @@ -286,6 +335,14 @@ impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> { #[stable(feature = "lazy_deref_mut", since = "1.89.0")] impl<T, F: FnOnce() -> T> DerefMut for LazyCell<T, F> { + /// # Panics + /// + /// If the initialization closure panics (the one that is passed to the [`new()`] method), the + /// panic is propagated to the caller, and the cell becomes poisoned. This will cause all future + /// accesses of the cell (via [`force()`] or a dereference) to panic. + /// + /// [`new()`]: LazyCell::new + /// [`force()`]: LazyCell::force #[inline] fn deref_mut(&mut self) -> &mut T { LazyCell::force_mut(self) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index b0752a85faf..7ee0962721f 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -920,7 +920,11 @@ impl char { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_alphanumeric(self) -> bool { - self.is_alphabetic() || self.is_numeric() + if self.is_ascii() { + self.is_ascii_alphanumeric() + } else { + unicode::Alphabetic(self) || unicode::N(self) + } } /// Returns `true` if this `char` has the general category for control codes. diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 51d037ddfd2..e315c4fac08 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -212,7 +212,7 @@ pub trait Clone: Sized { #[stable(feature = "rust1", since = "1.0.0")] fn clone_from(&mut self, source: &Self) where - Self: ~const Destruct, + Self: [const] Destruct, { *self = source.clone() } diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 1b9af10a6fd..a64fade285b 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -2022,7 +2022,7 @@ mod impls { #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl<A: PointeeSized, B: PointeeSized> const PartialEq<&B> for &A where - A: ~const PartialEq<B>, + A: [const] PartialEq<B>, { #[inline] fn eq(&self, other: &&B) -> bool { @@ -2094,7 +2094,7 @@ mod impls { #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl<A: PointeeSized, B: PointeeSized> const PartialEq<&mut B> for &mut A where - A: ~const PartialEq<B>, + A: [const] PartialEq<B>, { #[inline] fn eq(&self, other: &&mut B) -> bool { @@ -2164,7 +2164,7 @@ mod impls { #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl<A: PointeeSized, B: PointeeSized> const PartialEq<&mut B> for &A where - A: ~const PartialEq<B>, + A: [const] PartialEq<B>, { #[inline] fn eq(&self, other: &&mut B) -> bool { @@ -2180,7 +2180,7 @@ mod impls { #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl<A: PointeeSized, B: PointeeSized> const PartialEq<&B> for &mut A where - A: ~const PartialEq<B>, + A: [const] PartialEq<B>, { #[inline] fn eq(&self, other: &&B) -> bool { diff --git a/library/core/src/cmp/bytewise.rs b/library/core/src/cmp/bytewise.rs index 7d61c9345ec..a06a6e8b69a 100644 --- a/library/core/src/cmp/bytewise.rs +++ b/library/core/src/cmp/bytewise.rs @@ -19,7 +19,7 @@ use crate::num::NonZero; #[rustc_specialization_trait] #[const_trait] pub(crate) unsafe trait BytewiseEq<Rhs = Self>: - ~const PartialEq<Rhs> + Sized + [const] PartialEq<Rhs> + Sized { } diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 220a24caf09..0c3034c3d4c 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -717,7 +717,7 @@ pub trait TryFrom<T>: Sized { #[rustc_const_unstable(feature = "const_try", issue = "74935")] impl<T: PointeeSized, U: PointeeSized> const AsRef<U> for &T where - T: ~const AsRef<U>, + T: [const] AsRef<U>, { #[inline] fn as_ref(&self) -> &U { @@ -730,7 +730,7 @@ where #[rustc_const_unstable(feature = "const_try", issue = "74935")] impl<T: PointeeSized, U: PointeeSized> const AsRef<U> for &mut T where - T: ~const AsRef<U>, + T: [const] AsRef<U>, { #[inline] fn as_ref(&self) -> &U { @@ -751,7 +751,7 @@ where #[rustc_const_unstable(feature = "const_try", issue = "74935")] impl<T: PointeeSized, U: PointeeSized> const AsMut<U> for &mut T where - T: ~const AsMut<U>, + T: [const] AsMut<U>, { #[inline] fn as_mut(&mut self) -> &mut U { @@ -772,7 +772,7 @@ where #[rustc_const_unstable(feature = "const_from", issue = "143773")] impl<T, U> const Into<U> for T where - U: ~const From<T>, + U: [const] From<T>, { /// Calls `U::from(self)`. /// @@ -816,7 +816,7 @@ impl<T> const From<!> for T { #[rustc_const_unstable(feature = "const_from", issue = "143773")] impl<T, U> const TryInto<U> for T where - U: ~const TryFrom<T>, + U: [const] TryFrom<T>, { type Error = U::Error; @@ -832,7 +832,7 @@ where #[rustc_const_unstable(feature = "const_from", issue = "143773")] impl<T, U> const TryFrom<U> for T where - U: ~const Into<T>, + U: [const] Into<T>, { type Error = Infallible; diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index c43f3834630..e6b599fafcf 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -652,7 +652,7 @@ impl CStr { } } -#[stable(feature = "c_string_eq_c_str", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "c_string_eq_c_str", since = "1.90.0")] impl PartialEq<&Self> for CStr { #[inline] fn eq(&self, other: &&Self) -> bool { diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 696d323c66d..c72eeb9a9c9 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -649,8 +649,6 @@ pub const fn must_use<T>(value: T) -> T { /// } /// } /// ``` -/// -/// #[unstable(feature = "likely_unlikely", issue = "136873")] #[inline(always)] pub const fn likely(b: bool) -> bool { diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 106cc725fee..7228ad0ed6d 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -150,69 +150,63 @@ pub unsafe fn atomic_xchg<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: /// Adds to the current value, returning the previous value. /// `T` must be an integer or pointer type. -/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new -/// value stored at `*dst` will have the provenance of the old value stored there. +/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method. For example, [`AtomicIsize::fetch_add`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_xadd<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T; +pub unsafe fn atomic_xadd<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T; /// Subtract from the current value, returning the previous value. /// `T` must be an integer or pointer type. -/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new -/// value stored at `*dst` will have the provenance of the old value stored there. +/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method. For example, [`AtomicIsize::fetch_sub`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_xsub<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T; +pub unsafe fn atomic_xsub<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T; /// Bitwise and with the current value, returning the previous value. /// `T` must be an integer or pointer type. -/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new -/// value stored at `*dst` will have the provenance of the old value stored there. +/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method. For example, [`AtomicBool::fetch_and`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_and<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T; +pub unsafe fn atomic_and<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T; /// Bitwise nand with the current value, returning the previous value. /// `T` must be an integer or pointer type. -/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new -/// value stored at `*dst` will have the provenance of the old value stored there. +/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`AtomicBool`] type via the `fetch_nand` method. For example, [`AtomicBool::fetch_nand`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_nand<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T; +pub unsafe fn atomic_nand<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T; /// Bitwise or with the current value, returning the previous value. /// `T` must be an integer or pointer type. -/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new -/// value stored at `*dst` will have the provenance of the old value stored there. +/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method. For example, [`AtomicBool::fetch_or`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_or<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T; +pub unsafe fn atomic_or<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T; /// Bitwise xor with the current value, returning the previous value. /// `T` must be an integer or pointer type. -/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new -/// value stored at `*dst` will have the provenance of the old value stored there. +/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method. For example, [`AtomicBool::fetch_xor`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_xor<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T; +pub unsafe fn atomic_xor<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T; /// Maximum with the current value using a signed comparison. /// `T` must be a signed integer type. @@ -1828,7 +1822,7 @@ pub const fn three_way_compare<T: Copy>(lhs: T, rhss: T) -> crate::cmp::Ordering #[rustc_intrinsic] #[track_caller] #[miri::intrinsic_fallback_is_spec] // the fallbacks all `assume` to tell Miri -pub const unsafe fn disjoint_bitor<T: ~const fallback::DisjointBitOr>(a: T, b: T) -> T { +pub const unsafe fn disjoint_bitor<T: [const] fallback::DisjointBitOr>(a: T, b: T) -> T { // SAFETY: same preconditions as this function. unsafe { fallback::DisjointBitOr::disjoint_bitor(a, b) } } @@ -1897,7 +1891,7 @@ pub const fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool); #[rustc_nounwind] #[rustc_intrinsic] #[miri::intrinsic_fallback_is_spec] -pub const fn carrying_mul_add<T: ~const fallback::CarryingMulAdd<Unsigned = U>, U>( +pub const fn carrying_mul_add<T: [const] fallback::CarryingMulAdd<Unsigned = U>, U>( multiplier: T, multiplicand: T, addend: T, @@ -2667,7 +2661,7 @@ pub unsafe fn vtable_align(ptr: *const ()) -> usize; /// More specifically, this is the offset in bytes between successive /// items of the same type, including alignment padding. /// -/// The stabilized version of this intrinsic is [`size_of`]. +/// The stabilized version of this intrinsic is [`core::mem::size_of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic_const_stable_indirect] @@ -2681,7 +2675,7 @@ pub const fn size_of<T>() -> usize; /// Therefore, implementations must not require the user to uphold /// any safety invariants. /// -/// The stabilized version of this intrinsic is [`align_of`]. +/// The stabilized version of this intrinsic is [`core::mem::align_of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic_const_stable_indirect] @@ -2704,7 +2698,7 @@ pub const fn variant_count<T>() -> usize; /// The size of the referenced value in bytes. /// -/// The stabilized version of this intrinsic is [`size_of_val`]. +/// The stabilized version of this intrinsic is [`core::mem::size_of_val`]. /// /// # Safety /// @@ -2717,7 +2711,7 @@ pub const unsafe fn size_of_val<T: ?Sized>(ptr: *const T) -> usize; /// The required alignment of the referenced value. /// -/// The stabilized version of this intrinsic is [`align_of_val`]. +/// The stabilized version of this intrinsic is [`core::mem::align_of_val`]. /// /// # Safety /// diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 7ca41d224a0..56ca1305b60 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -233,10 +233,12 @@ //! //! ``` //! let mut values = vec![41]; -//! for x in &mut values { // same as `values.iter_mut()` +//! for x in &mut values { +//! // ^ same as `values.iter_mut()` //! *x += 1; //! } -//! for x in &values { // same as `values.iter()` +//! for x in &values { +//! // ^ same as `values.iter()` //! assert_eq!(*x, 42); //! } //! assert_eq!(values.len(), 1); diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 10f9d464f7d..7fb162a653f 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -807,7 +807,7 @@ pub trait Iterator { /// might be preferable to keep a functional style with longer iterators: /// /// ``` - /// (0..5).flat_map(|x| x * 100 .. x * 110) + /// (0..5).flat_map(|x| (x * 100)..(x * 110)) /// .enumerate() /// .filter(|&(i, x)| (i + x) % 3 == 0) /// .for_each(|(i, x)| println!("{i}:{x}")); @@ -1875,7 +1875,7 @@ pub trait Iterator { /// without giving up ownership of the original iterator, /// so you can use the original iterator afterwards. /// - /// Uses [impl<I: Iterator + ?Sized> Iterator for &mut I { type Item = I::Item; ...}](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#impl-Iterator-for-%26mut+I). + /// Uses [`impl<I: Iterator + ?Sized> Iterator for &mut I { type Item = I::Item; ...}`](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#impl-Iterator-for-%26mut+I). /// /// # Examples /// diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 3c33f4b1368..d5bce6ad233 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -195,6 +195,7 @@ #![feature(hexagon_target_feature)] #![feature(loongarch_target_feature)] #![feature(mips_target_feature)] +#![feature(nvptx_target_feature)] #![feature(powerpc_target_feature)] #![feature(riscv_target_feature)] #![feature(rtm_target_feature)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3d57da63683..c59290a757b 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -271,7 +271,10 @@ pub macro cfg_select($($tt:tt)*) { /// // expression given. /// debug_assert!(true); /// -/// fn some_expensive_computation() -> bool { true } // a very simple function +/// fn some_expensive_computation() -> bool { +/// // Some expensive computation here +/// true +/// } /// debug_assert!(some_expensive_computation()); /// /// // assert with a custom message @@ -1547,7 +1550,10 @@ pub(crate) mod builtin { /// // expression given. /// assert!(true); /// - /// fn some_computation() -> bool { true } // a very simple function + /// fn some_computation() -> bool { + /// // Some expensive computation here + /// true + /// } /// /// assert!(some_computation()); /// diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 45277a1c82d..ba00ee17b65 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -138,8 +138,7 @@ unsafe impl<T: Sync + PointeeSized> Send for &T {} /// impl Bar for Impl { } /// /// let x: &dyn Foo = &Impl; // OK -/// // let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot -/// // be made into an object +/// // let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot be made into an object /// ``` /// /// [trait object]: ../../book/ch17-02-trait-objects.html diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs new file mode 100644 index 00000000000..fecc94b815e --- /dev/null +++ b/library/core/src/mem/drop_guard.rs @@ -0,0 +1,155 @@ +use crate::fmt::{self, Debug}; +use crate::mem::ManuallyDrop; +use crate::ops::{Deref, DerefMut}; + +/// Wrap a value and run a closure when dropped. +/// +/// This is useful for quickly creating destructors inline. +/// +/// # Examples +/// +/// ```rust +/// # #![allow(unused)] +/// #![feature(drop_guard)] +/// +/// use std::mem::DropGuard; +/// +/// { +/// // Create a new guard around a string that will +/// // print its value when dropped. +/// let s = String::from("Chashu likes tuna"); +/// let mut s = DropGuard::new(s, |s| println!("{s}")); +/// +/// // Modify the string contained in the guard. +/// s.push_str("!!!"); +/// +/// // The guard will be dropped here, printing: +/// // "Chashu likes tuna!!!" +/// } +/// ``` +#[unstable(feature = "drop_guard", issue = "144426")] +#[doc(alias = "ScopeGuard")] +#[doc(alias = "defer")] +pub struct DropGuard<T, F> +where + F: FnOnce(T), +{ + inner: ManuallyDrop<T>, + f: ManuallyDrop<F>, +} + +impl<T, F> DropGuard<T, F> +where + F: FnOnce(T), +{ + /// Create a new instance of `DropGuard`. + /// + /// # Example + /// + /// ```rust + /// # #![allow(unused)] + /// #![feature(drop_guard)] + /// + /// use std::mem::DropGuard; + /// + /// let value = String::from("Chashu likes tuna"); + /// let guard = DropGuard::new(value, |s| println!("{s}")); + /// ``` + #[unstable(feature = "drop_guard", issue = "144426")] + #[must_use] + pub const fn new(inner: T, f: F) -> Self { + Self { inner: ManuallyDrop::new(inner), f: ManuallyDrop::new(f) } + } + + /// Consumes the `DropGuard`, returning the wrapped value. + /// + /// This will not execute the closure. This is implemented as an associated + /// function to prevent any potential conflicts with any other methods called + /// `into_inner` from the `Deref` and `DerefMut` impls. + /// + /// It is typically preferred to call this function instead of `mem::forget` + /// because it will return the stored value and drop variables captured + /// by the closure instead of leaking their owned resources. + /// + /// # Example + /// + /// ```rust + /// # #![allow(unused)] + /// #![feature(drop_guard)] + /// + /// use std::mem::DropGuard; + /// + /// let value = String::from("Nori likes chicken"); + /// let guard = DropGuard::new(value, |s| println!("{s}")); + /// assert_eq!(DropGuard::into_inner(guard), "Nori likes chicken"); + /// ``` + #[unstable(feature = "drop_guard", issue = "144426")] + #[inline] + pub fn into_inner(guard: Self) -> T { + // First we ensure that dropping the guard will not trigger + // its destructor + let mut guard = ManuallyDrop::new(guard); + + // Next we manually read the stored value from the guard. + // + // SAFETY: this is safe because we've taken ownership of the guard. + let value = unsafe { ManuallyDrop::take(&mut guard.inner) }; + + // Finally we drop the stored closure. We do this *after* having read + // the value, so that even if the closure's `drop` function panics, + // unwinding still tries to drop the value. + // + // SAFETY: this is safe because we've taken ownership of the guard. + unsafe { ManuallyDrop::drop(&mut guard.f) }; + value + } +} + +#[unstable(feature = "drop_guard", issue = "144426")] +impl<T, F> Deref for DropGuard<T, F> +where + F: FnOnce(T), +{ + type Target = T; + + fn deref(&self) -> &T { + &*self.inner + } +} + +#[unstable(feature = "drop_guard", issue = "144426")] +impl<T, F> DerefMut for DropGuard<T, F> +where + F: FnOnce(T), +{ + fn deref_mut(&mut self) -> &mut T { + &mut *self.inner + } +} + +#[unstable(feature = "drop_guard", issue = "144426")] +impl<T, F> Drop for DropGuard<T, F> +where + F: FnOnce(T), +{ + fn drop(&mut self) { + // SAFETY: `DropGuard` is in the process of being dropped. + let inner = unsafe { ManuallyDrop::take(&mut self.inner) }; + + // SAFETY: `DropGuard` is in the process of being dropped. + let f = unsafe { ManuallyDrop::take(&mut self.f) }; + + f(inner); + } +} + +#[unstable(feature = "drop_guard", issue = "144426")] +impl<T, F> Debug for DropGuard<T, F> +where + T: Debug, + F: FnOnce(T), +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 34d8370da7e..c160360cfac 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -773,8 +773,7 @@ impl<T> MaybeUninit<T> { /// // Initialize the `MaybeUninit` using `Cell::set`: /// unsafe { /// b.assume_init_ref().set(true); - /// // ^^^^^^^^^^^^^^^ - /// // Reference to an uninitialized `Cell<bool>`: UB! + /// //^^^^^^^^^^^^^^^ Reference to an uninitialized `Cell<bool>`: UB! /// } /// ``` #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] @@ -864,9 +863,9 @@ impl<T> MaybeUninit<T> { /// { /// let mut buffer = MaybeUninit::<[u8; 64]>::uninit(); /// reader.read_exact(unsafe { buffer.assume_init_mut() })?; - /// // ^^^^^^^^^^^^^^^^^^^^^^^^ - /// // (mutable) reference to uninitialized memory! - /// // This is undefined behavior. + /// // ^^^^^^^^^^^^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. /// Ok(unsafe { buffer.assume_init() }) /// } /// ``` @@ -884,13 +883,13 @@ impl<T> MaybeUninit<T> { /// let foo: Foo = unsafe { /// let mut foo = MaybeUninit::<Foo>::uninit(); /// ptr::write(&mut foo.assume_init_mut().a as *mut u32, 1337); - /// // ^^^^^^^^^^^^^^^^^^^^^ - /// // (mutable) reference to uninitialized memory! - /// // This is undefined behavior. + /// // ^^^^^^^^^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. /// ptr::write(&mut foo.assume_init_mut().b as *mut u8, 42); - /// // ^^^^^^^^^^^^^^^^^^^^^ - /// // (mutable) reference to uninitialized memory! - /// // This is undefined behavior. + /// // ^^^^^^^^^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. /// foo.assume_init() /// }; /// ``` diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 33407637ab3..db4c8e9e551 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -21,6 +21,10 @@ mod transmutability; #[unstable(feature = "transmutability", issue = "99571")] pub use transmutability::{Assume, TransmuteFrom}; +mod drop_guard; +#[unstable(feature = "drop_guard", issue = "144426")] +pub use drop_guard::DropGuard; + // This one has to be a re-export (rather than wrapping the underlying intrinsic) so that we can do // the special magic "types have equal size" check at the call site. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs index 69924199f99..df99e9b20c2 100644 --- a/library/core/src/net/socket_addr.rs +++ b/library/core/src/net/socket_addr.rs @@ -613,7 +613,7 @@ impl const From<SocketAddrV6> for SocketAddr { #[stable(feature = "addr_from_into_ip", since = "1.17.0")] #[rustc_const_unstable(feature = "const_try", issue = "74935")] -impl<I: ~const Into<IpAddr>> const From<(I, u16)> for SocketAddr { +impl<I: [const] Into<IpAddr>> const From<(I, u16)> for SocketAddr { /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`]. /// /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 5683d5ec92d..bd2f7445612 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -177,14 +177,14 @@ macro_rules! int_impl { /// #[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")] /// - /// assert_eq!(n.isolate_most_significant_one(), 0b_01000000); - #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_most_significant_one(), 0);")] + /// assert_eq!(n.isolate_highest_one(), 0b_01000000); + #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_highest_one(), 0);")] /// ``` #[unstable(feature = "isolate_most_least_significant_one", issue = "136909")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - pub const fn isolate_most_significant_one(self) -> Self { + pub const fn isolate_highest_one(self) -> Self { self & (((1 as $SelfT) << (<$SelfT>::BITS - 1)).wrapping_shr(self.leading_zeros())) } @@ -198,14 +198,14 @@ macro_rules! int_impl { /// #[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")] /// - /// assert_eq!(n.isolate_least_significant_one(), 0b_00000100); - #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_least_significant_one(), 0);")] + /// assert_eq!(n.isolate_lowest_one(), 0b_00000100); + #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_lowest_one(), 0);")] /// ``` #[unstable(feature = "isolate_most_least_significant_one", issue = "136909")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - pub const fn isolate_least_significant_one(self) -> Self { + pub const fn isolate_lowest_one(self) -> Self { self & self.wrapping_neg() } @@ -469,17 +469,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -560,17 +559,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_unsigned(2), 3);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_unsigned(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -611,17 +609,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).strict_sub(1), ", stringify!($SelfT), "::MIN + 1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -702,17 +699,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub_unsigned(2), -1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub_unsigned(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -753,17 +749,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.strict_mul(1), ", stringify!($SelfT), "::MAX);")] /// ``` /// /// The following panics because of overflow: /// /// ``` should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -855,24 +850,22 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div(-1), ", stringify!($Max), ");")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div(-1);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -924,24 +917,22 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div_euclid(-1), ", stringify!($Max), ");")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div_euclid(-1);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1092,24 +1083,22 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem(2), 1);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem(-1);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1160,24 +1149,22 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem_euclid(2), 1);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem_euclid(-1);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1249,17 +1236,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_neg(), -5);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_neg();")] /// - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1306,17 +1292,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x1", stringify!($SelfT), ".strict_shl(129);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1422,17 +1407,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(128);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1542,17 +1526,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").strict_abs(), 5);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_abs();")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1612,17 +1595,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(8", stringify!($SelfT), ".strict_pow(2), 64);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs index b92561c9e35..d57b1d433e5 100644 --- a/library/core/src/num/niche_types.rs +++ b/library/core/src/num/niche_types.rs @@ -46,11 +46,11 @@ macro_rules! define_valid_range_type { /// primitive without checking whether its zero. /// /// # Safety - /// Immediate language UB if `val == 0`, as it violates the validity - /// invariant of this type. + /// Immediate language UB if `val` is not within the valid range for this + /// type, as it violates the validity invariant. #[inline] pub const unsafe fn new_unchecked(val: $int) -> Self { - // SAFETY: Caller promised that `val` is non-zero. + // SAFETY: Caller promised that `val` is within the valid range. unsafe { $name(val) } } diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index f793602de50..08a66361e6f 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -203,7 +203,7 @@ impl<T> Copy for NonZero<T> where T: ZeroablePrimitive {} #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl<T> const PartialEq for NonZero<T> where - T: ZeroablePrimitive + ~const PartialEq, + T: ZeroablePrimitive + [const] PartialEq, { #[inline] fn eq(&self, other: &Self) -> bool { @@ -629,7 +629,7 @@ macro_rules! nonzero_integer { #[doc = concat!("let a = NonZero::<", stringify!($Int), ">::new(0b_01100100)?;")] #[doc = concat!("let b = NonZero::<", stringify!($Int), ">::new(0b_01000000)?;")] /// - /// assert_eq!(a.isolate_most_significant_one(), b); + /// assert_eq!(a.isolate_highest_one(), b); /// # Some(()) /// # } /// ``` @@ -637,7 +637,7 @@ macro_rules! nonzero_integer { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - pub const fn isolate_most_significant_one(self) -> Self { + pub const fn isolate_highest_one(self) -> Self { let n = self.get() & (((1 as $Int) << (<$Int>::BITS - 1)).wrapping_shr(self.leading_zeros())); // SAFETY: @@ -659,7 +659,7 @@ macro_rules! nonzero_integer { #[doc = concat!("let a = NonZero::<", stringify!($Int), ">::new(0b_01100100)?;")] #[doc = concat!("let b = NonZero::<", stringify!($Int), ">::new(0b_00000100)?;")] /// - /// assert_eq!(a.isolate_least_significant_one(), b); + /// assert_eq!(a.isolate_lowest_one(), b); /// # Some(()) /// # } /// ``` @@ -667,7 +667,7 @@ macro_rules! nonzero_integer { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - pub const fn isolate_least_significant_one(self) -> Self { + pub const fn isolate_lowest_one(self) -> Self { let n = self.get(); let n = n & n.wrapping_neg(); diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 584cd60fbe5..2c9a1196849 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -229,14 +229,14 @@ macro_rules! uint_impl { /// #[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")] /// - /// assert_eq!(n.isolate_most_significant_one(), 0b_01000000); - #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_most_significant_one(), 0);")] + /// assert_eq!(n.isolate_highest_one(), 0b_01000000); + #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_highest_one(), 0);")] /// ``` #[unstable(feature = "isolate_most_least_significant_one", issue = "136909")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - pub const fn isolate_most_significant_one(self) -> Self { + pub const fn isolate_highest_one(self) -> Self { self & (((1 as $SelfT) << (<$SelfT>::BITS - 1)).wrapping_shr(self.leading_zeros())) } @@ -250,14 +250,14 @@ macro_rules! uint_impl { /// #[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")] /// - /// assert_eq!(n.isolate_least_significant_one(), 0b_00000100); - #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_least_significant_one(), 0);")] + /// assert_eq!(n.isolate_lowest_one(), 0b_00000100); + #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_lowest_one(), 0);")] /// ``` #[unstable(feature = "isolate_most_least_significant_one", issue = "136909")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - pub const fn isolate_least_significant_one(self) -> Self { + pub const fn isolate_lowest_one(self) -> Self { self & self.wrapping_neg() } @@ -538,17 +538,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -630,22 +629,20 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_signed(2), 3);")] /// ``` /// /// The following panic because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_add_signed(-2);")] /// ``` /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_signed(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -695,17 +692,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub(1), 0);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0", stringify!($SelfT), ".strict_sub(1);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -790,8 +786,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_signed(-2), Some(3));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_sub_signed(-4), None);")] /// ``` - #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "1.90.0")] + #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "1.90.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -817,22 +813,20 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".strict_sub_signed(2), 1);")] /// ``` /// /// The following panic because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_sub_signed(2);")] /// ``` /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX).strict_sub_signed(-1);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -850,7 +844,6 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(unsigned_signed_diff)] #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_signed_diff(2), Some(8));")] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_signed_diff(10), Some(-8));")] #[doc = concat!( @@ -888,7 +881,8 @@ macro_rules! uint_impl { "::MAX), Some(0));" )] /// ``` - #[unstable(feature = "unsigned_signed_diff", issue = "126041")] + #[stable(feature = "unsigned_signed_diff", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "unsigned_signed_diff", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn checked_signed_diff(self, rhs: Self) -> Option<$SignedT> { let res = self.wrapping_sub(rhs) as $SignedT; @@ -932,17 +926,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_mul(1), 5);")] /// ``` /// /// The following panics because of overflow: /// /// ``` should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1029,17 +1022,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div(10), 10);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1085,16 +1077,15 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div_euclid(10), 10);")] /// ``` /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1239,17 +1230,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem(10), 0);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1296,17 +1286,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem_euclid(10), 0);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1568,17 +1557,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".strict_neg(), 0);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_neg();")] /// - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1625,17 +1613,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shl(129);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1741,17 +1728,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(129);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1867,17 +1853,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".strict_pow(5), 32);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1974,8 +1959,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_sub_signed(-2), 3);")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_sub_signed(-4), ", stringify!($SelfT), "::MAX);")] /// ``` - #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "1.90.0")] + #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "1.90.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2122,8 +2107,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_sub_signed(-2), 3);")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_sub_signed(-4), 1);")] /// ``` - #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "1.90.0")] + #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "1.90.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2581,8 +2566,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_signed(-2), (3, false));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_sub_signed(-4), (1, true));")] /// ``` - #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "1.90.0")] + #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "1.90.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 26661b20c12..7489a8bb6e7 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -187,6 +187,80 @@ impl<B, C> ControlFlow<B, C> { } } + /// Converts the `ControlFlow` into an `Result` which is `Ok` if the + /// `ControlFlow` was `Break` and `Err` if otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_ok)] + /// + /// use std::ops::ControlFlow; + /// + /// struct TreeNode<T> { + /// value: T, + /// left: Option<Box<TreeNode<T>>>, + /// right: Option<Box<TreeNode<T>>>, + /// } + /// + /// impl<T> TreeNode<T> { + /// fn find<'a>(&'a self, mut predicate: impl FnMut(&T) -> bool) -> Result<&'a T, ()> { + /// let mut f = |t: &'a T| -> ControlFlow<&'a T> { + /// if predicate(t) { + /// ControlFlow::Break(t) + /// } else { + /// ControlFlow::Continue(()) + /// } + /// }; + /// + /// self.traverse_inorder(&mut f).break_ok() + /// } + /// + /// fn traverse_inorder<'a, B>( + /// &'a self, + /// f: &mut impl FnMut(&'a T) -> ControlFlow<B>, + /// ) -> ControlFlow<B> { + /// if let Some(left) = &self.left { + /// left.traverse_inorder(f)?; + /// } + /// f(&self.value)?; + /// if let Some(right) = &self.right { + /// right.traverse_inorder(f)?; + /// } + /// ControlFlow::Continue(()) + /// } + /// + /// fn leaf(value: T) -> Option<Box<TreeNode<T>>> { + /// Some(Box::new(Self { + /// value, + /// left: None, + /// right: None, + /// })) + /// } + /// } + /// + /// let node = TreeNode { + /// value: 0, + /// left: TreeNode::leaf(1), + /// right: Some(Box::new(TreeNode { + /// value: -1, + /// left: TreeNode::leaf(5), + /// right: TreeNode::leaf(2), + /// })), + /// }; + /// + /// let res = node.find(|val: &i32| *val > 3); + /// assert_eq!(res, Ok(&5)); + /// ``` + #[inline] + #[unstable(feature = "control_flow_ok", issue = "140266")] + pub fn break_ok(self) -> Result<B, C> { + match self { + ControlFlow::Continue(c) => Err(c), + ControlFlow::Break(b) => Ok(b), + } + } + /// Maps `ControlFlow<B, C>` to `ControlFlow<T, C>` by applying a function /// to the break value in case it exists. #[inline] @@ -218,6 +292,79 @@ impl<B, C> ControlFlow<B, C> { } } + /// Converts the `ControlFlow` into an `Result` which is `Ok` if the + /// `ControlFlow` was `Continue` and `Err` if otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_ok)] + /// + /// use std::ops::ControlFlow; + /// + /// struct TreeNode<T> { + /// value: T, + /// left: Option<Box<TreeNode<T>>>, + /// right: Option<Box<TreeNode<T>>>, + /// } + /// + /// impl<T> TreeNode<T> { + /// fn validate<B>(&self, f: &mut impl FnMut(&T) -> ControlFlow<B>) -> Result<(), B> { + /// self.traverse_inorder(f).continue_ok() + /// } + /// + /// fn traverse_inorder<B>(&self, f: &mut impl FnMut(&T) -> ControlFlow<B>) -> ControlFlow<B> { + /// if let Some(left) = &self.left { + /// left.traverse_inorder(f)?; + /// } + /// f(&self.value)?; + /// if let Some(right) = &self.right { + /// right.traverse_inorder(f)?; + /// } + /// ControlFlow::Continue(()) + /// } + /// + /// fn leaf(value: T) -> Option<Box<TreeNode<T>>> { + /// Some(Box::new(Self { + /// value, + /// left: None, + /// right: None, + /// })) + /// } + /// } + /// + /// let node = TreeNode { + /// value: 0, + /// left: TreeNode::leaf(1), + /// right: Some(Box::new(TreeNode { + /// value: -1, + /// left: TreeNode::leaf(5), + /// right: TreeNode::leaf(2), + /// })), + /// }; + /// + /// let res = node.validate(&mut |val| { + /// if *val < 0 { + /// return ControlFlow::Break("negative value detected"); + /// } + /// + /// if *val > 4 { + /// return ControlFlow::Break("too big value detected"); + /// } + /// + /// ControlFlow::Continue(()) + /// }); + /// assert_eq!(res, Err("too big value detected")); + /// ``` + #[inline] + #[unstable(feature = "control_flow_ok", issue = "140266")] + pub fn continue_ok(self) -> Result<C, B> { + match self { + ControlFlow::Continue(c) => Ok(c), + ControlFlow::Break(b) => Err(b), + } + } + /// Maps `ControlFlow<B, C>` to `ControlFlow<B, T>` by applying a function /// to the continue value in case it exists. #[inline] diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index c2dede9fa08..5f68c1f55c2 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -269,7 +269,7 @@ impl<T: ?Sized> const Deref for &mut T { #[stable(feature = "rust1", since = "1.0.0")] #[const_trait] #[rustc_const_unstable(feature = "const_deref", issue = "88955")] -pub trait DerefMut: ~const Deref + PointeeSized { +pub trait DerefMut: [const] Deref + PointeeSized { /// Mutably dereferences the value. #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "deref_mut_method"] diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index efc751a094d..ad46e52a475 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -260,7 +260,7 @@ mod impls { #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] impl<A: Tuple, F: ?Sized> const Fn<A> for &F where - F: ~const Fn<A>, + F: [const] Fn<A>, { extern "rust-call" fn call(&self, args: A) -> F::Output { (**self).call(args) @@ -271,7 +271,7 @@ mod impls { #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] impl<A: Tuple, F: ?Sized> const FnMut<A> for &F where - F: ~const Fn<A>, + F: [const] Fn<A>, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (**self).call(args) @@ -282,7 +282,7 @@ mod impls { #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] impl<A: Tuple, F: ?Sized> const FnOnce<A> for &F where - F: ~const Fn<A>, + F: [const] Fn<A>, { type Output = F::Output; @@ -295,7 +295,7 @@ mod impls { #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] impl<A: Tuple, F: ?Sized> const FnMut<A> for &mut F where - F: ~const FnMut<A>, + F: [const] FnMut<A>, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (*self).call_mut(args) @@ -306,7 +306,7 @@ mod impls { #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] impl<A: Tuple, F: ?Sized> const FnOnce<A> for &mut F where - F: ~const FnMut<A>, + F: [const] FnMut<A>, { type Output = F::Output; extern "rust-call" fn call_once(self, args: A) -> F::Output { diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs index d8489e9a949..1aed2fb4742 100644 --- a/library/core/src/ops/index.rs +++ b/library/core/src/ops/index.rs @@ -169,7 +169,7 @@ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#ind #[doc(alias = "[]")] #[rustc_const_unstable(feature = "const_index", issue = "143775")] #[const_trait] -pub trait IndexMut<Idx: ?Sized>: ~const Index<Idx> { +pub trait IndexMut<Idx: ?Sized>: [const] Index<Idx> { /// Performs the mutable indexing (`container[index]`) operation. /// /// # Panics diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index ad3b6439a61..f33a33e6b75 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -1141,6 +1141,12 @@ impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) { } } +// This impl intentionally does not have `T: ?Sized`; +// see https://github.com/rust-lang/rust/pull/61584 for discussion of why. +// +/// If you need to use this implementation where `T` is unsized, +/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], +/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`. #[stable(feature = "collections_range", since = "1.28.0")] impl<T> RangeBounds<T> for RangeFrom<&T> { fn start_bound(&self) -> Bound<&T> { @@ -1151,6 +1157,12 @@ impl<T> RangeBounds<T> for RangeFrom<&T> { } } +// This impl intentionally does not have `T: ?Sized`; +// see https://github.com/rust-lang/rust/pull/61584 for discussion of why. +// +/// If you need to use this implementation where `T` is unsized, +/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], +/// i.e. replace `..end` with `(Bound::Unbounded, Bound::Excluded(end))`. #[stable(feature = "collections_range", since = "1.28.0")] impl<T> RangeBounds<T> for RangeTo<&T> { fn start_bound(&self) -> Bound<&T> { @@ -1161,6 +1173,12 @@ impl<T> RangeBounds<T> for RangeTo<&T> { } } +// This impl intentionally does not have `T: ?Sized`; +// see https://github.com/rust-lang/rust/pull/61584 for discussion of why. +// +/// If you need to use this implementation where `T` is unsized, +/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], +/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`. #[stable(feature = "collections_range", since = "1.28.0")] impl<T> RangeBounds<T> for Range<&T> { fn start_bound(&self) -> Bound<&T> { @@ -1171,6 +1189,12 @@ impl<T> RangeBounds<T> for Range<&T> { } } +// This impl intentionally does not have `T: ?Sized`; +// see https://github.com/rust-lang/rust/pull/61584 for discussion of why. +// +/// If you need to use this implementation where `T` is unsized, +/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], +/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`. #[stable(feature = "collections_range", since = "1.28.0")] impl<T> RangeBounds<T> for RangeInclusive<&T> { fn start_bound(&self) -> Bound<&T> { @@ -1181,6 +1205,12 @@ impl<T> RangeBounds<T> for RangeInclusive<&T> { } } +// This impl intentionally does not have `T: ?Sized`; +// see https://github.com/rust-lang/rust/pull/61584 for discussion of why. +// +/// If you need to use this implementation where `T` is unsized, +/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], +/// i.e. replace `..=end` with `(Bound::Unbounded, Bound::Included(end))`. #[stable(feature = "collections_range", since = "1.28.0")] impl<T> RangeBounds<T> for RangeToInclusive<&T> { fn start_bound(&self) -> Bound<&T> { diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index a889c824be5..76bf438878f 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -130,7 +130,7 @@ use crate::ops::ControlFlow; #[lang = "Try"] #[const_trait] #[rustc_const_unstable(feature = "const_try", issue = "74935")] -pub trait Try: ~const FromResidual { +pub trait Try: [const] FromResidual { /// The type of the value produced by `?` when *not* short-circuiting. #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] type Output; diff --git a/library/core/src/option.rs b/library/core/src/option.rs index ed070fbd227..560d20ce617 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -651,7 +651,7 @@ impl<T> Option<T> { #[inline] #[stable(feature = "is_some_and", since = "1.70.0")] #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] - pub const fn is_some_and(self, f: impl ~const FnOnce(T) -> bool + ~const Destruct) -> bool { + pub const fn is_some_and(self, f: impl [const] FnOnce(T) -> bool + [const] Destruct) -> bool { match self { None => false, Some(x) => f(x), @@ -700,7 +700,7 @@ impl<T> Option<T> { #[inline] #[stable(feature = "is_none_or", since = "1.82.0")] #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] - pub const fn is_none_or(self, f: impl ~const FnOnce(T) -> bool + ~const Destruct) -> bool { + pub const fn is_none_or(self, f: impl [const] FnOnce(T) -> bool + [const] Destruct) -> bool { match self { None => true, Some(x) => f(x), @@ -1030,7 +1030,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn unwrap_or(self, default: T) -> T where - T: ~const Destruct, + T: [const] Destruct, { match self { Some(x) => x, @@ -1053,7 +1053,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn unwrap_or_else<F>(self, f: F) -> T where - F: ~const FnOnce() -> T + ~const Destruct, + F: [const] FnOnce() -> T + [const] Destruct, { match self { Some(x) => x, @@ -1085,7 +1085,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn unwrap_or_default(self) -> T where - T: ~const Default, + T: [const] Default, { match self { Some(x) => x, @@ -1152,7 +1152,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn map<U, F>(self, f: F) -> Option<U> where - F: ~const FnOnce(T) -> U + ~const Destruct, + F: [const] FnOnce(T) -> U + [const] Destruct, { match self { Some(x) => Some(f(x)), @@ -1183,7 +1183,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn inspect<F>(self, f: F) -> Self where - F: ~const FnOnce(&T) + ~const Destruct, + F: [const] FnOnce(&T) + [const] Destruct, { if let Some(ref x) = self { f(x); @@ -1216,8 +1216,8 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn map_or<U, F>(self, default: U, f: F) -> U where - F: ~const FnOnce(T) -> U + ~const Destruct, - U: ~const Destruct, + F: [const] FnOnce(T) -> U + [const] Destruct, + U: [const] Destruct, { match self { Some(t) => f(t), @@ -1263,8 +1263,8 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn map_or_else<U, D, F>(self, default: D, f: F) -> U where - D: ~const FnOnce() -> U + ~const Destruct, - F: ~const FnOnce(T) -> U + ~const Destruct, + D: [const] FnOnce() -> U + [const] Destruct, + F: [const] FnOnce(T) -> U + [const] Destruct, { match self { Some(t) => f(t), @@ -1294,8 +1294,8 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn map_or_default<U, F>(self, f: F) -> U where - U: ~const Default, - F: ~const FnOnce(T) -> U + ~const Destruct, + U: [const] Default, + F: [const] FnOnce(T) -> U + [const] Destruct, { match self { Some(t) => f(t), @@ -1327,7 +1327,7 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] - pub const fn ok_or<E: ~const Destruct>(self, err: E) -> Result<T, E> { + pub const fn ok_or<E: [const] Destruct>(self, err: E) -> Result<T, E> { match self { Some(v) => Ok(v), None => Err(err), @@ -1355,7 +1355,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn ok_or_else<E, F>(self, err: F) -> Result<T, E> where - F: ~const FnOnce() -> E + ~const Destruct, + F: [const] FnOnce() -> E + [const] Destruct, { match self { Some(v) => Ok(v), @@ -1487,8 +1487,8 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn and<U>(self, optb: Option<U>) -> Option<U> where - T: ~const Destruct, - U: ~const Destruct, + T: [const] Destruct, + U: [const] Destruct, { match self { Some(_) => optb, @@ -1531,7 +1531,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn and_then<U, F>(self, f: F) -> Option<U> where - F: ~const FnOnce(T) -> Option<U> + ~const Destruct, + F: [const] FnOnce(T) -> Option<U> + [const] Destruct, { match self { Some(x) => f(x), @@ -1568,8 +1568,8 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn filter<P>(self, predicate: P) -> Self where - P: ~const FnOnce(&T) -> bool + ~const Destruct, - T: ~const Destruct, + P: [const] FnOnce(&T) -> bool + [const] Destruct, + T: [const] Destruct, { if let Some(x) = self { if predicate(&x) { @@ -1611,7 +1611,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn or(self, optb: Option<T>) -> Option<T> where - T: ~const Destruct, + T: [const] Destruct, { match self { x @ Some(_) => x, @@ -1637,10 +1637,10 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn or_else<F>(self, f: F) -> Option<T> where - F: ~const FnOnce() -> Option<T> + ~const Destruct, + F: [const] FnOnce() -> Option<T> + [const] Destruct, //FIXME(const_hack): this `T: ~const Destruct` is unnecessary, but even precise live drops can't tell // no value of type `T` gets dropped here - T: ~const Destruct, + T: [const] Destruct, { match self { x @ Some(_) => x, @@ -1674,7 +1674,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn xor(self, optb: Option<T>) -> Option<T> where - T: ~const Destruct, + T: [const] Destruct, { match (self, optb) { (a @ Some(_), None) => a, @@ -1712,7 +1712,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn insert(&mut self, value: T) -> &mut T where - T: ~const Destruct, + T: [const] Destruct, { *self = Some(value); @@ -1768,7 +1768,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn get_or_insert_default(&mut self) -> &mut T where - T: ~const Default + ~const Destruct, + T: [const] Default + [const] Destruct, { self.get_or_insert_with(T::default) } @@ -1795,8 +1795,8 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn get_or_insert_with<F>(&mut self, f: F) -> &mut T where - F: ~const FnOnce() -> T + ~const Destruct, - T: ~const Destruct, + F: [const] FnOnce() -> T + [const] Destruct, + T: [const] Destruct, { if let None = self { *self = Some(f()); @@ -1863,7 +1863,7 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn take_if<P>(&mut self, predicate: P) -> Option<T> where - P: ~const FnOnce(&mut T) -> bool + ~const Destruct, + P: [const] FnOnce(&mut T) -> bool + [const] Destruct, { if self.as_mut().map_or(false, predicate) { self.take() } else { None } } @@ -1911,8 +1911,8 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn zip<U>(self, other: Option<U>) -> Option<(T, U)> where - T: ~const Destruct, - U: ~const Destruct, + T: [const] Destruct, + U: [const] Destruct, { match (self, other) { (Some(a), Some(b)) => Some((a, b)), @@ -1952,9 +1952,9 @@ impl<T> Option<T> { #[rustc_const_unstable(feature = "const_option_ops", issue = "143956")] pub const fn zip_with<U, F, R>(self, other: Option<U>, f: F) -> Option<R> where - F: ~const FnOnce(T, U) -> R + ~const Destruct, - T: ~const Destruct, - U: ~const Destruct, + F: [const] FnOnce(T, U) -> R + [const] Destruct, + T: [const] Destruct, + U: [const] Destruct, { match (self, other) { (Some(a), Some(b)) => Some(f(a, b)), @@ -2149,7 +2149,7 @@ impl<T> const Clone for Option<T> where // FIXME(const_hack): the T: ~const Destruct should be inferred from the Self: ~const Destruct in clone_from. // See https://github.com/rust-lang/rust/issues/144207 - T: ~const Clone + ~const Destruct, + T: [const] Clone + [const] Destruct, { #[inline] fn clone(&self) -> Self { @@ -2307,7 +2307,7 @@ impl<'a, T> const From<&'a mut Option<T>> for Option<&'a mut T> { impl<T> crate::marker::StructuralPartialEq for Option<T> {} #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] -impl<T: ~const PartialEq> const PartialEq for Option<T> { +impl<T: [const] PartialEq> const PartialEq for Option<T> { #[inline] fn eq(&self, other: &Self) -> bool { // Spelling out the cases explicitly optimizes better than diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index 97227020885..6ef7d5a22a3 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -1,5 +1,7 @@ +use crate::cmp::Ordering; use crate::ffi::CStr; use crate::fmt; +use crate::hash::{Hash, Hasher}; use crate::marker::PhantomData; use crate::ptr::NonNull; @@ -32,7 +34,7 @@ use crate::ptr::NonNull; /// Files are compared as strings, not `Path`, which could be unexpected. /// See [`Location::file`]'s documentation for more discussion. #[lang = "panic_location"] -#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive(Copy, Clone)] #[stable(feature = "panic_hooks", since = "1.10.0")] pub struct Location<'a> { // A raw pointer is used rather than a reference because the pointer is valid for one more byte @@ -45,6 +47,44 @@ pub struct Location<'a> { } #[stable(feature = "panic_hooks", since = "1.10.0")] +impl PartialEq for Location<'_> { + fn eq(&self, other: &Self) -> bool { + // Compare col / line first as they're cheaper to compare and more likely to differ, + // while not impacting the result. + self.col == other.col && self.line == other.line && self.file() == other.file() + } +} + +#[stable(feature = "panic_hooks", since = "1.10.0")] +impl Eq for Location<'_> {} + +#[stable(feature = "panic_hooks", since = "1.10.0")] +impl Ord for Location<'_> { + fn cmp(&self, other: &Self) -> Ordering { + self.file() + .cmp(other.file()) + .then_with(|| self.line.cmp(&other.line)) + .then_with(|| self.col.cmp(&other.col)) + } +} + +#[stable(feature = "panic_hooks", since = "1.10.0")] +impl PartialOrd for Location<'_> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +#[stable(feature = "panic_hooks", since = "1.10.0")] +impl Hash for Location<'_> { + fn hash<H: Hasher>(&self, state: &mut H) { + self.file().hash(state); + self.line.hash(state); + self.col.hash(state); + } +} + +#[stable(feature = "panic_hooks", since = "1.10.0")] impl fmt::Debug for Location<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Location") diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 9a1ba7d1728..1c824e336be 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -271,6 +271,7 @@ mod prim_bool {} /// When the compiler sees a value of type `!` in a [coercion site], it implicitly inserts a /// coercion to allow the type checker to infer any type: /// +// FIXME: use `core::convert::absurd` here instead, once it's merged /// ```rust,ignore (illustrative-and-has-placeholders) /// // this /// let x: u8 = panic!(); @@ -281,7 +282,6 @@ mod prim_bool {} /// // where absurd is a function with the following signature /// // (it's sound, because `!` always marks unreachable code): /// fn absurd<T>(_: !) -> T { ... } -// FIXME: use `core::convert::absurd` here instead, once it's merged /// ``` /// /// This can lead to compilation errors if the type cannot be inferred: diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index bd5b4e21baa..402634e49b3 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -1,3 +1,5 @@ +#![allow(clippy::enum_clike_unportable_variant)] + use crate::num::NonZero; use crate::ub_checks::assert_unsafe_precondition; use crate::{cmp, fmt, hash, mem, num}; @@ -241,7 +243,7 @@ impl const Default for Alignment { #[cfg(target_pointer_width = "16")] #[derive(Copy, Clone, PartialEq, Eq)] -#[repr(u16)] +#[repr(usize)] enum AlignmentEnum { _Align1Shl0 = 1 << 0, _Align1Shl1 = 1 << 1, @@ -263,7 +265,7 @@ enum AlignmentEnum { #[cfg(target_pointer_width = "32")] #[derive(Copy, Clone, PartialEq, Eq)] -#[repr(u32)] +#[repr(usize)] enum AlignmentEnum { _Align1Shl0 = 1 << 0, _Align1Shl1 = 1 << 1, @@ -301,7 +303,7 @@ enum AlignmentEnum { #[cfg(target_pointer_width = "64")] #[derive(Copy, Clone, PartialEq, Eq)] -#[repr(u64)] +#[repr(usize)] enum AlignmentEnum { _Align1Shl0 = 1 << 0, _Align1Shl1 = 1 << 1, diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 2ad520b7ead..8b3703bd4b3 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1528,7 +1528,7 @@ impl<T> *const [T] { #[inline] pub const unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output where - I: ~const SliceIndex<[T]>, + I: [const] SliceIndex<[T]>, { // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. unsafe { index.get_unchecked(self) } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index dbe3999b4a4..1a2a5182567 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -974,9 +974,10 @@ pub const fn dangling_mut<T>() -> *mut T { #[must_use] #[inline(always)] #[stable(feature = "exposed_provenance", since = "1.84.0")] +#[rustc_const_unstable(feature = "const_exposed_provenance", issue = "144538")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead -pub fn with_exposed_provenance<T>(addr: usize) -> *const T { +pub const fn with_exposed_provenance<T>(addr: usize) -> *const T { addr as *const T } @@ -1014,9 +1015,10 @@ pub fn with_exposed_provenance<T>(addr: usize) -> *const T { #[must_use] #[inline(always)] #[stable(feature = "exposed_provenance", since = "1.84.0")] +#[rustc_const_unstable(feature = "const_exposed_provenance", issue = "144538")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead -pub fn with_exposed_provenance_mut<T>(addr: usize) -> *mut T { +pub const fn with_exposed_provenance_mut<T>(addr: usize) -> *mut T { addr as *mut T } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 579e2461103..af39ec86d7a 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1885,7 +1885,7 @@ impl<T> *mut [T] { #[inline(always)] pub const unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output where - I: ~const SliceIndex<[T]>, + I: [const] SliceIndex<[T]>, { // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. unsafe { index.get_unchecked_mut(self) } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 62da6567cca..8667361fecc 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1601,7 +1601,7 @@ impl<T> NonNull<[T]> { #[inline] pub const unsafe fn get_unchecked_mut<I>(self, index: I) -> NonNull<I::Output> where - I: ~const SliceIndex<[T]>, + I: [const] SliceIndex<[T]>, { // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. // As a consequence, the resulting pointer cannot be null. diff --git a/library/core/src/range.rs b/library/core/src/range.rs index 5cd7956291c..7158fa0fcf0 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -167,6 +167,12 @@ impl<T> RangeBounds<T> for Range<T> { } } +// This impl intentionally does not have `T: ?Sized`; +// see https://github.com/rust-lang/rust/pull/61584 for discussion of why. +// +/// If you need to use this implementation where `T` is unsized, +/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], +/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`. #[unstable(feature = "new_range_api", issue = "125687")] impl<T> RangeBounds<T> for Range<&T> { fn start_bound(&self) -> Bound<&T> { @@ -346,6 +352,12 @@ impl<T> RangeBounds<T> for RangeInclusive<T> { } } +// This impl intentionally does not have `T: ?Sized`; +// see https://github.com/rust-lang/rust/pull/61584 for discussion of why. +// +/// If you need to use this implementation where `T` is unsized, +/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], +/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`. #[unstable(feature = "new_range_api", issue = "125687")] impl<T> RangeBounds<T> for RangeInclusive<&T> { fn start_bound(&self) -> Bound<&T> { @@ -491,6 +503,12 @@ impl<T> RangeBounds<T> for RangeFrom<T> { } } +// This impl intentionally does not have `T: ?Sized`; +// see https://github.com/rust-lang/rust/pull/61584 for discussion of why. +// +/// If you need to use this implementation where `T` is unsized, +/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], +/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`. #[unstable(feature = "new_range_api", issue = "125687")] impl<T> RangeBounds<T> for RangeFrom<&T> { fn start_bound(&self) -> Bound<&T> { diff --git a/library/core/src/result.rs b/library/core/src/result.rs index f65257ff59b..6148bdb866a 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -534,6 +534,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{self, FusedIterator, TrustedLen}; +use crate::marker::Destruct; use crate::ops::{self, ControlFlow, Deref, DerefMut}; use crate::{convert, fmt, hint}; @@ -606,7 +607,13 @@ impl<T, E> Result<T, E> { #[must_use] #[inline] #[stable(feature = "is_some_and", since = "1.70.0")] - pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn is_ok_and<F>(self, f: F) -> bool + where + F: [const] FnOnce(T) -> bool + [const] Destruct, + T: [const] Destruct, + E: [const] Destruct, + { match self { Err(_) => false, Ok(x) => f(x), @@ -655,7 +662,13 @@ impl<T, E> Result<T, E> { #[must_use] #[inline] #[stable(feature = "is_some_and", since = "1.70.0")] - pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn is_err_and<F>(self, f: F) -> bool + where + F: [const] FnOnce(E) -> bool + [const] Destruct, + E: [const] Destruct, + T: [const] Destruct, + { match self { Ok(_) => false, Err(e) => f(e), @@ -682,8 +695,13 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] #[rustc_diagnostic_item = "result_ok_method"] - pub fn ok(self) -> Option<T> { + pub const fn ok(self) -> Option<T> + where + T: [const] Destruct, + E: [const] Destruct, + { match self { Ok(x) => Some(x), Err(_) => None, @@ -706,7 +724,12 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn err(self) -> Option<E> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn err(self) -> Option<E> + where + T: [const] Destruct, + E: [const] Destruct, + { match self { Ok(_) => None, Err(x) => Some(x), @@ -796,7 +819,11 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn map<U, F>(self, op: F) -> Result<U, E> + where + F: [const] FnOnce(T) -> U + [const] Destruct, + { match self { Ok(t) => Ok(op(t)), Err(e) => Err(e), @@ -823,8 +850,15 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "result_map_or", since = "1.41.0")] + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] #[must_use = "if you don't need the returned value, use `if let` instead"] - pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U { + pub const fn map_or<U, F>(self, default: U, f: F) -> U + where + F: [const] FnOnce(T) -> U + [const] Destruct, + T: [const] Destruct, + E: [const] Destruct, + U: [const] Destruct, + { match self { Ok(t) => f(t), Err(_) => default, @@ -851,7 +885,12 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "result_map_or_else", since = "1.41.0")] - pub fn map_or_else<U, D: FnOnce(E) -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn map_or_else<U, D, F>(self, default: D, f: F) -> U + where + D: [const] FnOnce(E) -> U + [const] Destruct, + F: [const] FnOnce(T) -> U + [const] Destruct, + { match self { Ok(t) => f(t), Err(e) => default(e), @@ -877,10 +916,13 @@ impl<T, E> Result<T, E> { /// [default value]: Default::default #[inline] #[unstable(feature = "result_option_map_or_default", issue = "138099")] - pub fn map_or_default<U, F>(self, f: F) -> U + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn map_or_default<U, F>(self, f: F) -> U where - U: Default, - F: FnOnce(T) -> U, + F: [const] FnOnce(T) -> U + [const] Destruct, + U: [const] Default, + T: [const] Destruct, + E: [const] Destruct, { match self { Ok(t) => f(t), @@ -908,7 +950,11 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn map_err<F, O>(self, op: O) -> Result<T, F> + where + O: [const] FnOnce(E) -> F + [const] Destruct, + { match self { Ok(t) => Ok(t), Err(e) => Err(op(e)), @@ -930,7 +976,11 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "result_option_inspect", since = "1.76.0")] - pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn inspect<F>(self, f: F) -> Self + where + F: [const] FnOnce(&T) + [const] Destruct, + { if let Ok(ref t) = self { f(t); } @@ -954,7 +1004,11 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "result_option_inspect", since = "1.76.0")] - pub fn inspect_err<F: FnOnce(&E)>(self, f: F) -> Self { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn inspect_err<F>(self, f: F) -> Self + where + F: [const] FnOnce(&E) + [const] Destruct, + { if let Err(ref e) = self { f(e); } @@ -1033,7 +1087,8 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter(&self) -> Iter<'_, T> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn iter(&self) -> Iter<'_, T> { Iter { inner: self.as_ref().ok() } } @@ -1056,7 +1111,8 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter_mut(&mut self) -> IterMut<'_, T> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn iter_mut(&mut self) -> IterMut<'_, T> { IterMut { inner: self.as_mut().ok() } } @@ -1195,9 +1251,11 @@ impl<T, E> Result<T, E> { /// [`FromStr`]: crate::str::FromStr #[inline] #[stable(feature = "result_unwrap_or_default", since = "1.16.0")] - pub fn unwrap_or_default(self) -> T + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn unwrap_or_default(self) -> T where - T: Default, + T: [const] Default + [const] Destruct, + E: [const] Destruct, { match self { Ok(x) => x, @@ -1292,7 +1350,7 @@ impl<T, E> Result<T, E> { #[rustc_const_unstable(feature = "const_try", issue = "74935")] pub const fn into_ok(self) -> T where - E: ~const Into<!>, + E: [const] Into<!>, { match self { Ok(x) => x, @@ -1329,7 +1387,7 @@ impl<T, E> Result<T, E> { #[rustc_const_unstable(feature = "const_try", issue = "74935")] pub const fn into_err(self) -> E where - T: ~const Into<!>, + T: [const] Into<!>, { match self { Ok(x) => x.into(), @@ -1370,7 +1428,13 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn and<U>(self, res: Result<U, E>) -> Result<U, E> + where + T: [const] Destruct, + E: [const] Destruct, + U: [const] Destruct, + { match self { Ok(_) => res, Err(e) => Err(e), @@ -1409,8 +1473,12 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] #[rustc_confusables("flat_map", "flatmap")] - pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> { + pub const fn and_then<U, F>(self, op: F) -> Result<U, E> + where + F: [const] FnOnce(T) -> Result<U, E> + [const] Destruct, + { match self { Ok(t) => op(t), Err(e) => Err(e), @@ -1446,7 +1514,13 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn or<F>(self, res: Result<T, F>) -> Result<T, F> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn or<F>(self, res: Result<T, F>) -> Result<T, F> + where + T: [const] Destruct, + E: [const] Destruct, + F: [const] Destruct, + { match self { Ok(v) => Ok(v), Err(_) => res, @@ -1471,7 +1545,11 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn or_else<F, O>(self, op: O) -> Result<T, F> + where + O: [const] FnOnce(E) -> Result<T, F> + [const] Destruct, + { match self { Ok(t) => Ok(t), Err(e) => op(e), @@ -1498,7 +1576,12 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_or(self, default: T) -> T { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn unwrap_or(self, default: T) -> T + where + T: [const] Destruct, + E: [const] Destruct, + { match self { Ok(t) => t, Err(_) => default, @@ -1519,7 +1602,11 @@ impl<T, E> Result<T, E> { #[inline] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn unwrap_or_else<F>(self, op: F) -> T + where + F: [const] FnOnce(E) -> T + [const] Destruct, + { match self { Ok(t) => t, Err(e) => op(e), @@ -1544,7 +1631,7 @@ impl<T, E> Result<T, E> { /// /// ```no_run /// let x: Result<u32, &str> = Err("emergency failure"); - /// unsafe { x.unwrap_unchecked(); } // Undefined behavior! + /// unsafe { x.unwrap_unchecked() }; // Undefined behavior! /// ``` #[inline] #[track_caller] @@ -1762,7 +1849,7 @@ impl<T, E> Result<Result<T, E>, E> { #[cold] #[track_caller] fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! { - panic!("{msg}: {error:?}") + panic!("{msg}: {error:?}"); } // This is a separate function to avoid constructing a `dyn Debug` @@ -1773,7 +1860,7 @@ fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! { #[inline] #[cold] #[track_caller] -fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! { +const fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! { panic!() } @@ -2077,7 +2164,7 @@ impl<T, E> const ops::Try for Result<T, E> { #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] #[rustc_const_unstable(feature = "const_try", issue = "74935")] -impl<T, E, F: ~const From<E>> const ops::FromResidual<Result<convert::Infallible, E>> +impl<T, E, F: [const] From<E>> const ops::FromResidual<Result<convert::Infallible, E>> for Result<T, F> { #[inline] @@ -2091,7 +2178,7 @@ impl<T, E, F: ~const From<E>> const ops::FromResidual<Result<convert::Infallible #[diagnostic::do_not_recommend] #[unstable(feature = "try_trait_v2_yeet", issue = "96374")] #[rustc_const_unstable(feature = "const_try", issue = "74935")] -impl<T, E, F: ~const From<E>> const ops::FromResidual<ops::Yeet<E>> for Result<T, F> { +impl<T, E, F: [const] From<E>> const ops::FromResidual<ops::Yeet<E>> for Result<T, F> { #[inline] fn from_residual(ops::Yeet(e): ops::Yeet<E>) -> Self { Err(From::from(e)) diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 1eda8bc1bec..68bd12aa7bf 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -11,7 +11,7 @@ use crate::ops::ControlFlow; #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl<T, U> const PartialEq<[U]> for [T] where - T: ~const PartialEq<U>, + T: [const] PartialEq<U>, { fn eq(&self, other: &[U]) -> bool { SlicePartialEq::equal(self, other) @@ -109,7 +109,7 @@ trait SlicePartialEq<B> { #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl<A, B> const SlicePartialEq<B> for [A] where - A: ~const PartialEq<B>, + A: [const] PartialEq<B>, { default fn equal(&self, other: &[B]) -> bool { if self.len() != other.len() { @@ -138,7 +138,7 @@ where #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl<A, B> const SlicePartialEq<B> for [A] where - A: ~const BytewiseEq<B>, + A: [const] BytewiseEq<B>, { fn equal(&self, other: &[B]) -> bool { if self.len() != other.len() { diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 322b3580ede..ae360df80f6 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -9,7 +9,7 @@ use crate::{ops, range}; #[rustc_const_unstable(feature = "const_index", issue = "143775")] impl<T, I> const ops::Index<I> for [T] where - I: ~const SliceIndex<[T]>, + I: [const] SliceIndex<[T]>, { type Output = I::Output; @@ -23,7 +23,7 @@ where #[rustc_const_unstable(feature = "const_index", issue = "143775")] impl<T, I> const ops::IndexMut<I> for [T] where - I: ~const SliceIndex<[T]>, + I: [const] SliceIndex<[T]>, { #[inline(always)] fn index_mut(&mut self, index: I) -> &mut I::Output { diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 33132dcc714..ae910e05252 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2301,255 +2301,6 @@ impl<T, const N: usize> ExactSizeIterator for ArrayWindows<'_, T, N> { } } -/// An iterator over a slice in (non-overlapping) chunks (`N` elements at a -/// time), starting at the beginning of the slice. -/// -/// When the slice len is not evenly divided by the chunk size, the last -/// up to `N-1` elements will be omitted but can be retrieved from -/// the [`remainder`] function from the iterator. -/// -/// This struct is created by the [`array_chunks`] method on [slices]. -/// -/// # Example -/// -/// ``` -/// #![feature(array_chunks)] -/// -/// let slice = ['l', 'o', 'r', 'e', 'm']; -/// let mut iter = slice.array_chunks::<2>(); -/// assert_eq!(iter.next(), Some(&['l', 'o'])); -/// assert_eq!(iter.next(), Some(&['r', 'e'])); -/// assert_eq!(iter.next(), None); -/// ``` -/// -/// [`array_chunks`]: slice::array_chunks -/// [`remainder`]: ArrayChunks::remainder -/// [slices]: slice -#[derive(Debug)] -#[unstable(feature = "array_chunks", issue = "74985")] -#[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct ArrayChunks<'a, T: 'a, const N: usize> { - iter: Iter<'a, [T; N]>, - rem: &'a [T], -} - -impl<'a, T, const N: usize> ArrayChunks<'a, T, N> { - #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] - #[inline] - pub(super) const fn new(slice: &'a [T]) -> Self { - let (array_slice, rem) = slice.as_chunks(); - Self { iter: array_slice.iter(), rem } - } - - /// Returns the remainder of the original slice that is not going to be - /// returned by the iterator. The returned slice has at most `N-1` - /// elements. - #[must_use] - #[unstable(feature = "array_chunks", issue = "74985")] - pub fn remainder(&self) -> &'a [T] { - self.rem - } -} - -// FIXME(#26925) Remove in favor of `#[derive(Clone)]` -#[unstable(feature = "array_chunks", issue = "74985")] -impl<T, const N: usize> Clone for ArrayChunks<'_, T, N> { - fn clone(&self) -> Self { - ArrayChunks { iter: self.iter.clone(), rem: self.rem } - } -} - -#[unstable(feature = "array_chunks", issue = "74985")] -impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> { - type Item = &'a [T; N]; - - #[inline] - fn next(&mut self) -> Option<&'a [T; N]> { - self.iter.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } - - #[inline] - fn count(self) -> usize { - self.iter.count() - } - - #[inline] - fn nth(&mut self, n: usize) -> Option<Self::Item> { - self.iter.nth(n) - } - - #[inline] - fn last(self) -> Option<Self::Item> { - self.iter.last() - } - - unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> &'a [T; N] { - // SAFETY: The safety guarantees of `__iterator_get_unchecked` are - // transferred to the caller. - unsafe { self.iter.__iterator_get_unchecked(i) } - } -} - -#[unstable(feature = "array_chunks", issue = "74985")] -impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunks<'a, T, N> { - #[inline] - fn next_back(&mut self) -> Option<&'a [T; N]> { - self.iter.next_back() - } - - #[inline] - fn nth_back(&mut self, n: usize) -> Option<Self::Item> { - self.iter.nth_back(n) - } -} - -#[unstable(feature = "array_chunks", issue = "74985")] -impl<T, const N: usize> ExactSizeIterator for ArrayChunks<'_, T, N> { - fn is_empty(&self) -> bool { - self.iter.is_empty() - } -} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl<T, const N: usize> TrustedLen for ArrayChunks<'_, T, N> {} - -#[unstable(feature = "array_chunks", issue = "74985")] -impl<T, const N: usize> FusedIterator for ArrayChunks<'_, T, N> {} - -#[doc(hidden)] -#[unstable(feature = "array_chunks", issue = "74985")] -unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunks<'a, T, N> {} - -#[doc(hidden)] -#[unstable(feature = "array_chunks", issue = "74985")] -unsafe impl<'a, T, const N: usize> TrustedRandomAccessNoCoerce for ArrayChunks<'a, T, N> { - const MAY_HAVE_SIDE_EFFECT: bool = false; -} - -/// An iterator over a slice in (non-overlapping) mutable chunks (`N` elements -/// at a time), starting at the beginning of the slice. -/// -/// When the slice len is not evenly divided by the chunk size, the last -/// up to `N-1` elements will be omitted but can be retrieved from -/// the [`into_remainder`] function from the iterator. -/// -/// This struct is created by the [`array_chunks_mut`] method on [slices]. -/// -/// # Example -/// -/// ``` -/// #![feature(array_chunks)] -/// -/// let mut slice = ['l', 'o', 'r', 'e', 'm']; -/// let iter = slice.array_chunks_mut::<2>(); -/// ``` -/// -/// [`array_chunks_mut`]: slice::array_chunks_mut -/// [`into_remainder`]: ../../std/slice/struct.ArrayChunksMut.html#method.into_remainder -/// [slices]: slice -#[derive(Debug)] -#[unstable(feature = "array_chunks", issue = "74985")] -#[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct ArrayChunksMut<'a, T: 'a, const N: usize> { - iter: IterMut<'a, [T; N]>, - rem: &'a mut [T], -} - -impl<'a, T, const N: usize> ArrayChunksMut<'a, T, N> { - #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] - #[inline] - pub(super) const fn new(slice: &'a mut [T]) -> Self { - let (array_slice, rem) = slice.as_chunks_mut(); - Self { iter: array_slice.iter_mut(), rem } - } - - /// Returns the remainder of the original slice that is not going to be - /// returned by the iterator. The returned slice has at most `N-1` - /// elements. - #[must_use = "`self` will be dropped if the result is not used"] - #[unstable(feature = "array_chunks", issue = "74985")] - pub fn into_remainder(self) -> &'a mut [T] { - self.rem - } -} - -#[unstable(feature = "array_chunks", issue = "74985")] -impl<'a, T, const N: usize> Iterator for ArrayChunksMut<'a, T, N> { - type Item = &'a mut [T; N]; - - #[inline] - fn next(&mut self) -> Option<&'a mut [T; N]> { - self.iter.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } - - #[inline] - fn count(self) -> usize { - self.iter.count() - } - - #[inline] - fn nth(&mut self, n: usize) -> Option<Self::Item> { - self.iter.nth(n) - } - - #[inline] - fn last(self) -> Option<Self::Item> { - self.iter.last() - } - - unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> &'a mut [T; N] { - // SAFETY: The safety guarantees of `__iterator_get_unchecked` are transferred to - // the caller. - unsafe { self.iter.__iterator_get_unchecked(i) } - } -} - -#[unstable(feature = "array_chunks", issue = "74985")] -impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunksMut<'a, T, N> { - #[inline] - fn next_back(&mut self) -> Option<&'a mut [T; N]> { - self.iter.next_back() - } - - #[inline] - fn nth_back(&mut self, n: usize) -> Option<Self::Item> { - self.iter.nth_back(n) - } -} - -#[unstable(feature = "array_chunks", issue = "74985")] -impl<T, const N: usize> ExactSizeIterator for ArrayChunksMut<'_, T, N> { - fn is_empty(&self) -> bool { - self.iter.is_empty() - } -} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl<T, const N: usize> TrustedLen for ArrayChunksMut<'_, T, N> {} - -#[unstable(feature = "array_chunks", issue = "74985")] -impl<T, const N: usize> FusedIterator for ArrayChunksMut<'_, T, N> {} - -#[doc(hidden)] -#[unstable(feature = "array_chunks", issue = "74985")] -unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunksMut<'a, T, N> {} - -#[doc(hidden)] -#[unstable(feature = "array_chunks", issue = "74985")] -unsafe impl<'a, T, const N: usize> TrustedRandomAccessNoCoerce for ArrayChunksMut<'a, T, N> { - const MAY_HAVE_SIDE_EFFECT: bool = false; -} - /// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a /// time), starting at the end of the slice. /// diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 6fe5affc48b..64f5b5dd831 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -52,8 +52,6 @@ pub use index::SliceIndex; pub use index::{range, try_range}; #[unstable(feature = "array_windows", issue = "75027")] pub use iter::ArrayWindows; -#[unstable(feature = "array_chunks", issue = "74985")] -pub use iter::{ArrayChunks, ArrayChunksMut}; #[stable(feature = "slice_group_by", since = "1.77.0")] pub use iter::{ChunkBy, ChunkByMut}; #[stable(feature = "rust1", since = "1.0.0")] @@ -571,7 +569,7 @@ impl<T> [T] { #[rustc_const_unstable(feature = "const_index", issue = "143775")] pub const fn get<I>(&self, index: I) -> Option<&I::Output> where - I: ~const SliceIndex<Self>, + I: [const] SliceIndex<Self>, { index.get(self) } @@ -598,7 +596,7 @@ impl<T> [T] { #[rustc_const_unstable(feature = "const_index", issue = "143775")] pub const fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output> where - I: ~const SliceIndex<Self>, + I: [const] SliceIndex<Self>, { index.get_mut(self) } @@ -638,7 +636,7 @@ impl<T> [T] { #[rustc_const_unstable(feature = "const_index", issue = "143775")] pub const unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output where - I: ~const SliceIndex<Self>, + I: [const] SliceIndex<Self>, { // SAFETY: the caller must uphold most of the safety requirements for `get_unchecked`; // the slice is dereferenceable because `self` is a safe reference. @@ -683,7 +681,7 @@ impl<T> [T] { #[rustc_const_unstable(feature = "const_index", issue = "143775")] pub const unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output where - I: ~const SliceIndex<Self>, + I: [const] SliceIndex<Self>, { // SAFETY: the caller must uphold the safety requirements for `get_unchecked_mut`; // the slice is dereferenceable because `self` is a safe reference. @@ -971,7 +969,7 @@ impl<T> [T] { /// assert!(v == [3, 2, 1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_slice_reverse", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_reverse", since = "1.90.0")] #[inline] pub const fn reverse(&mut self) { let half_len = self.len() / 2; @@ -1232,7 +1230,7 @@ impl<T> [T] { /// /// [`chunks`]: slice::chunks /// [`rchunks_exact`]: slice::rchunks_exact - /// [`as_chunks`]: slice::chunks + /// [`as_chunks`]: slice::as_chunks #[stable(feature = "chunks_exact", since = "1.31.0")] #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] #[inline] @@ -1448,42 +1446,6 @@ impl<T> [T] { (remainder, array_slice) } - /// Returns an iterator over `N` elements of the slice at a time, starting at the - /// beginning of the slice. - /// - /// The chunks are array references and do not overlap. If `N` does not divide the - /// length of the slice, then the last up to `N-1` elements will be omitted and can be - /// retrieved from the `remainder` function of the iterator. - /// - /// This method is the const generic equivalent of [`chunks_exact`]. - /// - /// # Panics - /// - /// Panics if `N` is zero. This check will most probably get changed to a compile time - /// error before this method gets stabilized. - /// - /// # Examples - /// - /// ``` - /// #![feature(array_chunks)] - /// let slice = ['l', 'o', 'r', 'e', 'm']; - /// let mut iter = slice.array_chunks(); - /// assert_eq!(iter.next().unwrap(), &['l', 'o']); - /// assert_eq!(iter.next().unwrap(), &['r', 'e']); - /// assert!(iter.next().is_none()); - /// assert_eq!(iter.remainder(), &['m']); - /// ``` - /// - /// [`chunks_exact`]: slice::chunks_exact - #[unstable(feature = "array_chunks", issue = "74985")] - #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] - #[inline] - #[track_caller] - pub const fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> { - assert!(N != 0, "chunk size must be non-zero"); - ArrayChunks::new(self) - } - /// Splits the slice into a slice of `N`-element arrays, /// assuming that there's no remainder. /// @@ -1646,44 +1608,6 @@ impl<T> [T] { (remainder, array_slice) } - /// Returns an iterator over `N` elements of the slice at a time, starting at the - /// beginning of the slice. - /// - /// The chunks are mutable array references and do not overlap. If `N` does not divide - /// the length of the slice, then the last up to `N-1` elements will be omitted and - /// can be retrieved from the `into_remainder` function of the iterator. - /// - /// This method is the const generic equivalent of [`chunks_exact_mut`]. - /// - /// # Panics - /// - /// Panics if `N` is zero. This check will most probably get changed to a compile time - /// error before this method gets stabilized. - /// - /// # Examples - /// - /// ``` - /// #![feature(array_chunks)] - /// let v = &mut [0, 0, 0, 0, 0]; - /// let mut count = 1; - /// - /// for chunk in v.array_chunks_mut() { - /// *chunk = [count; 2]; - /// count += 1; - /// } - /// assert_eq!(v, &[1, 1, 2, 2, 0]); - /// ``` - /// - /// [`chunks_exact_mut`]: slice::chunks_exact_mut - #[unstable(feature = "array_chunks", issue = "74985")] - #[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")] - #[inline] - #[track_caller] - pub const fn array_chunks_mut<const N: usize>(&mut self) -> ArrayChunksMut<'_, T, N> { - assert!(N != 0, "chunk size must be non-zero"); - ArrayChunksMut::new(self) - } - /// Returns an iterator over overlapping windows of `N` elements of a slice, /// starting at the beginning of the slice. /// @@ -4050,8 +3974,9 @@ impl<T> [T] { /// /// [`split_at_mut`]: slice::split_at_mut #[stable(feature = "swap_with_slice", since = "1.27.0")] + #[rustc_const_unstable(feature = "const_swap_with_slice", issue = "142204")] #[track_caller] - pub fn swap_with_slice(&mut self, other: &mut [T]) { + pub const fn swap_with_slice(&mut self, other: &mut [T]) { assert!(self.len() == other.len(), "destination and source slices have different lengths"); // SAFETY: `self` is valid for `self.len()` elements by definition, and `src` was // checked to have the same length. The slices cannot overlap because diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index bcf886484ad..d2985d8a186 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -52,7 +52,7 @@ impl<'a> Iterator for Chars<'a> { const CHUNK_SIZE: usize = 32; if remainder >= CHUNK_SIZE { - let mut chunks = self.iter.as_slice().array_chunks::<CHUNK_SIZE>(); + let mut chunks = self.iter.as_slice().as_chunks::<CHUNK_SIZE>().0.iter(); let mut bytes_skipped: usize = 0; while remainder > CHUNK_SIZE diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index c40af4de7e0..1b6e84175b9 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -603,7 +603,7 @@ impl str { #[stable(feature = "str_checked_slicing", since = "1.20.0")] #[rustc_const_unstable(feature = "const_index", issue = "143775")] #[inline] - pub const fn get<I: ~const SliceIndex<str>>(&self, i: I) -> Option<&I::Output> { + pub const fn get<I: [const] SliceIndex<str>>(&self, i: I) -> Option<&I::Output> { i.get(self) } @@ -636,7 +636,7 @@ impl str { #[stable(feature = "str_checked_slicing", since = "1.20.0")] #[rustc_const_unstable(feature = "const_index", issue = "143775")] #[inline] - pub const fn get_mut<I: ~const SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> { + pub const fn get_mut<I: [const] SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> { i.get_mut(self) } diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index bcbbb11c83b..e116b138383 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -996,7 +996,10 @@ impl<'b> Pattern for &'b str { return haystack.as_bytes().contains(&self.as_bytes()[0]); } - #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] + #[cfg(any( + all(target_arch = "x86_64", target_feature = "sse2"), + all(target_arch = "loongarch64", target_feature = "lsx") + ))] if self.len() <= 32 { if let Some(result) = simd_contains(self, haystack) { return result; @@ -1770,11 +1773,18 @@ impl TwoWayStrategy for RejectAndMatch { /// If we ever ship std with for x86-64-v3 or adapt this for other platforms then wider vectors /// should be evaluated. /// +/// Similarly, on LoongArch the 128-bit LSX vector extension is the baseline, +/// so we also use `u8x16` there. Wider vector widths may be considered +/// for future LoongArch extensions (e.g., LASX). +/// /// For haystacks smaller than vector-size + needle length it falls back to /// a naive O(n*m) search so this implementation should not be called on larger needles. /// /// [0]: http://0x80.pl/articles/simd-strfind.html#sse-avx2 -#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] +#[cfg(any( + all(target_arch = "x86_64", target_feature = "sse2"), + all(target_arch = "loongarch64", target_feature = "lsx") +))] #[inline] fn simd_contains(needle: &str, haystack: &str) -> Option<bool> { let needle = needle.as_bytes(); @@ -1906,7 +1916,10 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> { /// # Safety /// /// Both slices must have the same length. -#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] // only called on x86 +#[cfg(any( + all(target_arch = "x86_64", target_feature = "sse2"), + all(target_arch = "loongarch64", target_feature = "lsx") +))] #[inline] unsafe fn small_slice_eq(x: &[u8], y: &[u8]) -> bool { debug_assert_eq!(x.len(), y.len()); diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 1597d1c1fa8..dc88f35eca7 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -53,7 +53,7 @@ impl PartialOrd for str { #[rustc_const_unstable(feature = "const_index", issue = "143775")] impl<I> const ops::Index<I> for str where - I: ~const SliceIndex<str>, + I: [const] SliceIndex<str>, { type Output = I::Output; @@ -67,7 +67,7 @@ where #[rustc_const_unstable(feature = "const_index", issue = "143775")] impl<I> const ops::IndexMut<I> for str where - I: ~const SliceIndex<str>, + I: [const] SliceIndex<str>, { #[inline] fn index_mut(&mut self, index: I) -> &mut I::Output { diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 57bea505433..44a6895f90a 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1245,8 +1245,8 @@ impl AtomicBool { /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the /// atomic types work with interior mutability. All modifications of an atomic change the value /// through a shared reference, and can do so safely as long as they use atomic operations. Any - /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same - /// restriction in [Memory model for atomic accesses]. + /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the + /// requirements of the [memory model]. /// /// # Examples /// @@ -1265,7 +1265,7 @@ impl AtomicBool { /// # } /// ``` /// - /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + /// [memory model]: self#memory-model-for-atomic-accesses #[inline] #[stable(feature = "atomic_as_ptr", since = "1.70.0")] #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] @@ -2293,7 +2293,7 @@ impl<T> AtomicPtr<T> { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_add(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() } + unsafe { atomic_add(self.p.get(), val, order).cast() } } /// Offsets the pointer's address by subtracting `val` *bytes*, returning the @@ -2318,9 +2318,10 @@ impl<T> AtomicPtr<T> { /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// - /// let atom = AtomicPtr::<i64>::new(core::ptr::without_provenance_mut(1)); - /// assert_eq!(atom.fetch_byte_sub(1, Ordering::Relaxed).addr(), 1); - /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 0); + /// let mut arr = [0i64, 1]; + /// let atom = AtomicPtr::<i64>::new(&raw mut arr[1]); + /// assert_eq!(atom.fetch_byte_sub(8, Ordering::Relaxed).addr(), (&raw const arr[1]).addr()); + /// assert_eq!(atom.load(Ordering::Relaxed).addr(), (&raw const arr[0]).addr()); /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] @@ -2328,7 +2329,7 @@ impl<T> AtomicPtr<T> { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_sub(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() } + unsafe { atomic_sub(self.p.get(), val, order).cast() } } /// Performs a bitwise "or" operation on the address of the current pointer, @@ -2379,7 +2380,7 @@ impl<T> AtomicPtr<T> { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_or(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() } + unsafe { atomic_or(self.p.get(), val, order).cast() } } /// Performs a bitwise "and" operation on the address of the current @@ -2429,7 +2430,7 @@ impl<T> AtomicPtr<T> { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_and(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() } + unsafe { atomic_and(self.p.get(), val, order).cast() } } /// Performs a bitwise "xor" operation on the address of the current @@ -2477,7 +2478,7 @@ impl<T> AtomicPtr<T> { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_xor(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() } + unsafe { atomic_xor(self.p.get(), val, order).cast() } } /// Returns a mutable pointer to the underlying pointer. @@ -2489,8 +2490,8 @@ impl<T> AtomicPtr<T> { /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the /// atomic types work with interior mutability. All modifications of an atomic change the value /// through a shared reference, and can do so safely as long as they use atomic operations. Any - /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same - /// restriction in [Memory model for atomic accesses]. + /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the + /// requirements of the [memory model]. /// /// # Examples /// @@ -2510,7 +2511,7 @@ impl<T> AtomicPtr<T> { /// } /// ``` /// - /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + /// [memory model]: self#memory-model-for-atomic-accesses #[inline] #[stable(feature = "atomic_as_ptr", since = "1.70.0")] #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] @@ -3623,8 +3624,8 @@ macro_rules! atomic_int { /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the /// atomic types work with interior mutability. All modifications of an atomic change the value /// through a shared reference, and can do so safely as long as they use atomic operations. Any - /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same - /// restriction in [Memory model for atomic accesses]. + /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the + /// requirements of the [memory model]. /// /// # Examples /// @@ -3645,7 +3646,7 @@ macro_rules! atomic_int { /// # } /// ``` /// - /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + /// [memory model]: self#memory-model-for-atomic-accesses #[inline] #[stable(feature = "atomic_as_ptr", since = "1.70.0")] #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] @@ -3981,15 +3982,15 @@ unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_add<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_add`. unsafe { match order { - Relaxed => intrinsics::atomic_xadd::<T, { AO::Relaxed }>(dst, val), - Acquire => intrinsics::atomic_xadd::<T, { AO::Acquire }>(dst, val), - Release => intrinsics::atomic_xadd::<T, { AO::Release }>(dst, val), - AcqRel => intrinsics::atomic_xadd::<T, { AO::AcqRel }>(dst, val), - SeqCst => intrinsics::atomic_xadd::<T, { AO::SeqCst }>(dst, val), + Relaxed => intrinsics::atomic_xadd::<T, U, { AO::Relaxed }>(dst, val), + Acquire => intrinsics::atomic_xadd::<T, U, { AO::Acquire }>(dst, val), + Release => intrinsics::atomic_xadd::<T, U, { AO::Release }>(dst, val), + AcqRel => intrinsics::atomic_xadd::<T, U, { AO::AcqRel }>(dst, val), + SeqCst => intrinsics::atomic_xadd::<T, U, { AO::SeqCst }>(dst, val), } } } @@ -3998,15 +3999,15 @@ unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_sub<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_sub`. unsafe { match order { - Relaxed => intrinsics::atomic_xsub::<T, { AO::Relaxed }>(dst, val), - Acquire => intrinsics::atomic_xsub::<T, { AO::Acquire }>(dst, val), - Release => intrinsics::atomic_xsub::<T, { AO::Release }>(dst, val), - AcqRel => intrinsics::atomic_xsub::<T, { AO::AcqRel }>(dst, val), - SeqCst => intrinsics::atomic_xsub::<T, { AO::SeqCst }>(dst, val), + Relaxed => intrinsics::atomic_xsub::<T, U, { AO::Relaxed }>(dst, val), + Acquire => intrinsics::atomic_xsub::<T, U, { AO::Acquire }>(dst, val), + Release => intrinsics::atomic_xsub::<T, U, { AO::Release }>(dst, val), + AcqRel => intrinsics::atomic_xsub::<T, U, { AO::AcqRel }>(dst, val), + SeqCst => intrinsics::atomic_xsub::<T, U, { AO::SeqCst }>(dst, val), } } } @@ -4147,15 +4148,15 @@ unsafe fn atomic_compare_exchange_weak<T: Copy>( #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_and<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_and` unsafe { match order { - Relaxed => intrinsics::atomic_and::<T, { AO::Relaxed }>(dst, val), - Acquire => intrinsics::atomic_and::<T, { AO::Acquire }>(dst, val), - Release => intrinsics::atomic_and::<T, { AO::Release }>(dst, val), - AcqRel => intrinsics::atomic_and::<T, { AO::AcqRel }>(dst, val), - SeqCst => intrinsics::atomic_and::<T, { AO::SeqCst }>(dst, val), + Relaxed => intrinsics::atomic_and::<T, U, { AO::Relaxed }>(dst, val), + Acquire => intrinsics::atomic_and::<T, U, { AO::Acquire }>(dst, val), + Release => intrinsics::atomic_and::<T, U, { AO::Release }>(dst, val), + AcqRel => intrinsics::atomic_and::<T, U, { AO::AcqRel }>(dst, val), + SeqCst => intrinsics::atomic_and::<T, U, { AO::SeqCst }>(dst, val), } } } @@ -4163,15 +4164,15 @@ unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_nand<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_nand` unsafe { match order { - Relaxed => intrinsics::atomic_nand::<T, { AO::Relaxed }>(dst, val), - Acquire => intrinsics::atomic_nand::<T, { AO::Acquire }>(dst, val), - Release => intrinsics::atomic_nand::<T, { AO::Release }>(dst, val), - AcqRel => intrinsics::atomic_nand::<T, { AO::AcqRel }>(dst, val), - SeqCst => intrinsics::atomic_nand::<T, { AO::SeqCst }>(dst, val), + Relaxed => intrinsics::atomic_nand::<T, U, { AO::Relaxed }>(dst, val), + Acquire => intrinsics::atomic_nand::<T, U, { AO::Acquire }>(dst, val), + Release => intrinsics::atomic_nand::<T, U, { AO::Release }>(dst, val), + AcqRel => intrinsics::atomic_nand::<T, U, { AO::AcqRel }>(dst, val), + SeqCst => intrinsics::atomic_nand::<T, U, { AO::SeqCst }>(dst, val), } } } @@ -4179,15 +4180,15 @@ unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_or<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_or` unsafe { match order { - SeqCst => intrinsics::atomic_or::<T, { AO::SeqCst }>(dst, val), - Acquire => intrinsics::atomic_or::<T, { AO::Acquire }>(dst, val), - Release => intrinsics::atomic_or::<T, { AO::Release }>(dst, val), - AcqRel => intrinsics::atomic_or::<T, { AO::AcqRel }>(dst, val), - Relaxed => intrinsics::atomic_or::<T, { AO::Relaxed }>(dst, val), + SeqCst => intrinsics::atomic_or::<T, U, { AO::SeqCst }>(dst, val), + Acquire => intrinsics::atomic_or::<T, U, { AO::Acquire }>(dst, val), + Release => intrinsics::atomic_or::<T, U, { AO::Release }>(dst, val), + AcqRel => intrinsics::atomic_or::<T, U, { AO::AcqRel }>(dst, val), + Relaxed => intrinsics::atomic_or::<T, U, { AO::Relaxed }>(dst, val), } } } @@ -4195,15 +4196,15 @@ unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_xor<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_xor` unsafe { match order { - SeqCst => intrinsics::atomic_xor::<T, { AO::SeqCst }>(dst, val), - Acquire => intrinsics::atomic_xor::<T, { AO::Acquire }>(dst, val), - Release => intrinsics::atomic_xor::<T, { AO::Release }>(dst, val), - AcqRel => intrinsics::atomic_xor::<T, { AO::AcqRel }>(dst, val), - Relaxed => intrinsics::atomic_xor::<T, { AO::Relaxed }>(dst, val), + SeqCst => intrinsics::atomic_xor::<T, U, { AO::SeqCst }>(dst, val), + Acquire => intrinsics::atomic_xor::<T, U, { AO::Acquire }>(dst, val), + Release => intrinsics::atomic_xor::<T, U, { AO::Release }>(dst, val), + AcqRel => intrinsics::atomic_xor::<T, U, { AO::AcqRel }>(dst, val), + Relaxed => intrinsics::atomic_xor::<T, U, { AO::Relaxed }>(dst, val), } } } | 
