diff --git a/alloc/src/collections/btree/map.rs b/alloc/src/collections/btree/map.rs index acbbb6df9a5a5..c4e599222e501 100644 --- a/alloc/src/collections/btree/map.rs +++ b/alloc/src/collections/btree/map.rs @@ -135,6 +135,8 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; /// ]); /// ``` /// +/// ## `Entry` API +/// /// `BTreeMap` implements an [`Entry API`], which allows for complex /// methods of getting, setting, updating and removing keys and their values: /// diff --git a/alloc/src/vec/mod.rs b/alloc/src/vec/mod.rs index 2321aab2c516e..8001faf9d20a5 100644 --- a/alloc/src/vec/mod.rs +++ b/alloc/src/vec/mod.rs @@ -49,7 +49,27 @@ //! v[1] = v[1] + 5; //! ``` //! +//! # Memory layout +//! +//! When the type is non-zero-sized and the capacity is nonzero, [`Vec`] uses the [`Global`] +//! allocator for its allocation. It is valid to convert both ways between such a [`Vec`] and a raw +//! pointer allocated with the [`Global`] allocator, provided that the [`Layout`] used with the +//! allocator is correct for a sequence of `capacity` elements of the type, and the first `len` +//! values pointed to by the raw pointer are valid. More precisely, a `ptr: *mut T` that has been +//! allocated with the [`Global`] allocator with [`Layout::array::(capacity)`][Layout::array] may +//! be converted into a vec using +//! [`Vec::::from_raw_parts(ptr, len, capacity)`](Vec::from_raw_parts). Conversely, the memory +//! backing a `value: *mut T` obtained from [`Vec::::as_mut_ptr`] may be deallocated using the +//! [`Global`] allocator with the same layout. +//! +//! For zero-sized types (ZSTs), or when the capacity is zero, the `Vec` pointer must be non-null +//! and sufficiently aligned. The recommended way to build a `Vec` of ZSTs if [`vec!`] cannot be +//! used is to use [`ptr::NonNull::dangling`]. +//! //! [`push`]: Vec::push +//! [`ptr::NonNull::dangling`]: NonNull::dangling +//! [`Layout`]: crate::alloc::Layout +//! [Layout::array]: crate::alloc::Layout::array #![stable(feature = "rust1", since = "1.0.0")] @@ -523,18 +543,23 @@ impl Vec { /// This is highly unsafe, due to the number of invariants that aren't /// checked: /// - /// * `ptr` must have been allocated using the global allocator, such as via - /// the [`alloc::alloc`] function. - /// * `T` needs to have the same alignment as what `ptr` was allocated with. + /// * If `T` is not a zero-sized type and the capacity is nonzero, `ptr` must have + /// been allocated using the global allocator, such as via the [`alloc::alloc`] + /// function. If `T` is a zero-sized type or the capacity is zero, `ptr` need + /// only be non-null and aligned. + /// * `T` needs to have the same alignment as what `ptr` was allocated with, + /// if the pointer is required to be allocated. /// (`T` having a less strict alignment is not sufficient, the alignment really /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be /// allocated and deallocated with the same layout.) - /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs - /// to be the same size as the pointer was allocated with. (Because similar to - /// alignment, [`dealloc`] must be called with the same layout `size`.) + /// * The size of `T` times the `capacity` (ie. the allocated size in bytes), if + /// nonzero, needs to be the same size as the pointer was allocated with. + /// (Because similar to alignment, [`dealloc`] must be called with the same + /// layout `size`.) /// * `length` needs to be less than or equal to `capacity`. /// * The first `length` values must be properly initialized values of type `T`. - /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// * `capacity` needs to be the capacity that the pointer was allocated with, + /// if the pointer is required to be allocated. /// * The allocated size in bytes must be no larger than `isize::MAX`. /// See the safety documentation of [`pointer::offset`]. /// @@ -770,12 +795,16 @@ impl Vec { /// order as the arguments to [`from_raw_parts`]. /// /// After calling this function, the caller is responsible for the - /// memory previously managed by the `Vec`. The only way to do - /// this is to convert the raw pointer, length, and capacity back - /// into a `Vec` with the [`from_raw_parts`] function, allowing - /// the destructor to perform the cleanup. + /// memory previously managed by the `Vec`. Most often, one does + /// this by converting the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts`] function; more generally, + /// if `T` is non-zero-sized and the capacity is nonzero, one may use + /// any method that calls [`dealloc`] with a layout of + /// `Layout::array::(capacity)`; if `T` is zero-sized or the + /// capacity is zero, nothing needs to be done. /// /// [`from_raw_parts`]: Vec::from_raw_parts + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc /// /// # Examples /// @@ -1755,6 +1784,12 @@ impl Vec { /// may still invalidate this pointer. /// See the second example below for how this guarantee can be used. /// + /// The method also guarantees that, as long as `T` is not zero-sized and the capacity is + /// nonzero, the pointer may be passed into [`dealloc`] with a layout of + /// `Layout::array::(capacity)` in order to deallocate the backing memory. If this is done, + /// be careful not to run the destructor of the `Vec`, as dropping it will result in + /// double-frees. Wrapping the `Vec` in a [`ManuallyDrop`] is the typical way to achieve this. + /// /// # Examples /// /// ``` @@ -1787,9 +1822,24 @@ impl Vec { /// } /// ``` /// + /// Deallocating a vector using [`Box`] (which uses [`dealloc`] internally): + /// + /// ``` + /// use std::mem::{ManuallyDrop, MaybeUninit}; + /// + /// let mut v = ManuallyDrop::new(vec![0, 1, 2]); + /// let ptr = v.as_mut_ptr(); + /// let capacity = v.capacity(); + /// let slice_ptr: *mut [MaybeUninit] = + /// std::ptr::slice_from_raw_parts_mut(ptr.cast(), capacity); + /// drop(unsafe { Box::from_raw(slice_ptr) }); + /// ``` + /// /// [`as_mut_ptr`]: Vec::as_mut_ptr /// [`as_ptr`]: Vec::as_ptr /// [`as_non_null`]: Vec::as_non_null + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// [`ManuallyDrop`]: core::mem::ManuallyDrop #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] #[rustc_never_returns_null_ptr] diff --git a/core/src/clone.rs b/core/src/clone.rs index e315c4fac08a2..0add77b2bc89a 100644 --- a/core/src/clone.rs +++ b/core/src/clone.rs @@ -139,6 +139,34 @@ mod uninit; /// // Note: With the manual implementations the above line will compile. /// ``` /// +/// ## `Clone` and `PartialEq`/`Eq` +/// `Clone` is intended for the duplication of objects. Consequently, when implementing +/// both `Clone` and [`PartialEq`], the following property is expected to hold: +/// ```text +/// x == x -> x.clone() == x +/// ``` +/// In other words, if an object compares equal to itself, +/// its clone must also compare equal to the original. +/// +/// For types that also implement [`Eq`] – for which `x == x` always holds – +/// this implies that `x.clone() == x` must always be true. +/// Standard library collections such as +/// [`HashMap`], [`HashSet`], [`BTreeMap`], [`BTreeSet`] and [`BinaryHeap`] +/// rely on their keys respecting this property for correct behavior. +/// Furthermore, these collections require that cloning a key preserves the outcome of the +/// [`Hash`] and [`Ord`] methods. Thankfully, this follows automatically from `x.clone() == x` +/// if `Hash` and `Ord` are correctly implemented according to their own requirements. +/// +/// When deriving both `Clone` and [`PartialEq`] using `#[derive(Clone, PartialEq)]` +/// or when additionally deriving [`Eq`] using `#[derive(Clone, PartialEq, Eq)]`, +/// then this property is automatically upheld – provided that it is satisfied by +/// the underlying types. +/// +/// Violating this property is a logic error. The behavior resulting from a logic error is not +/// specified, but users of the trait must ensure that such logic errors do *not* result in +/// undefined behavior. This means that `unsafe` code **must not** rely on this property +/// being satisfied. +/// /// ## Additional implementors /// /// In addition to the [implementors listed below][impls], @@ -152,6 +180,11 @@ mod uninit; /// (even if the referent doesn't), /// while variables captured by mutable reference never implement `Clone`. /// +/// [`HashMap`]: ../../std/collections/struct.HashMap.html +/// [`HashSet`]: ../../std/collections/struct.HashSet.html +/// [`BTreeMap`]: ../../std/collections/struct.BTreeMap.html +/// [`BTreeSet`]: ../../std/collections/struct.BTreeSet.html +/// [`BinaryHeap`]: ../../std/collections/struct.BinaryHeap.html /// [impls]: #implementors #[stable(feature = "rust1", since = "1.0.0")] #[lang = "clone"] diff --git a/core/src/internal_macros.rs b/core/src/internal_macros.rs index 2aaefba2468bb..f90818c7969c9 100644 --- a/core/src/internal_macros.rs +++ b/core/src/internal_macros.rs @@ -1,13 +1,9 @@ // implements the unary operator "op &T" // based on "op T" where T is expected to be `Copy`able macro_rules! forward_ref_unop { - (impl $imp:ident, $method:ident for $t:ty) => { - forward_ref_unop!(impl $imp, $method for $t, - #[stable(feature = "rust1", since = "1.0.0")]); - }; - (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => { - #[$attr] - impl $imp for &$t { + (impl $imp:ident, $method:ident for $t:ty, $(#[$attr:meta])+) => { + $(#[$attr])+ + impl const $imp for &$t { type Output = <$t as $imp>::Output; #[inline] @@ -21,13 +17,9 @@ macro_rules! forward_ref_unop { // implements binary operators "&T op U", "T op &U", "&T op &U" // based on "T op U" where T and U are expected to be `Copy`able macro_rules! forward_ref_binop { - (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { - forward_ref_binop!(impl $imp, $method for $t, $u, - #[stable(feature = "rust1", since = "1.0.0")]); - }; - (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { - #[$attr] - impl<'a> $imp<$u> for &'a $t { + (impl $imp:ident, $method:ident for $t:ty, $u:ty, $(#[$attr:meta])+) => { + $(#[$attr])+ + impl const $imp<$u> for &$t { type Output = <$t as $imp<$u>>::Output; #[inline] @@ -37,8 +29,8 @@ macro_rules! forward_ref_binop { } } - #[$attr] - impl $imp<&$u> for $t { + $(#[$attr])+ + impl const $imp<&$u> for $t { type Output = <$t as $imp<$u>>::Output; #[inline] @@ -48,8 +40,8 @@ macro_rules! forward_ref_binop { } } - #[$attr] - impl $imp<&$u> for &$t { + $(#[$attr])+ + impl const $imp<&$u> for &$t { type Output = <$t as $imp<$u>>::Output; #[inline] @@ -64,13 +56,9 @@ macro_rules! forward_ref_binop { // implements "T op= &U", based on "T op= U" // where U is expected to be `Copy`able macro_rules! forward_ref_op_assign { - (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { - forward_ref_op_assign!(impl $imp, $method for $t, $u, - #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]); - }; - (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { - #[$attr] - impl $imp<&$u> for $t { + (impl $imp:ident, $method:ident for $t:ty, $u:ty, $(#[$attr:meta])+) => { + $(#[$attr])+ + impl const $imp<&$u> for $t { #[inline] #[track_caller] fn $method(&mut self, other: &$u) { diff --git a/core/src/net/ip_addr.rs b/core/src/net/ip_addr.rs index 6adeb2aa3fdad..87f2110034c5a 100644 --- a/core/src/net/ip_addr.rs +++ b/core/src/net/ip_addr.rs @@ -2,7 +2,6 @@ use super::display_buffer::DisplayBuffer; use crate::cmp::Ordering; use crate::fmt::{self, Write}; use crate::hash::{Hash, Hasher}; -use crate::iter; use crate::mem::transmute; use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not}; @@ -2348,20 +2347,24 @@ impl const From<[u16; 8]> for IpAddr { } #[stable(feature = "ip_bitops", since = "1.75.0")] -impl Not for Ipv4Addr { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Not for Ipv4Addr { type Output = Ipv4Addr; #[inline] fn not(mut self) -> Ipv4Addr { - for octet in &mut self.octets { - *octet = !*octet; + let mut idx = 0; + while idx < 4 { + self.octets[idx] = !self.octets[idx]; + idx += 1; } self } } #[stable(feature = "ip_bitops", since = "1.75.0")] -impl Not for &'_ Ipv4Addr { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Not for &'_ Ipv4Addr { type Output = Ipv4Addr; #[inline] @@ -2371,20 +2374,24 @@ impl Not for &'_ Ipv4Addr { } #[stable(feature = "ip_bitops", since = "1.75.0")] -impl Not for Ipv6Addr { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Not for Ipv6Addr { type Output = Ipv6Addr; #[inline] fn not(mut self) -> Ipv6Addr { - for octet in &mut self.octets { - *octet = !*octet; + let mut idx = 0; + while idx < 16 { + self.octets[idx] = !self.octets[idx]; + idx += 1; } self } } #[stable(feature = "ip_bitops", since = "1.75.0")] -impl Not for &'_ Ipv6Addr { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Not for &'_ Ipv6Addr { type Output = Ipv6Addr; #[inline] @@ -2400,23 +2407,25 @@ macro_rules! bitop_impls { )*) => { $( $(#[$attr])* - impl $BitOpAssign for $ty { + impl const $BitOpAssign for $ty { fn $bitop_assign(&mut self, rhs: $ty) { - for (lhs, rhs) in iter::zip(&mut self.octets, rhs.octets) { - lhs.$bitop_assign(rhs); + let mut idx = 0; + while idx < self.octets.len() { + self.octets[idx].$bitop_assign(rhs.octets[idx]); + idx += 1; } } } $(#[$attr])* - impl $BitOpAssign<&'_ $ty> for $ty { + impl const $BitOpAssign<&'_ $ty> for $ty { fn $bitop_assign(&mut self, rhs: &'_ $ty) { self.$bitop_assign(*rhs); } } $(#[$attr])* - impl $BitOp for $ty { + impl const $BitOp for $ty { type Output = $ty; #[inline] @@ -2427,7 +2436,7 @@ macro_rules! bitop_impls { } $(#[$attr])* - impl $BitOp<&'_ $ty> for $ty { + impl const $BitOp<&'_ $ty> for $ty { type Output = $ty; #[inline] @@ -2438,7 +2447,7 @@ macro_rules! bitop_impls { } $(#[$attr])* - impl $BitOp<$ty> for &'_ $ty { + impl const $BitOp<$ty> for &'_ $ty { type Output = $ty; #[inline] @@ -2450,7 +2459,7 @@ macro_rules! bitop_impls { } $(#[$attr])* - impl $BitOp<&'_ $ty> for &'_ $ty { + impl const $BitOp<&'_ $ty> for &'_ $ty { type Output = $ty; #[inline] @@ -2466,12 +2475,16 @@ macro_rules! bitop_impls { bitop_impls! { #[stable(feature = "ip_bitops", since = "1.75.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] impl (BitAnd, BitAndAssign) for Ipv4Addr = (bitand, bitand_assign); #[stable(feature = "ip_bitops", since = "1.75.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] impl (BitOr, BitOrAssign) for Ipv4Addr = (bitor, bitor_assign); #[stable(feature = "ip_bitops", since = "1.75.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] impl (BitAnd, BitAndAssign) for Ipv6Addr = (bitand, bitand_assign); #[stable(feature = "ip_bitops", since = "1.75.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] impl (BitOr, BitOrAssign) for Ipv6Addr = (bitor, bitor_assign); } diff --git a/core/src/num/nonzero.rs b/core/src/num/nonzero.rs index 08a66361e6f4d..308d722f5d564 100644 --- a/core/src/num/nonzero.rs +++ b/core/src/num/nonzero.rs @@ -310,9 +310,10 @@ where } #[stable(feature = "nonzero_bitor", since = "1.45.0")] -impl BitOr for NonZero +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const BitOr for NonZero where - T: ZeroablePrimitive + BitOr, + T: ZeroablePrimitive + [const] BitOr, { type Output = Self; @@ -324,9 +325,10 @@ where } #[stable(feature = "nonzero_bitor", since = "1.45.0")] -impl BitOr for NonZero +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const BitOr for NonZero where - T: ZeroablePrimitive + BitOr, + T: ZeroablePrimitive + [const] BitOr, { type Output = Self; @@ -338,9 +340,10 @@ where } #[stable(feature = "nonzero_bitor", since = "1.45.0")] -impl BitOr> for T +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const BitOr> for T where - T: ZeroablePrimitive + BitOr, + T: ZeroablePrimitive + [const] BitOr, { type Output = NonZero; @@ -352,10 +355,11 @@ where } #[stable(feature = "nonzero_bitor", since = "1.45.0")] -impl BitOrAssign for NonZero +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const BitOrAssign for NonZero where T: ZeroablePrimitive, - Self: BitOr, + Self: [const] BitOr, { #[inline] fn bitor_assign(&mut self, rhs: Self) { @@ -364,10 +368,11 @@ where } #[stable(feature = "nonzero_bitor", since = "1.45.0")] -impl BitOrAssign for NonZero +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const BitOrAssign for NonZero where T: ZeroablePrimitive, - Self: BitOr, + Self: [const] BitOr, { #[inline] fn bitor_assign(&mut self, rhs: T) { @@ -1239,7 +1244,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls { // Impls for unsigned nonzero types only. (unsigned $Int:ty) => { #[stable(feature = "nonzero_div", since = "1.51.0")] - impl Div> for $Int { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Div> for $Int { type Output = $Int; /// Same as `self / other.get()`, but because `other` is a `NonZero<_>`, @@ -1257,7 +1263,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls { } #[stable(feature = "nonzero_div_assign", since = "1.79.0")] - impl DivAssign> for $Int { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const DivAssign> for $Int { /// Same as `self /= other.get()`, but because `other` is a `NonZero<_>`, /// there's never a runtime check for division-by-zero. /// @@ -1270,7 +1277,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls { } #[stable(feature = "nonzero_div", since = "1.51.0")] - impl Rem> for $Int { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Rem> for $Int { type Output = $Int; /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. @@ -1283,7 +1291,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls { } #[stable(feature = "nonzero_div_assign", since = "1.79.0")] - impl RemAssign> for $Int { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const RemAssign> for $Int { /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. #[inline] fn rem_assign(&mut self, other: NonZero<$Int>) { @@ -1323,7 +1332,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls { // Impls for signed nonzero types only. (signed $Int:ty) => { #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] - impl Neg for NonZero<$Int> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Neg for NonZero<$Int> { type Output = Self; #[inline] @@ -1334,7 +1344,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls { } forward_ref_unop! { impl Neg, neg for NonZero<$Int>, - #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] } + #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } }; } diff --git a/core/src/num/saturating.rs b/core/src/num/saturating.rs index 4460e430aecfa..c7040721b9353 100644 --- a/core/src/num/saturating.rs +++ b/core/src/num/saturating.rs @@ -109,7 +109,8 @@ impl fmt::UpperHex for Saturating { // // *self = *self << other; // // } // // } -// // forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f } +// // forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f, +// // #[unstable(feature = "saturating_int_impl", issue = "87920")] } // // #[unstable(feature = "saturating_int_impl", issue = "87920")] // impl Shr<$f> for Saturating<$t> { @@ -134,7 +135,8 @@ impl fmt::UpperHex for Saturating { // *self = *self >> other; // } // } -// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f } +// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f, +// #[unstable(feature = "saturating_int_impl", issue = "87920")] } // }; // } // @@ -159,7 +161,8 @@ impl fmt::UpperHex for Saturating { // *self = *self << other; // } // } -// forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f } +// forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f, +// #[unstable(feature = "saturating_int_impl", issue = "87920")] } // // #[unstable(feature = "saturating_int_impl", issue = "87920")] // impl Shr<$f> for Saturating<$t> { @@ -180,7 +183,8 @@ impl fmt::UpperHex for Saturating { // *self = *self >> other; // } // } -// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f } +// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f, +// #[unstable(feature = "saturating_int_impl", issue = "87920")] } // }; // } // @@ -209,7 +213,8 @@ impl fmt::UpperHex for Saturating { macro_rules! saturating_impl { ($($t:ty)*) => ($( #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl Add for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Add for Saturating<$t> { type Output = Saturating<$t>; #[inline] @@ -218,28 +223,36 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl Add, add for Saturating<$t>, Saturating<$t>, - #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl AddAssign for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const AddAssign for Saturating<$t> { #[inline] fn add_assign(&mut self, other: Saturating<$t>) { *self = *self + other; } } - forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, Saturating<$t> } + forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] - impl AddAssign<$t> for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const AddAssign<$t> for Saturating<$t> { #[inline] fn add_assign(&mut self, other: $t) { *self = *self + Saturating(other); } } - forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, $t } + forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, $t, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl Sub for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Sub for Saturating<$t> { type Output = Saturating<$t>; #[inline] @@ -248,28 +261,36 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl Sub, sub for Saturating<$t>, Saturating<$t>, - #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl SubAssign for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const SubAssign for Saturating<$t> { #[inline] fn sub_assign(&mut self, other: Saturating<$t>) { *self = *self - other; } } - forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, Saturating<$t> } + forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] - impl SubAssign<$t> for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const SubAssign<$t> for Saturating<$t> { #[inline] fn sub_assign(&mut self, other: $t) { *self = *self - Saturating(other); } } - forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, $t } + forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, $t, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl Mul for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Mul for Saturating<$t> { type Output = Saturating<$t>; #[inline] @@ -278,25 +299,32 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl Mul, mul for Saturating<$t>, Saturating<$t>, - #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl MulAssign for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const MulAssign for Saturating<$t> { #[inline] fn mul_assign(&mut self, other: Saturating<$t>) { *self = *self * other; } } - forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, Saturating<$t> } + forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] - impl MulAssign<$t> for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const MulAssign<$t> for Saturating<$t> { #[inline] fn mul_assign(&mut self, other: $t) { *self = *self * Saturating(other); } } - forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, $t } + forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, $t, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } /// # Examples /// @@ -314,7 +342,8 @@ macro_rules! saturating_impl { #[doc = concat!("let _ = Saturating(0", stringify!($t), ") / Saturating(0);")] /// ``` #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl Div for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Div for Saturating<$t> { type Output = Saturating<$t>; #[inline] @@ -323,29 +352,36 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl Div, div for Saturating<$t>, Saturating<$t>, - #[stable(feature = "saturating_int_impl", since = "1.74.0")] } - + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl DivAssign for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const DivAssign for Saturating<$t> { #[inline] fn div_assign(&mut self, other: Saturating<$t>) { *self = *self / other; } } - forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, Saturating<$t> } + forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] - impl DivAssign<$t> for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const DivAssign<$t> for Saturating<$t> { #[inline] fn div_assign(&mut self, other: $t) { *self = *self / Saturating(other); } } - forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, $t } + forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, $t, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl Rem for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Rem for Saturating<$t> { type Output = Saturating<$t>; #[inline] @@ -354,28 +390,36 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl Rem, rem for Saturating<$t>, Saturating<$t>, - #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl RemAssign for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const RemAssign for Saturating<$t> { #[inline] fn rem_assign(&mut self, other: Saturating<$t>) { *self = *self % other; } } - forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, Saturating<$t> } + forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] - impl RemAssign<$t> for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const RemAssign<$t> for Saturating<$t> { #[inline] fn rem_assign(&mut self, other: $t) { *self = *self % Saturating(other); } } - forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, $t } + forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, $t, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl Not for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Not for Saturating<$t> { type Output = Saturating<$t>; #[inline] @@ -384,10 +428,12 @@ macro_rules! saturating_impl { } } forward_ref_unop! { impl Not, not for Saturating<$t>, - #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl BitXor for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitXor for Saturating<$t> { type Output = Saturating<$t>; #[inline] @@ -396,28 +442,36 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl BitXor, bitxor for Saturating<$t>, Saturating<$t>, - #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl BitXorAssign for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitXorAssign for Saturating<$t> { #[inline] fn bitxor_assign(&mut self, other: Saturating<$t>) { *self = *self ^ other; } } - forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, Saturating<$t> } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] - impl BitXorAssign<$t> for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitXorAssign<$t> for Saturating<$t> { #[inline] fn bitxor_assign(&mut self, other: $t) { *self = *self ^ Saturating(other); } } - forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, $t } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, $t, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl BitOr for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitOr for Saturating<$t> { type Output = Saturating<$t>; #[inline] @@ -426,28 +480,36 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl BitOr, bitor for Saturating<$t>, Saturating<$t>, - #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl BitOrAssign for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitOrAssign for Saturating<$t> { #[inline] fn bitor_assign(&mut self, other: Saturating<$t>) { *self = *self | other; } } - forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, Saturating<$t> } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] - impl BitOrAssign<$t> for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitOrAssign<$t> for Saturating<$t> { #[inline] fn bitor_assign(&mut self, other: $t) { *self = *self | Saturating(other); } } - forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, $t } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, $t, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl BitAnd for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitAnd for Saturating<$t> { type Output = Saturating<$t>; #[inline] @@ -456,25 +518,32 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl BitAnd, bitand for Saturating<$t>, Saturating<$t>, - #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl BitAndAssign for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitAndAssign for Saturating<$t> { #[inline] fn bitand_assign(&mut self, other: Saturating<$t>) { *self = *self & other; } } - forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, Saturating<$t> } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] - impl BitAndAssign<$t> for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitAndAssign<$t> for Saturating<$t> { #[inline] fn bitand_assign(&mut self, other: $t) { *self = *self & Saturating(other); } } - forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, $t } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, $t, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } @@ -931,7 +1000,8 @@ macro_rules! saturating_int_impl_signed { } #[stable(feature = "saturating_int_impl", since = "1.74.0")] - impl Neg for Saturating<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Neg for Saturating<$t> { type Output = Self; #[inline] fn neg(self) -> Self { @@ -939,7 +1009,8 @@ macro_rules! saturating_int_impl_signed { } } forward_ref_unop! { impl Neg, neg for Saturating<$t>, - #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } diff --git a/core/src/num/wrapping.rs b/core/src/num/wrapping.rs index c460f38bd2e4d..9ccad4b6459cd 100644 --- a/core/src/num/wrapping.rs +++ b/core/src/num/wrapping.rs @@ -88,7 +88,8 @@ impl fmt::UpperHex for Wrapping { macro_rules! sh_impl_signed { ($t:ident, $f:ident) => { #[stable(feature = "rust1", since = "1.0.0")] - impl Shl<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Shl<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -101,19 +102,24 @@ macro_rules! sh_impl_signed { } } forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, - #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShlAssign<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const ShlAssign<$f> for Wrapping<$t> { #[inline] fn shl_assign(&mut self, other: $f) { *self = *self << other; } } - forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "rust1", since = "1.0.0")] - impl Shr<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Shr<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -126,23 +132,28 @@ macro_rules! sh_impl_signed { } } forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, - #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShrAssign<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const ShrAssign<$f> for Wrapping<$t> { #[inline] fn shr_assign(&mut self, other: $f) { *self = *self >> other; } } - forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } }; } macro_rules! sh_impl_unsigned { ($t:ident, $f:ident) => { #[stable(feature = "rust1", since = "1.0.0")] - impl Shl<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Shl<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -151,19 +162,24 @@ macro_rules! sh_impl_unsigned { } } forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, - #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShlAssign<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const ShlAssign<$f> for Wrapping<$t> { #[inline] fn shl_assign(&mut self, other: $f) { *self = *self << other; } } - forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "rust1", since = "1.0.0")] - impl Shr<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Shr<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -172,16 +188,20 @@ macro_rules! sh_impl_unsigned { } } forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, - #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShrAssign<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const ShrAssign<$f> for Wrapping<$t> { #[inline] fn shr_assign(&mut self, other: $f) { *self = *self >> other; } } - forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } }; } @@ -210,7 +230,8 @@ sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } macro_rules! wrapping_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Add for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Add for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -219,28 +240,36 @@ macro_rules! wrapping_impl { } } forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t>, - #[stable(feature = "wrapping_ref", since = "1.14.0")] } + #[stable(feature = "wrapping_ref", since = "1.14.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl AddAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const AddAssign for Wrapping<$t> { #[inline] fn add_assign(&mut self, other: Wrapping<$t>) { *self = *self + other; } } - forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - impl AddAssign<$t> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const AddAssign<$t> for Wrapping<$t> { #[inline] fn add_assign(&mut self, other: $t) { *self = *self + Wrapping(other); } } - forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "rust1", since = "1.0.0")] - impl Sub for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Sub for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -249,28 +278,36 @@ macro_rules! wrapping_impl { } } forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t>, - #[stable(feature = "wrapping_ref", since = "1.14.0")] } + #[stable(feature = "wrapping_ref", since = "1.14.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl SubAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const SubAssign for Wrapping<$t> { #[inline] fn sub_assign(&mut self, other: Wrapping<$t>) { *self = *self - other; } } - forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - impl SubAssign<$t> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const SubAssign<$t> for Wrapping<$t> { #[inline] fn sub_assign(&mut self, other: $t) { *self = *self - Wrapping(other); } } - forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "rust1", since = "1.0.0")] - impl Mul for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Mul for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -279,28 +316,36 @@ macro_rules! wrapping_impl { } } forward_ref_binop! { impl Mul, mul for Wrapping<$t>, Wrapping<$t>, - #[stable(feature = "wrapping_ref", since = "1.14.0")] } + #[stable(feature = "wrapping_ref", since = "1.14.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl MulAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const MulAssign for Wrapping<$t> { #[inline] fn mul_assign(&mut self, other: Wrapping<$t>) { *self = *self * other; } } - forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - impl MulAssign<$t> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const MulAssign<$t> for Wrapping<$t> { #[inline] fn mul_assign(&mut self, other: $t) { *self = *self * Wrapping(other); } } - forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "wrapping_div", since = "1.3.0")] - impl Div for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Div for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -309,28 +354,36 @@ macro_rules! wrapping_impl { } } forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t>, - #[stable(feature = "wrapping_ref", since = "1.14.0")] } + #[stable(feature = "wrapping_ref", since = "1.14.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl DivAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const DivAssign for Wrapping<$t> { #[inline] fn div_assign(&mut self, other: Wrapping<$t>) { *self = *self / other; } } - forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - impl DivAssign<$t> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const DivAssign<$t> for Wrapping<$t> { #[inline] fn div_assign(&mut self, other: $t) { *self = *self / Wrapping(other); } } - forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "wrapping_impls", since = "1.7.0")] - impl Rem for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Rem for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -339,28 +392,36 @@ macro_rules! wrapping_impl { } } forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t>, - #[stable(feature = "wrapping_ref", since = "1.14.0")] } + #[stable(feature = "wrapping_ref", since = "1.14.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl RemAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const RemAssign for Wrapping<$t> { #[inline] fn rem_assign(&mut self, other: Wrapping<$t>) { *self = *self % other; } } - forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - impl RemAssign<$t> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const RemAssign<$t> for Wrapping<$t> { #[inline] fn rem_assign(&mut self, other: $t) { *self = *self % Wrapping(other); } } - forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "rust1", since = "1.0.0")] - impl Not for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Not for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -369,10 +430,12 @@ macro_rules! wrapping_impl { } } forward_ref_unop! { impl Not, not for Wrapping<$t>, - #[stable(feature = "wrapping_ref", since = "1.14.0")] } + #[stable(feature = "wrapping_ref", since = "1.14.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "rust1", since = "1.0.0")] - impl BitXor for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitXor for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -381,28 +444,36 @@ macro_rules! wrapping_impl { } } forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t>, - #[stable(feature = "wrapping_ref", since = "1.14.0")] } + #[stable(feature = "wrapping_ref", since = "1.14.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitXorAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitXorAssign for Wrapping<$t> { #[inline] fn bitxor_assign(&mut self, other: Wrapping<$t>) { *self = *self ^ other; } } - forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - impl BitXorAssign<$t> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitXorAssign<$t> for Wrapping<$t> { #[inline] fn bitxor_assign(&mut self, other: $t) { *self = *self ^ Wrapping(other); } } - forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "rust1", since = "1.0.0")] - impl BitOr for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitOr for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -411,28 +482,36 @@ macro_rules! wrapping_impl { } } forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t>, - #[stable(feature = "wrapping_ref", since = "1.14.0")] } + #[stable(feature = "wrapping_ref", since = "1.14.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitOrAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitOrAssign for Wrapping<$t> { #[inline] fn bitor_assign(&mut self, other: Wrapping<$t>) { *self = *self | other; } } - forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - impl BitOrAssign<$t> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitOrAssign<$t> for Wrapping<$t> { #[inline] fn bitor_assign(&mut self, other: $t) { *self = *self | Wrapping(other); } } - forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "rust1", since = "1.0.0")] - impl BitAnd for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitAnd for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -441,28 +520,36 @@ macro_rules! wrapping_impl { } } forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t>, - #[stable(feature = "wrapping_ref", since = "1.14.0")] } + #[stable(feature = "wrapping_ref", since = "1.14.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitAndAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitAndAssign for Wrapping<$t> { #[inline] fn bitand_assign(&mut self, other: Wrapping<$t>) { *self = *self & other; } } - forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - impl BitAndAssign<$t> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitAndAssign<$t> for Wrapping<$t> { #[inline] fn bitand_assign(&mut self, other: $t) { *self = *self & Wrapping(other); } } - forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } #[stable(feature = "wrapping_neg", since = "1.10.0")] - impl Neg for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Neg for Wrapping<$t> { type Output = Self; #[inline] fn neg(self) -> Self { @@ -470,7 +557,8 @@ macro_rules! wrapping_impl { } } forward_ref_unop! { impl Neg, neg for Wrapping<$t>, - #[stable(feature = "wrapping_ref", since = "1.14.0")] } + #[stable(feature = "wrapping_ref", since = "1.14.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } diff --git a/core/src/ops/arith.rs b/core/src/ops/arith.rs index 7d44b1733b9c6..16c719b0c3946 100644 --- a/core/src/ops/arith.rs +++ b/core/src/ops/arith.rs @@ -106,7 +106,9 @@ macro_rules! add_impl { fn add(self, other: $t) -> $t { self + other } } - forward_ref_binop! { impl Add, add for $t, $t } + forward_ref_binop! { impl Add, add for $t, $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } @@ -218,7 +220,9 @@ macro_rules! sub_impl { fn sub(self, other: $t) -> $t { self - other } } - forward_ref_binop! { impl Sub, sub for $t, $t } + forward_ref_binop! { impl Sub, sub for $t, $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } @@ -351,7 +355,9 @@ macro_rules! mul_impl { fn mul(self, other: $t) -> $t { self * other } } - forward_ref_binop! { impl Mul, mul for $t, $t } + forward_ref_binop! { impl Mul, mul for $t, $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } @@ -493,7 +499,9 @@ macro_rules! div_impl_integer { fn div(self, other: $t) -> $t { self / other } } - forward_ref_binop! { impl Div, div for $t, $t } + forward_ref_binop! { impl Div, div for $t, $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*)*) } @@ -513,7 +521,9 @@ macro_rules! div_impl_float { fn div(self, other: $t) -> $t { self / other } } - forward_ref_binop! { impl Div, div for $t, $t } + forward_ref_binop! { impl Div, div for $t, $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } @@ -599,7 +609,9 @@ macro_rules! rem_impl_integer { fn rem(self, other: $t) -> $t { self % other } } - forward_ref_binop! { impl Rem, rem for $t, $t } + forward_ref_binop! { impl Rem, rem for $t, $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*)*) } @@ -634,7 +646,9 @@ macro_rules! rem_impl_float { fn rem(self, other: $t) -> $t { self % other } } - forward_ref_binop! { impl Rem, rem for $t, $t } + forward_ref_binop! { impl Rem, rem for $t, $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } @@ -678,7 +692,9 @@ rem_impl_float! { f16 f32 f64 f128 } /// ``` #[lang = "neg"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[doc(alias = "-")] +#[const_trait] pub trait Neg { /// The resulting type after applying the `-` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -701,7 +717,8 @@ pub trait Neg { macro_rules! neg_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Neg for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Neg for $t { type Output = $t; #[inline] @@ -709,7 +726,9 @@ macro_rules! neg_impl { fn neg(self) -> $t { -self } } - forward_ref_unop! { impl Neg, neg for $t } + forward_ref_unop! { impl Neg, neg for $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } @@ -746,12 +765,14 @@ neg_impl! { isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } /// ``` #[lang = "add_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "cannot add-assign `{Rhs}` to `{Self}`", label = "no implementation for `{Self} += {Rhs}`" )] #[doc(alias = "+")] #[doc(alias = "+=")] +#[const_trait] pub trait AddAssign { /// Performs the `+=` operation. /// @@ -769,14 +790,17 @@ pub trait AddAssign { macro_rules! add_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl AddAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const AddAssign for $t { #[inline] #[track_caller] #[rustc_inherit_overflow_checks] fn add_assign(&mut self, other: $t) { *self += other } } - forward_ref_op_assign! { impl AddAssign, add_assign for $t, $t } + forward_ref_op_assign! { impl AddAssign, add_assign for $t, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )+) } @@ -813,12 +837,14 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f /// ``` #[lang = "sub_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "cannot subtract-assign `{Rhs}` from `{Self}`", label = "no implementation for `{Self} -= {Rhs}`" )] #[doc(alias = "-")] #[doc(alias = "-=")] +#[const_trait] pub trait SubAssign { /// Performs the `-=` operation. /// @@ -836,14 +862,17 @@ pub trait SubAssign { macro_rules! sub_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl SubAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const SubAssign for $t { #[inline] #[track_caller] #[rustc_inherit_overflow_checks] fn sub_assign(&mut self, other: $t) { *self -= other } } - forward_ref_op_assign! { impl SubAssign, sub_assign for $t, $t } + forward_ref_op_assign! { impl SubAssign, sub_assign for $t, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )+) } @@ -871,12 +900,14 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f /// ``` #[lang = "mul_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "cannot multiply-assign `{Self}` by `{Rhs}`", label = "no implementation for `{Self} *= {Rhs}`" )] #[doc(alias = "*")] #[doc(alias = "*=")] +#[const_trait] pub trait MulAssign { /// Performs the `*=` operation. /// @@ -894,14 +925,17 @@ pub trait MulAssign { macro_rules! mul_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl MulAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const MulAssign for $t { #[inline] #[track_caller] #[rustc_inherit_overflow_checks] fn mul_assign(&mut self, other: $t) { *self *= other } } - forward_ref_op_assign! { impl MulAssign, mul_assign for $t, $t } + forward_ref_op_assign! { impl MulAssign, mul_assign for $t, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )+) } @@ -929,12 +963,14 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f /// ``` #[lang = "div_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "cannot divide-assign `{Self}` by `{Rhs}`", label = "no implementation for `{Self} /= {Rhs}`" )] #[doc(alias = "/")] #[doc(alias = "/=")] +#[const_trait] pub trait DivAssign { /// Performs the `/=` operation. /// @@ -952,13 +988,16 @@ pub trait DivAssign { macro_rules! div_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl DivAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const DivAssign for $t { #[inline] #[track_caller] fn div_assign(&mut self, other: $t) { *self /= other } } - forward_ref_op_assign! { impl DivAssign, div_assign for $t, $t } + forward_ref_op_assign! { impl DivAssign, div_assign for $t, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )+) } @@ -990,12 +1029,14 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f /// ``` #[lang = "rem_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "cannot calculate and assign the remainder of `{Self}` divided by `{Rhs}`", label = "no implementation for `{Self} %= {Rhs}`" )] #[doc(alias = "%")] #[doc(alias = "%=")] +#[const_trait] pub trait RemAssign { /// Performs the `%=` operation. /// @@ -1013,13 +1054,16 @@ pub trait RemAssign { macro_rules! rem_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl RemAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const RemAssign for $t { #[inline] #[track_caller] fn rem_assign(&mut self, other: $t) { *self %= other } } - forward_ref_op_assign! { impl RemAssign, rem_assign for $t, $t } + forward_ref_op_assign! { impl RemAssign, rem_assign for $t, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )+) } diff --git a/core/src/ops/bit.rs b/core/src/ops/bit.rs index deb54c8ba348e..001967282190f 100644 --- a/core/src/ops/bit.rs +++ b/core/src/ops/bit.rs @@ -30,7 +30,9 @@ /// ``` #[lang = "not"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[doc(alias = "!")] +#[const_trait] pub trait Not { /// The resulting type after applying the `!` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -54,21 +56,25 @@ pub trait Not { macro_rules! not_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Not for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Not for $t { type Output = $t; #[inline] fn not(self) -> $t { !self } } - forward_ref_unop! { impl Not, not for $t } + forward_ref_unop! { impl Not, not for $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[stable(feature = "not_never", since = "1.60.0")] -impl Not for ! { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Not for ! { type Output = !; #[inline] @@ -137,10 +143,12 @@ impl Not for ! { #[lang = "bitand"] #[doc(alias = "&")] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "no implementation for `{Self} & {Rhs}`", label = "no implementation for `{Self} & {Rhs}`" )] +#[const_trait] pub trait BitAnd { /// The resulting type after applying the `&` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -164,14 +172,17 @@ pub trait BitAnd { macro_rules! bitand_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl BitAnd for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitAnd for $t { type Output = $t; #[inline] fn bitand(self, rhs: $t) -> $t { self & rhs } } - forward_ref_binop! { impl BitAnd, bitand for $t, $t } + forward_ref_binop! { impl BitAnd, bitand for $t, $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } @@ -237,10 +248,12 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitor"] #[doc(alias = "|")] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "no implementation for `{Self} | {Rhs}`", label = "no implementation for `{Self} | {Rhs}`" )] +#[const_trait] pub trait BitOr { /// The resulting type after applying the `|` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -264,14 +277,17 @@ pub trait BitOr { macro_rules! bitor_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl BitOr for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitOr for $t { type Output = $t; #[inline] fn bitor(self, rhs: $t) -> $t { self | rhs } } - forward_ref_binop! { impl BitOr, bitor for $t, $t } + forward_ref_binop! { impl BitOr, bitor for $t, $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } @@ -337,10 +353,12 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitxor"] #[doc(alias = "^")] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "no implementation for `{Self} ^ {Rhs}`", label = "no implementation for `{Self} ^ {Rhs}`" )] +#[const_trait] pub trait BitXor { /// The resulting type after applying the `^` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -364,14 +382,17 @@ pub trait BitXor { macro_rules! bitxor_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl BitXor for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitXor for $t { type Output = $t; #[inline] fn bitxor(self, other: $t) -> $t { self ^ other } } - forward_ref_binop! { impl BitXor, bitxor for $t, $t } + forward_ref_binop! { impl BitXor, bitxor for $t, $t, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )*) } @@ -436,10 +457,12 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "shl"] #[doc(alias = "<<")] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "no implementation for `{Self} << {Rhs}`", label = "no implementation for `{Self} << {Rhs}`" )] +#[const_trait] pub trait Shl { /// The resulting type after applying the `<<` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -461,7 +484,8 @@ pub trait Shl { macro_rules! shl_impl { ($t:ty, $f:ty) => { #[stable(feature = "rust1", since = "1.0.0")] - impl Shl<$f> for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Shl<$f> for $t { type Output = $t; #[inline] @@ -471,7 +495,9 @@ macro_rules! shl_impl { } } - forward_ref_binop! { impl Shl, shl for $t, $f } + forward_ref_binop! { impl Shl, shl for $t, $f, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } }; } @@ -554,10 +580,12 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } #[lang = "shr"] #[doc(alias = ">>")] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "no implementation for `{Self} >> {Rhs}`", label = "no implementation for `{Self} >> {Rhs}`" )] +#[const_trait] pub trait Shr { /// The resulting type after applying the `>>` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -579,7 +607,8 @@ pub trait Shr { macro_rules! shr_impl { ($t:ty, $f:ty) => { #[stable(feature = "rust1", since = "1.0.0")] - impl Shr<$f> for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const Shr<$f> for $t { type Output = $t; #[inline] @@ -589,7 +618,9 @@ macro_rules! shr_impl { } } - forward_ref_binop! { impl Shr, shr for $t, $f } + forward_ref_binop! { impl Shr, shr for $t, $f, + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } }; } @@ -681,10 +712,12 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } #[lang = "bitand_assign"] #[doc(alias = "&=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "no implementation for `{Self} &= {Rhs}`", label = "no implementation for `{Self} &= {Rhs}`" )] +#[const_trait] pub trait BitAndAssign { /// Performs the `&=` operation. /// @@ -714,12 +747,15 @@ pub trait BitAndAssign { macro_rules! bitand_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitAndAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitAndAssign for $t { #[inline] fn bitand_assign(&mut self, other: $t) { *self &= other } } - forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )+) } @@ -752,10 +788,12 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitor_assign"] #[doc(alias = "|=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "no implementation for `{Self} |= {Rhs}`", label = "no implementation for `{Self} |= {Rhs}`" )] +#[const_trait] pub trait BitOrAssign { /// Performs the `|=` operation. /// @@ -785,12 +823,15 @@ pub trait BitOrAssign { macro_rules! bitor_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitOrAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitOrAssign for $t { #[inline] fn bitor_assign(&mut self, other: $t) { *self |= other } } - forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )+) } @@ -823,10 +864,12 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitxor_assign"] #[doc(alias = "^=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "no implementation for `{Self} ^= {Rhs}`", label = "no implementation for `{Self} ^= {Rhs}`" )] +#[const_trait] pub trait BitXorAssign { /// Performs the `^=` operation. /// @@ -856,12 +899,15 @@ pub trait BitXorAssign { macro_rules! bitxor_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitXorAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const BitXorAssign for $t { #[inline] fn bitxor_assign(&mut self, other: $t) { *self ^= other } } - forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } )+) } @@ -892,10 +938,12 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "shl_assign"] #[doc(alias = "<<=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "no implementation for `{Self} <<= {Rhs}`", label = "no implementation for `{Self} <<= {Rhs}`" )] +#[const_trait] pub trait ShlAssign { /// Performs the `<<=` operation. /// @@ -917,7 +965,8 @@ pub trait ShlAssign { macro_rules! shl_assign_impl { ($t:ty, $f:ty) => { #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShlAssign<$f> for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const ShlAssign<$f> for $t { #[inline] #[rustc_inherit_overflow_checks] fn shl_assign(&mut self, other: $f) { @@ -925,7 +974,9 @@ macro_rules! shl_assign_impl { } } - forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f } + forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } }; } @@ -974,10 +1025,12 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } #[lang = "shr_assign"] #[doc(alias = ">>=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] #[diagnostic::on_unimplemented( message = "no implementation for `{Self} >>= {Rhs}`", label = "no implementation for `{Self} >>= {Rhs}`" )] +#[const_trait] pub trait ShrAssign { /// Performs the `>>=` operation. /// @@ -999,7 +1052,8 @@ pub trait ShrAssign { macro_rules! shr_assign_impl { ($t:ty, $f:ty) => { #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShrAssign<$f> for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] + impl const ShrAssign<$f> for $t { #[inline] #[rustc_inherit_overflow_checks] fn shr_assign(&mut self, other: $f) { @@ -1007,7 +1061,9 @@ macro_rules! shr_assign_impl { } } - forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f } + forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "143802")] } }; } diff --git a/core/src/ops/range.rs b/core/src/ops/range.rs index f33a33e6b752f..95d1e2069ac94 100644 --- a/core/src/ops/range.rs +++ b/core/src/ops/range.rs @@ -853,7 +853,7 @@ pub trait RangeBounds { /// assert!( RangeBounds::is_empty(&(f32::NAN..5.0))); /// ``` /// - /// But never empty is either side is unbounded: + /// But never empty if either side is unbounded: /// /// ``` /// #![feature(range_bounds_is_empty)] diff --git a/core/src/time.rs b/core/src/time.rs index 0fb5c0bac7562..0cc570f4b7335 100644 --- a/core/src/time.rs +++ b/core/src/time.rs @@ -373,7 +373,6 @@ impl Duration { /// # Examples /// /// ``` - /// #![feature(duration_constructors_lite)] /// use std::time::Duration; /// /// let duration = Duration::from_hours(6); @@ -381,7 +380,8 @@ impl Duration { /// assert_eq!(6 * 60 * 60, duration.as_secs()); /// assert_eq!(0, duration.subsec_nanos()); /// ``` - #[unstable(feature = "duration_constructors_lite", issue = "140881")] + #[stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_hours(hours: u64) -> Duration { @@ -401,7 +401,6 @@ impl Duration { /// # Examples /// /// ``` - /// #![feature(duration_constructors_lite)] /// use std::time::Duration; /// /// let duration = Duration::from_mins(10); @@ -409,7 +408,8 @@ impl Duration { /// assert_eq!(10 * 60, duration.as_secs()); /// assert_eq!(0, duration.subsec_nanos()); /// ``` - #[unstable(feature = "duration_constructors_lite", issue = "140881")] + #[stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_mins(mins: u64) -> Duration { @@ -1100,7 +1100,8 @@ impl Duration { } #[stable(feature = "duration", since = "1.3.0")] -impl Add for Duration { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Add for Duration { type Output = Duration; #[inline] @@ -1110,7 +1111,8 @@ impl Add for Duration { } #[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl AddAssign for Duration { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const AddAssign for Duration { #[inline] fn add_assign(&mut self, rhs: Duration) { *self = *self + rhs; @@ -1118,7 +1120,8 @@ impl AddAssign for Duration { } #[stable(feature = "duration", since = "1.3.0")] -impl Sub for Duration { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Sub for Duration { type Output = Duration; #[inline] @@ -1128,7 +1131,8 @@ impl Sub for Duration { } #[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl SubAssign for Duration { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const SubAssign for Duration { #[inline] fn sub_assign(&mut self, rhs: Duration) { *self = *self - rhs; @@ -1136,7 +1140,8 @@ impl SubAssign for Duration { } #[stable(feature = "duration", since = "1.3.0")] -impl Mul for Duration { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Mul for Duration { type Output = Duration; #[inline] @@ -1146,7 +1151,8 @@ impl Mul for Duration { } #[stable(feature = "symmetric_u32_duration_mul", since = "1.31.0")] -impl Mul for u32 { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Mul for u32 { type Output = Duration; #[inline] @@ -1156,7 +1162,8 @@ impl Mul for u32 { } #[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl MulAssign for Duration { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const MulAssign for Duration { #[inline] fn mul_assign(&mut self, rhs: u32) { *self = *self * rhs; @@ -1164,7 +1171,8 @@ impl MulAssign for Duration { } #[stable(feature = "duration", since = "1.3.0")] -impl Div for Duration { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Div for Duration { type Output = Duration; #[inline] @@ -1175,7 +1183,8 @@ impl Div for Duration { } #[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl DivAssign for Duration { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const DivAssign for Duration { #[inline] #[track_caller] fn div_assign(&mut self, rhs: u32) { diff --git a/coretests/tests/lib.rs b/coretests/tests/lib.rs index 75679bbac91fc..0c4d49f3c994b 100644 --- a/coretests/tests/lib.rs +++ b/coretests/tests/lib.rs @@ -36,7 +36,6 @@ #![feature(drop_guard)] #![feature(duration_constants)] #![feature(duration_constructors)] -#![feature(duration_constructors_lite)] #![feature(error_generic_member_access)] #![feature(exact_div)] #![feature(exact_size_is_empty)] diff --git a/coretests/tests/tuple.rs b/coretests/tests/tuple.rs index ea1e281425c89..5d680d1047237 100644 --- a/coretests/tests/tuple.rs +++ b/coretests/tests/tuple.rs @@ -37,7 +37,7 @@ fn test_partial_ord() { assert!(!((1.0f64, 2.0f64) <= (f64::NAN, 3.0))); assert!(!((1.0f64, 2.0f64) > (f64::NAN, 3.0))); assert!(!((1.0f64, 2.0f64) >= (f64::NAN, 3.0))); - assert!(((1.0f64, 2.0f64) < (2.0, f64::NAN))); + assert!((1.0f64, 2.0f64) < (2.0, f64::NAN)); assert!(!((2.0f64, 2.0f64) < (2.0, f64::NAN))); } diff --git a/std/src/collections/hash/map.rs b/std/src/collections/hash/map.rs index edbdd0411457f..15a7a770d1a87 100644 --- a/std/src/collections/hash/map.rs +++ b/std/src/collections/hash/map.rs @@ -135,6 +135,8 @@ use crate::ops::Index; /// ]); /// ``` /// +/// ## `Entry` API +/// /// `HashMap` implements an [`Entry` API](#method.entry), which allows /// for complex methods of getting, setting, updating and removing keys and /// their values: @@ -167,6 +169,8 @@ use crate::ops::Index; /// player_stats.entry("mana").and_modify(|mana| *mana += 200).or_insert(100); /// ``` /// +/// ## Usage with custom key types +/// /// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`]. /// We must also derive [`PartialEq`]. /// diff --git a/std/src/sys/fs/windows.rs b/std/src/sys/fs/windows.rs index 9b674a251652b..09feddd0be9a1 100644 --- a/std/src/sys/fs/windows.rs +++ b/std/src/sys/fs/windows.rs @@ -80,7 +80,7 @@ pub struct OpenOptions { attributes: u32, share_mode: u32, security_qos_flags: u32, - security_attributes: *mut c::SECURITY_ATTRIBUTES, + inherit_handle: bool, } #[derive(Clone, PartialEq, Eq, Debug)] @@ -203,7 +203,7 @@ impl OpenOptions { share_mode: c::FILE_SHARE_READ | c::FILE_SHARE_WRITE | c::FILE_SHARE_DELETE, attributes: 0, security_qos_flags: 0, - security_attributes: ptr::null_mut(), + inherit_handle: false, } } @@ -243,8 +243,8 @@ impl OpenOptions { // receive is `SECURITY_ANONYMOUS = 0x0`, which we can't check for later on. self.security_qos_flags = flags | c::SECURITY_SQOS_PRESENT; } - pub fn security_attributes(&mut self, attrs: *mut c::SECURITY_ATTRIBUTES) { - self.security_attributes = attrs; + pub fn inherit_handle(&mut self, inherit: bool) { + self.inherit_handle = inherit; } fn get_access_mode(&self) -> io::Result { @@ -307,12 +307,17 @@ impl File { fn open_native(path: &WCStr, opts: &OpenOptions) -> io::Result { let creation = opts.get_creation_mode()?; + let sa = c::SECURITY_ATTRIBUTES { + nLength: size_of::() as u32, + lpSecurityDescriptor: ptr::null_mut(), + bInheritHandle: opts.inherit_handle as c::BOOL, + }; let handle = unsafe { c::CreateFileW( path.as_ptr(), opts.get_access_mode()?, opts.share_mode, - opts.security_attributes, + if opts.inherit_handle { &sa } else { ptr::null() }, creation, opts.get_flags_and_attributes(), ptr::null_mut(), diff --git a/std/src/sys/io/io_slice/uefi.rs b/std/src/sys/io/io_slice/uefi.rs new file mode 100644 index 0000000000000..909cfbea0b7ba --- /dev/null +++ b/std/src/sys/io/io_slice/uefi.rs @@ -0,0 +1,74 @@ +//! A buffer type used with `Write::write_vectored` for UEFI Networking APIs. Vectored writing to +//! File is not supported as of UEFI Spec 2.11. + +use crate::marker::PhantomData; +use crate::slice; + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct IoSlice<'a> { + len: u32, + data: *const u8, + _p: PhantomData<&'a [u8]>, +} + +impl<'a> IoSlice<'a> { + #[inline] + pub fn new(buf: &'a [u8]) -> IoSlice<'a> { + let len = buf.len().try_into().unwrap(); + Self { len, data: buf.as_ptr(), _p: PhantomData } + } + + #[inline] + pub fn advance(&mut self, n: usize) { + self.len = u32::try_from(n) + .ok() + .and_then(|n| self.len.checked_sub(n)) + .expect("advancing IoSlice beyond its length"); + unsafe { self.data = self.data.add(n) }; + } + + #[inline] + pub const fn as_slice(&self) -> &'a [u8] { + unsafe { slice::from_raw_parts(self.data, self.len as usize) } + } +} + +#[repr(C)] +pub struct IoSliceMut<'a> { + len: u32, + data: *mut u8, + _p: PhantomData<&'a mut [u8]>, +} + +impl<'a> IoSliceMut<'a> { + #[inline] + pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { + let len = buf.len().try_into().unwrap(); + Self { len, data: buf.as_mut_ptr(), _p: PhantomData } + } + + #[inline] + pub fn advance(&mut self, n: usize) { + self.len = u32::try_from(n) + .ok() + .and_then(|n| self.len.checked_sub(n)) + .expect("advancing IoSlice beyond its length"); + unsafe { self.data = self.data.add(n) }; + } + + #[inline] + pub fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.data, self.len as usize) } + } + + #[inline] + pub const fn into_slice(self) -> &'a mut [u8] { + unsafe { slice::from_raw_parts_mut(self.data, self.len as usize) } + } + + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [u8] { + unsafe { slice::from_raw_parts_mut(self.data, self.len as usize) } + } +} diff --git a/std/src/sys/io/mod.rs b/std/src/sys/io/mod.rs index 4d0365d42fd9b..ae75f4d97b431 100644 --- a/std/src/sys/io/mod.rs +++ b/std/src/sys/io/mod.rs @@ -11,6 +11,9 @@ mod io_slice { } else if #[cfg(target_os = "wasi")] { mod wasi; pub use wasi::*; + } else if #[cfg(target_os = "uefi")] { + mod uefi; + pub use uefi::*; } else { mod unsupported; pub use unsupported::*; diff --git a/std/src/sys/pal/uefi/tests.rs b/std/src/sys/pal/uefi/tests.rs index 38658cc4e9ac4..56ca999cc7e99 100644 --- a/std/src/sys/pal/uefi/tests.rs +++ b/std/src/sys/pal/uefi/tests.rs @@ -1,7 +1,13 @@ +//! These tests are not run automatically right now. Please run these tests manually by copying them +//! to a separate project when modifying any related code. + use super::alloc::*; -use super::time::*; +use super::time::system_time_internal::{from_uefi, to_uefi}; +use crate::io::{IoSlice, IoSliceMut}; use crate::time::Duration; +const SECS_IN_MINUTE: u64 = 60; + #[test] fn align() { // UEFI ABI specifies that allocation alignment minimum is always 8. So this can be @@ -23,19 +29,177 @@ fn align() { } #[test] -fn epoch() { - let t = r_efi::system::Time { - year: 1970, +fn systemtime_start() { + let t = r_efi::efi::Time { + year: 1900, month: 1, day: 1, hour: 0, minute: 0, second: 0, nanosecond: 0, - timezone: r_efi::efi::UNSPECIFIED_TIMEZONE, + timezone: -1440, daylight: 0, + pad2: 0, + }; + assert_eq!(from_uefi(&t), Duration::new(0, 0)); + assert_eq!(t, to_uefi(&from_uefi(&t), -1440, 0).unwrap()); + assert!(to_uefi(&from_uefi(&t), 0, 0).is_none()); +} + +#[test] +fn systemtime_utc_start() { + let t = r_efi::efi::Time { + year: 1900, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, pad1: 0, + nanosecond: 0, + timezone: 0, + daylight: 0, pad2: 0, }; - assert_eq!(system_time_internal::uefi_time_to_duration(t), Duration::new(0, 0)); + assert_eq!(from_uefi(&t), Duration::new(1440 * SECS_IN_MINUTE, 0)); + assert_eq!(t, to_uefi(&from_uefi(&t), 0, 0).unwrap()); + assert!(to_uefi(&from_uefi(&t), -1440, 0).is_some()); +} + +#[test] +fn systemtime_end() { + let t = r_efi::efi::Time { + year: 9999, + month: 12, + day: 31, + hour: 23, + minute: 59, + second: 59, + pad1: 0, + nanosecond: 0, + timezone: 1440, + daylight: 0, + pad2: 0, + }; + assert!(to_uefi(&from_uefi(&t), 1440, 0).is_some()); + assert!(to_uefi(&from_uefi(&t), 1439, 0).is_none()); +} + +// UEFI IoSlice and IoSliceMut Tests +// +// Strictly speaking, vectored read/write types for UDP4, UDP6, TCP4, TCP6 are defined +// separately in the UEFI Spec. However, they have the same signature. These tests just ensure +// that `IoSlice` and `IoSliceMut` are compatible with the vectored types for all the +// networking protocols. + +unsafe fn to_slice(val: &T) -> &[u8] { + let len = size_of_val(val); + unsafe { crate::slice::from_raw_parts(crate::ptr::from_ref(val).cast(), len) } +} + +#[test] +fn io_slice_single() { + let mut data = [0, 1, 2, 3, 4]; + + let tcp4_frag = r_efi::protocols::tcp4::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let tcp6_frag = r_efi::protocols::tcp6::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let udp4_frag = r_efi::protocols::udp4::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let udp6_frag = r_efi::protocols::udp6::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let io_slice = IoSlice::new(&data); + + unsafe { + assert_eq!(to_slice(&io_slice), to_slice(&tcp4_frag)); + assert_eq!(to_slice(&io_slice), to_slice(&tcp6_frag)); + assert_eq!(to_slice(&io_slice), to_slice(&udp4_frag)); + assert_eq!(to_slice(&io_slice), to_slice(&udp6_frag)); + } +} + +#[test] +fn io_slice_mut_single() { + let mut data = [0, 1, 2, 3, 4]; + + let tcp4_frag = r_efi::protocols::tcp4::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let tcp6_frag = r_efi::protocols::tcp6::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let udp4_frag = r_efi::protocols::udp4::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let udp6_frag = r_efi::protocols::udp6::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let io_slice_mut = IoSliceMut::new(&mut data); + + unsafe { + assert_eq!(to_slice(&io_slice_mut), to_slice(&tcp4_frag)); + assert_eq!(to_slice(&io_slice_mut), to_slice(&tcp6_frag)); + assert_eq!(to_slice(&io_slice_mut), to_slice(&udp4_frag)); + assert_eq!(to_slice(&io_slice_mut), to_slice(&udp6_frag)); + } +} + +#[test] +fn io_slice_multi() { + let mut data = [0, 1, 2, 3, 4]; + + let tcp4_frag = r_efi::protocols::tcp4::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let rhs = + [tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag]; + let lhs = [ + IoSlice::new(&data), + IoSlice::new(&data), + IoSlice::new(&data), + IoSlice::new(&data), + IoSlice::new(&data), + ]; + + unsafe { + assert_eq!(to_slice(&lhs), to_slice(&rhs)); + } +} + +#[test] +fn io_slice_basic() { + let data = [0, 1, 2, 3, 4]; + let mut io_slice = IoSlice::new(&data); + + assert_eq!(data, io_slice.as_slice()); + io_slice.advance(2); + assert_eq!(&data[2..], io_slice.as_slice()); +} + +#[test] +fn io_slice_mut_basic() { + let data = [0, 1, 2, 3, 4]; + let mut data_clone = [0, 1, 2, 3, 4]; + let mut io_slice_mut = IoSliceMut::new(&mut data_clone); + + assert_eq!(data, io_slice_mut.as_slice()); + assert_eq!(data, io_slice_mut.as_mut_slice()); + + io_slice_mut.advance(2); + assert_eq!(&data[2..], io_slice_mut.into_slice()); } diff --git a/std/src/sys/pal/uefi/time.rs b/std/src/sys/pal/uefi/time.rs index eeb2c35ffbbc9..a5ab76903274d 100644 --- a/std/src/sys/pal/uefi/time.rs +++ b/std/src/sys/pal/uefi/time.rs @@ -1,16 +1,42 @@ use crate::time::Duration; -const SECS_IN_MINUTE: u64 = 60; -const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; -const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); +/// When a Timezone is specified, the stored Duration is in UTC. If timezone is unspecified, then +/// the timezone is assumed to be in UTC. +/// +/// UEFI SystemTime is stored as Duration from 1900-01-01-00:00:00 with timezone -1440 as anchor #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct SystemTime(Duration); -pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); +pub const UNIX_EPOCH: SystemTime = SystemTime::from_uefi(r_efi::efi::Time { + year: 1970, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + nanosecond: 0, + timezone: 0, + daylight: 0, + pad1: 0, + pad2: 0, +}); + +const MAX_UEFI_TIME: SystemTime = SystemTime::from_uefi(r_efi::efi::Time { + year: 9999, + month: 12, + day: 31, + hour: 23, + minute: 59, + second: 59, + nanosecond: 999_999_999, + timezone: 1440, + daylight: 0, + pad1: 0, + pad2: 0, +}); impl Instant { pub fn now() -> Instant { @@ -40,6 +66,15 @@ impl Instant { } impl SystemTime { + pub(crate) const fn from_uefi(t: r_efi::efi::Time) -> Self { + Self(system_time_internal::from_uefi(&t)) + } + + #[expect(dead_code)] + pub(crate) const fn to_uefi(self, timezone: i16, daylight: u8) -> Option { + system_time_internal::to_uefi(&self.0, timezone, daylight) + } + pub fn now() -> SystemTime { system_time_internal::now() .unwrap_or_else(|| panic!("time not implemented on this platform")) @@ -50,11 +85,14 @@ impl SystemTime { } pub fn checked_add_duration(&self, other: &Duration) -> Option { - Some(SystemTime(self.0.checked_add(*other)?)) + let temp = Self(self.0.checked_add(*other)?); + + // Check if can be represented in UEFI + if temp <= MAX_UEFI_TIME { Some(temp) } else { None } } pub fn checked_sub_duration(&self, other: &Duration) -> Option { - Some(SystemTime(self.0.checked_sub(*other)?)) + self.0.checked_sub(*other).map(Self) } } @@ -66,51 +104,132 @@ pub(crate) mod system_time_internal { use crate::mem::MaybeUninit; use crate::ptr::NonNull; + const SECS_IN_MINUTE: u64 = 60; + const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; + const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; + const TIMEZONE_DELTA: u64 = 1440 * SECS_IN_MINUTE; + pub fn now() -> Option { let runtime_services: NonNull = helpers::runtime_services()?; let mut t: MaybeUninit