From 91bf4760432456c30e9bd82fc34108ea582201bf Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Sun, 21 Apr 2024 17:24:46 -0400 Subject: [PATCH 1/3] add trait primitive::{Integer, Float} --- library/core/src/primitive.rs | 67 -- library/core/src/primitive/float_macros.rs | 44 ++ library/core/src/primitive/int_macros.rs | 880 +++++++++++++++++++++ library/core/src/primitive/mod.rs | 367 +++++++++ 4 files changed, 1291 insertions(+), 67 deletions(-) delete mode 100644 library/core/src/primitive.rs create mode 100644 library/core/src/primitive/float_macros.rs create mode 100644 library/core/src/primitive/int_macros.rs create mode 100644 library/core/src/primitive/mod.rs diff --git a/library/core/src/primitive.rs b/library/core/src/primitive.rs deleted file mode 100644 index e20b2c5c9382a..0000000000000 --- a/library/core/src/primitive.rs +++ /dev/null @@ -1,67 +0,0 @@ -//! This module reexports the primitive types to allow usage that is not -//! possibly shadowed by other declared types. -//! -//! This is normally only useful in macro generated code. -//! -//! An example of this is when generating a new struct and an impl for it: -//! -//! ```rust,compile_fail -//! pub struct bool; -//! -//! impl QueryId for bool { -//! const SOME_PROPERTY: bool = true; -//! } -//! -//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; } -//! ``` -//! -//! Note that the `SOME_PROPERTY` associated constant would not compile, as its -//! type `bool` refers to the struct, rather than to the primitive bool type. -//! -//! A correct implementation could look like: -//! -//! ```rust -//! # #[allow(non_camel_case_types)] -//! pub struct bool; -//! -//! impl QueryId for bool { -//! const SOME_PROPERTY: core::primitive::bool = true; -//! } -//! -//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; } -//! ``` - -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use bool; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use char; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use f32; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use f64; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use i128; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use i16; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use i32; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use i64; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use i8; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use isize; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use str; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use u128; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use u16; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use u32; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use u64; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use u8; -#[stable(feature = "core_primitive", since = "1.43.0")] -pub use usize; diff --git a/library/core/src/primitive/float_macros.rs b/library/core/src/primitive/float_macros.rs new file mode 100644 index 0000000000000..2a82ff603d97e --- /dev/null +++ b/library/core/src/primitive/float_macros.rs @@ -0,0 +1,44 @@ +// Note: currently limiting this to what f16/f128 already support (which isn't much). +// f32/f64 share essentially their whole API which should be added here eventually. + +macro_rules! float_decl { + () => { + /// Returns `true` if this value is NaN. + fn is_nan(self) -> bool; + + /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with + /// positive sign bit and positive infinity. Note that IEEE 754 doesn't assign any + /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that + /// the bit pattern of NaNs are conserved over arithmetic operations, the result of + /// `is_sign_positive` on a NaN might produce an unexpected result in some cases. + /// See [explanation of NaN as a special value](f32) for more info. + fn is_sign_positive(self) -> bool; + + /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with + /// negative sign bit and negative infinity. Note that IEEE 754 doesn't assign any + /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that + /// the bit pattern of NaNs are conserved over arithmetic operations, the result of + /// `is_sign_negative` on a NaN might produce an unexpected result in some cases. + /// See [explanation of NaN as a special value](f32) for more info. + fn is_sign_negative(self) -> bool; + }; +} + +macro_rules! float_impl { + () => { + #[inline] + fn is_nan(self) -> bool { + Self::is_nan(self) + } + + #[inline] + fn is_sign_positive(self) -> bool { + Self::is_sign_positive(self) + } + + #[inline] + fn is_sign_negative(self) -> bool { + Self::is_sign_negative(self) + } + }; +} diff --git a/library/core/src/primitive/int_macros.rs b/library/core/src/primitive/int_macros.rs new file mode 100644 index 0000000000000..0dd774e48dd93 --- /dev/null +++ b/library/core/src/primitive/int_macros.rs @@ -0,0 +1,880 @@ +macro_rules! int_decl { + () => { + /// The smallest value that can be represented by this integer type. + const MIN: Self; + + /// The largest value that can be represented by this integer type. + const MAX: Self; + + /// The size of this integer type in bits. + const BITS: u32; + + /// Returns the number of zeros in the binary representation of `self`. + fn count_ones(self) -> u32; + + /// Returns the number of zeros in the binary representation of `self`. + fn count_zeros(self) -> u32; + + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// Depending on what you're doing with the value, you might also be interested in the + /// [`ilog2`] function which returns a consistent number, even if the type widens. + fn leading_zeros(self) -> u32; + + /// Returns the number of trailing zeros in the binary representation of `self`. + fn trailing_zeros(self) -> u32; + + /// Returns the number of leading ones in the binary representation of `self`. + fn leading_ones(self) -> u32; + + /// Returns the number of trailing ones in the binary representation of `self`. + fn trailing_ones(self) -> u32; + + /// Shifts the bits to the left by a specified amount, `n`, + /// wrapping the truncated bits to the end of the resulting integer. + /// + /// Please note this isn't the same operation as the `<<` shifting operator! + fn rotate_left(self, n: u32) -> Self; + + /// Shifts the bits to the right by a specified amount, `n`, + /// wrapping the truncated bits to the beginning of the resulting + /// integer. + /// + /// Please note this isn't the same operation as the `>>` shifting operator! + fn rotate_right(self, n: u32) -> Self; + + /// Reverses the byte order of the integer. + fn swap_bytes(self) -> Self; + + /// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit, + /// second least-significant bit becomes second most-significant bit, etc. + fn reverse_bits(self) -> Self; + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + fn from_be(x: Self) -> Self; + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + fn from_le(x: Self) -> Self; + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + fn to_be(self) -> Self; + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + fn to_le(self) -> Self; + + /// Checked integer addition. Computes `self + rhs`, returning `None` + /// if overflow occurred. + fn checked_add(self, rhs: Self) -> Option; + + /// Strict integer addition. Computes `self + rhs`, panicking + /// if overflow occurred. + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + fn strict_add(self, rhs: Self) -> Self; + + /// Unchecked integer addition. Computes `self + rhs`, assuming overflow + /// cannot occur. + /// + /// Calling `x.unchecked_add(y)` is semantically equivalent to calling + /// `x.`[`checked_add`]`(y).`[`unwrap_unchecked`]`()`. + /// + /// If you're just trying to avoid the panic in debug mode, then **do not** + /// use this. Instead, you're looking for [`wrapping_add`]. + /// + /// # Safety + /// + /// This results in undefined behavior when `self + rhs > Self::MAX` or + /// `self + rhs < Self::MIN`, i.e. when [`checked_add`] would return `None`. + unsafe fn unchecked_add(self, rhs: Self) -> Self; + + /// Checked integer subtraction. Computes `self - rhs`, returning `None` if + /// overflow occurred. + fn checked_sub(self, rhs: Self) -> Option; + + /// Strict integer subtraction. Computes `self - rhs`, panicking if + /// overflow occurred. + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + fn strict_sub(self, rhs: Self) -> Self; + + /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow + /// cannot occur. + /// + /// Calling `x.unchecked_sub(y)` is semantically equivalent to calling + /// `x.`[`checked_sub`]`(y).`[`unwrap_unchecked`]`()`. + /// + /// If you're just trying to avoid the panic in debug mode, then **do not** + /// use this. Instead, you're looking for [`wrapping_sub`]. + /// + /// # Safety + /// + /// This results in undefined behavior when `self - rhs > Self::MAX` or + /// `self - rhs < Self::MIN`, i.e. when [`checked_sub`] would return `None`. + unsafe fn unchecked_sub(self, rhs: Self) -> Self; + + /// Checked integer multiplication. Computes `self * rhs`, returning `None` if + /// overflow occurred. + fn checked_mul(self, rhs: Self) -> Option; + + /// Strict integer multiplication. Computes `self * rhs`, panicking if + /// overflow occurred. + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + fn strict_mul(self, rhs: Self) -> Self; + + /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow + /// cannot occur. + /// + /// Calling `x.unchecked_mul(y)` is semantically equivalent to calling + /// `x.`[`checked_mul`]`(y).`[`unwrap_unchecked`]`()`. + /// + /// If you're just trying to avoid the panic in debug mode, then **do not** + /// use this. Instead, you're looking for [`wrapping_mul`]. + /// + /// # Safety + /// + /// This results in undefined behavior when `self * rhs > Self::MAX` or + /// `self * rhs < Self::MIN`, i.e. when [`checked_mul`] would return `None`. + unsafe fn unchecked_mul(self, rhs: Self) -> Self; + + /// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0` + /// or the division results in overflow. + fn checked_div(self, rhs: Self) -> Option; + + /// Strict integer division. Computes `self / rhs`, panicking + /// if overflow occurred. + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + fn strict_div(self, rhs: Self) -> Self; + + /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, + /// returning `None` if `rhs == 0` or the division results in overflow. + fn checked_div_euclid(self, rhs: Self) -> Option; + + /// Strict Euclidean division. Computes `self.div_euclid(rhs)`, panicking + /// if overflow occurred. + fn strict_div_euclid(self, rhs: Self) -> Self; + + /// Checked integer remainder. Computes `self % rhs`, returning `None` if + /// `rhs == 0` or the division results in overflow. + fn checked_rem(self, rhs: Self) -> Option; + + /// Strict integer remainder. Computes `self % rhs`, panicking if + /// the division results in overflow. + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + fn strict_rem(self, rhs: Self) -> Self; + + /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` + /// if `rhs == 0` or the division results in overflow. + fn checked_rem_euclid(self, rhs: Self) -> Option; + + /// Strict Euclidean remainder. Computes `self.rem_euclid(rhs)`, panicking if + /// the division results in overflow. + fn strict_rem_euclid(self, rhs: Self) -> Self; + + /// Checked negation. Computes `-self`, returning `None` if the result is `< MIN`. + fn checked_neg(self) -> Option; + + /// Strict negation. Computes `-self`, panicking if the result is `< MIN`. + fn strict_neg(self) -> Self; + + /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger + /// than or equal to the number of bits in `self`. + fn checked_shl(self, rhs: u32) -> Option; + + /// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger + /// than or equal to the number of bits in `self`. + fn strict_shl(self, rhs: u32) -> Self; + + /// Unchecked shift left. Computes `self << rhs`, assuming that + /// `rhs` is less than the number of bits in `self`. + /// + /// # Safety + /// + /// This results in undefined behavior if `rhs` is larger than + /// or equal to the number of bits in `self`, + /// i.e. when [`checked_shl`] would return `None`. + unsafe fn unchecked_shl(self, rhs: u32) -> Self; + + /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is + /// larger than or equal to the number of bits in `self`. + fn checked_shr(self, rhs: u32) -> Option; + + /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is + /// larger than or equal to the number of bits in `self`. + fn strict_shr(self, rhs: u32) -> Self; + + /// Unchecked shift right. Computes `self >> rhs`, assuming that + /// `rhs` is less than the number of bits in `self`. + /// + /// # Safety + /// + /// This results in undefined behavior if `rhs` is larger than + /// or equal to the number of bits in `self`, + /// i.e. when [`checked_shr`] would return `None`. + unsafe fn unchecked_shr(self, rhs: u32) -> Self; + + /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if + /// overflow occurred. + fn checked_pow(self, exp: u32) -> Option; + + /// Strict exponentiation. Computes `self.pow(exp)`, panicking if + /// overflow occurred. + fn strict_pow(self, exp: u32) -> Self; + + /// Saturating integer addition. Computes `self + rhs`, saturating at + /// the numeric bounds instead of overflowing. + fn saturating_add(self, rhs: Self) -> Self; + + /// Saturating integer subtraction. Computes `self - rhs`, saturating at the + /// numeric bounds instead of overflowing. + fn saturating_sub(self, rhs: Self) -> Self; + + /// Saturating integer multiplication. Computes `self * rhs`, saturating at the + /// numeric bounds instead of overflowing. + fn saturating_mul(self, rhs: Self) -> Self; + + /// Saturating integer division. Computes `self / rhs`, saturating at the + /// numeric bounds instead of overflowing. + fn saturating_div(self, rhs: Self) -> Self; + + /// Saturating integer exponentiation. Computes `self.pow(exp)`, + /// saturating at the numeric bounds instead of overflowing. + fn saturating_pow(self, exp: u32) -> Self; + + /// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the + /// boundary of the type. + fn wrapping_add(self, rhs: Self) -> Self; + + /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the + /// boundary of the type. + fn wrapping_sub(self, rhs: Self) -> Self; + + /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at + /// the boundary of the type. + fn wrapping_mul(self, rhs: Self) -> Self; + + /// Wrapping (modular) division. Computes `self / rhs`, wrapping around at the + /// boundary of the type. + /// + /// The only case where such wrapping can occur is when one divides `MIN / -1` on a signed type (where + /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value + /// that is too large to represent in the type. In such a case, this function returns `MIN` itself. + fn wrapping_div(self, rhs: Self) -> Self; + + /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`, + /// wrapping around at the boundary of the type. + /// + /// Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value + /// for the type). This is equivalent to `-MIN`, a positive value that is too large to represent in the + /// type. In this case, this method returns `MIN` itself. + fn wrapping_div_euclid(self, rhs: Self) -> Self; + + /// Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the + /// boundary of the type. + /// + /// Such wrap-around never actually occurs mathematically; implementation artifacts make `x % y` + /// invalid for `MIN / -1` on a signed type (where `MIN` is the negative minimal value). In such a case, + /// this function returns `0`. + fn wrapping_rem(self, rhs: Self) -> Self; + + /// Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around + /// at the boundary of the type. + /// + /// Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value + /// for the type). In this case, this method returns 0. + fn wrapping_rem_euclid(self, rhs: Self) -> Self; + + /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary + /// of the type. + /// + /// The only case where such wrapping can occur is when one negates `MIN` on a signed type (where `MIN` + /// is the negative minimal value for the type); this is a positive value that is too large to represent + /// in the type. In such a case, this function returns `MIN` itself. + fn wrapping_neg(self) -> Self; + + /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes + /// any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to + /// the range of the type, rather than the bits shifted out of the LHS being returned to the other end. + /// The primitive integer types all implement a [`rotate_left`](Self::rotate_left) function, + /// which may be what you want instead. + fn wrapping_shl(self, rhs: u32) -> Self; + + /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, + /// where `mask` removes any high-order bits of `rhs` that + /// would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-right; the + /// RHS of a wrapping shift-right is restricted to the range + /// of the type, rather than the bits shifted out of the LHS + /// being returned to the other end. The primitive integer + /// types all implement a [`rotate_right`](Self::rotate_right) function, + /// which may be what you want instead. + fn wrapping_shr(self, rhs: u32) -> Self; + + /// Wrapping (modular) exponentiation. Computes `self.pow(exp)`, + /// wrapping around at the boundary of the type. + fn wrapping_pow(self, exp: u32) -> Self; + + /// Calculates `self` + `rhs` + /// + /// Returns a tuple of the addition along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + fn overflowing_add(self, rhs: Self) -> (Self, bool); + + /// Calculates `self` - `rhs` + /// + /// Returns a tuple of the subtraction along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + fn overflowing_sub(self, rhs: Self) -> (Self, bool); + + /// Calculates the multiplication of `self` and `rhs`. + /// + /// Returns a tuple of the multiplication along with a boolean + /// indicating whether an arithmetic overflow would occur. If an + /// overflow would have occurred then the wrapped value is returned. + fn overflowing_mul(self, rhs: Self) -> (Self, bool); + + /// Calculates the divisor when `self` is divided by `rhs`. + /// + /// Returns a tuple of the divisor along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// occur then self is returned. + fn overflowing_div(self, rhs: Self) -> (Self, bool); + + /// Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. + /// + /// Returns a tuple of the divisor along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// occur then self is returned. + fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool); + + /// Calculates the remainder when `self` is divided by `rhs`. + /// + /// Returns a tuple of the remainder after dividing along with a boolean + /// indicating whether an arithmetic overflow would occur. If an + /// overflow would occur then 0 is returned. + fn overflowing_rem(self, rhs: Self) -> (Self, bool); + + /// Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`. + /// + /// Returns a tuple of the remainder after dividing along with a boolean + /// indicating whether an arithmetic overflow would occur. If an + /// overflow would occur then 0 is returned. + fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool); + + /// Negates self, overflowing if this is equal to the minimum value. + /// + /// Returns a tuple of the negated version of self along with a boolean + /// indicating whether an overflow happened. If `self` is the minimum + /// signed value (e.g., `i32::MIN` for values of type `i32`), then the + /// minimum value will be returned again and `true` will be returned for + /// an overflow happening. + fn overflowing_neg(self) -> (Self, bool); + + /// Shifts self left by `rhs` bits. + /// + /// Returns a tuple of the shifted version of self along with a boolean + /// indicating whether the shift value was larger than or equal to the + /// number of bits. If the shift value is too large, then value is + /// masked (N-1) where N is the number of bits, and this value is then + /// used to perform the shift. + fn overflowing_shl(self, rhs: u32) -> (Self, bool); + + /// Shifts self right by `rhs` bits. + /// + /// Returns a tuple of the shifted version of self along with a boolean + /// indicating whether the shift value was larger than or equal to the + /// number of bits. If the shift value is too large, then value is + /// masked (N-1) where N is the number of bits, and this value is then + /// used to perform the shift. + fn overflowing_shr(self, rhs: u32) -> (Self, bool); + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// Returns a tuple of the exponentiation along with a bool indicating + /// whether an overflow happened. + fn overflowing_pow(self, exp: u32) -> (Self, bool); + + /// Raises self to the power of `exp`, using exponentiation by squaring. + fn pow(self, exp: u32) -> Self; + + /// Returns the square root of the number, rounded down. + #[unstable(feature = "isqrt", issue = "116226")] + fn isqrt(self) -> Self; + + /// Calculates the quotient of Euclidean division of `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with + /// `r = self.rem_euclid(rhs)` and `0 <= r < abs(rhs)`. + /// + /// In other words, the result is `self / rhs` rounded to the integer `q` + /// such that `self >= q * rhs`. + /// If `self > 0`, this is equal to round towards zero (the default in Rust); + /// if `self < 0`, this is equal to round towards +/- infinity. + fn div_euclid(self, rhs: Self) -> Self; + + /// Calculates the least nonnegative remainder of `self (mod rhs)`. + /// + /// This is done as if by the Euclidean division algorithm -- given + /// `r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, + /// and `0 <= r < abs(rhs)`. + fn rem_euclid(self, rhs: Self) -> Self; + + /// Calculates the quotient of `self` and `rhs`, rounding the result + /// towards negative infinity. + #[unstable(feature = "int_roundings", issue = "88581")] + fn div_floor(self, rhs: Self) -> Self; + + /// Calculates the quotient of `self` and `rhs`, rounding the result + /// towards positive infinity. + #[unstable(feature = "int_roundings", issue = "88581")] + fn div_ceil(self, rhs: Self) -> Self; + + /// If `rhs` is positive, calculates the smallest value greater than or + /// equal to `self` that is a multiple of `rhs`. If `rhs` is negative, + /// calculates the largest value less than or equal to `self` that is a + /// multiple of `rhs`. + #[unstable(feature = "int_roundings", issue = "88581")] + fn next_multiple_of(self, rhs: Self) -> Self; + + /// If `rhs` is positive, calculates the smallest value greater than or + /// equal to `self` that is a multiple of `rhs`. If `rhs` is negative, + /// calculates the largest value less than or equal to `self` that is a + /// multiple of `rhs`. Returns `None` if `rhs` is zero or the operation + /// would result in overflow. + #[unstable(feature = "int_roundings", issue = "88581")] + fn checked_next_multiple_of(self, rhs: Self) -> Option; + + /// Returns the smallest value that can be represented by this integer type. + /// + /// New code should prefer to use [`Self::MIN`] instead. + #[deprecated( + since = "TBD", + note = "replaced by the `MAX` associated constant on this type" + )] + fn min_value() -> Self; + + /// Returns the largest value that can be represented by this integer type. + /// + /// New code should prefer to use [`Self::MAX`] instead. + #[deprecated( + since = "TBD", + note = "replaced by the `MAX` associated constant on this type" + )] + fn max_value() -> Self; + }; +} + +macro_rules! int_impl { + () => { + const MIN: Self = Self::MIN; + const MAX: Self = Self::MAX; + const BITS: u32 = Self::BITS; + + #[inline] + fn count_ones(self) -> u32 { + Self::count_ones(self) + } + + #[inline] + fn count_zeros(self) -> u32 { + Self::count_zeros(self) + } + + #[inline] + fn leading_zeros(self) -> u32 { + Self::leading_zeros(self) + } + + #[inline] + fn trailing_zeros(self) -> u32 { + Self::trailing_zeros(self) + } + + #[inline] + fn leading_ones(self) -> u32 { + Self::leading_ones(self) + } + + #[inline] + fn trailing_ones(self) -> u32 { + Self::trailing_ones(self) + } + + #[inline] + fn rotate_left(self, n: u32) -> Self { + Self::rotate_left(self, n) + } + + #[inline] + fn rotate_right(self, n: u32) -> Self { + Self::rotate_right(self, n) + } + + #[inline] + fn swap_bytes(self) -> Self { + Self::swap_bytes(self) + } + + #[inline] + fn reverse_bits(self) -> Self { + Self::reverse_bits(self) + } + + #[inline] + fn from_be(x: Self) -> Self { + Self::from_be(x) + } + + #[inline] + fn from_le(x: Self) -> Self { + Self::from_le(x) + } + + #[inline] + fn to_be(self) -> Self { + Self::to_be(self) + } + + #[inline] + fn to_le(self) -> Self { + Self::to_le(self) + } + + #[inline] + fn checked_add(self, rhs: Self) -> Option { + Self::checked_add(self, rhs) + } + + #[inline] + fn strict_add(self, rhs: Self) -> Self { + Self::strict_add(self, rhs) + } + + #[inline] + unsafe fn unchecked_add(self, rhs: Self) -> Self { + // SAFETY: deferred to the caller + unsafe { Self::unchecked_add(self, rhs) } + } + + #[inline] + fn checked_sub(self, rhs: Self) -> Option { + Self::checked_sub(self, rhs) + } + + #[inline] + fn strict_sub(self, rhs: Self) -> Self { + Self::strict_sub(self, rhs) + } + + #[inline] + unsafe fn unchecked_sub(self, rhs: Self) -> Self { + // SAFETY: deferred to the caller + unsafe { Self::unchecked_sub(self, rhs) } + } + + #[inline] + fn checked_mul(self, rhs: Self) -> Option { + Self::checked_mul(self, rhs) + } + + #[inline] + fn strict_mul(self, rhs: Self) -> Self { + Self::strict_mul(self, rhs) + } + + #[inline] + unsafe fn unchecked_mul(self, rhs: Self) -> Self { + // SAFETY: deferred to the caller + unsafe { Self::unchecked_mul(self, rhs) } + } + + #[inline] + fn checked_div(self, rhs: Self) -> Option { + Self::checked_div(self, rhs) + } + + #[inline] + fn strict_div(self, rhs: Self) -> Self { + Self::strict_div(self, rhs) + } + + #[inline] + fn checked_div_euclid(self, rhs: Self) -> Option { + Self::checked_div_euclid(self, rhs) + } + + #[inline] + fn strict_div_euclid(self, rhs: Self) -> Self { + Self::strict_div_euclid(self, rhs) + } + + #[inline] + fn checked_rem(self, rhs: Self) -> Option { + Self::checked_rem(self, rhs) + } + + #[inline] + fn strict_rem(self, rhs: Self) -> Self { + Self::strict_rem(self, rhs) + } + + #[inline] + fn checked_rem_euclid(self, rhs: Self) -> Option { + Self::checked_rem_euclid(self, rhs) + } + + #[inline] + fn strict_rem_euclid(self, rhs: Self) -> Self { + Self::strict_rem_euclid(self, rhs) + } + + #[inline] + fn checked_neg(self) -> Option { + Self::checked_neg(self) + } + + #[inline] + fn strict_neg(self) -> Self { + Self::strict_neg(self) + } + + #[inline] + fn checked_shl(self, rhs: u32) -> Option { + Self::checked_shl(self, rhs) + } + + #[inline] + fn strict_shl(self, rhs: u32) -> Self { + Self::strict_shl(self, rhs) + } + + #[inline] + unsafe fn unchecked_shl(self, rhs: u32) -> Self { + // SAFETY: deferred to the caller + unsafe { Self::unchecked_shl(self, rhs) } + } + + #[inline] + fn checked_shr(self, rhs: u32) -> Option { + Self::checked_shr(self, rhs) + } + + #[inline] + fn strict_shr(self, rhs: u32) -> Self { + Self::strict_shr(self, rhs) + } + + #[inline] + unsafe fn unchecked_shr(self, rhs: u32) -> Self { + // SAFETY: deferred to the caller + unsafe { Self::unchecked_shr(self, rhs) } + } + + #[inline] + fn checked_pow(self, exp: u32) -> Option { + Self::checked_pow(self, exp) + } + + #[inline] + fn strict_pow(self, exp: u32) -> Self { + Self::strict_pow(self, exp) + } + + #[inline] + fn saturating_add(self, rhs: Self) -> Self { + Self::saturating_add(self, rhs) + } + + #[inline] + fn saturating_sub(self, rhs: Self) -> Self { + Self::saturating_sub(self, rhs) + } + + #[inline] + fn saturating_mul(self, rhs: Self) -> Self { + Self::saturating_mul(self, rhs) + } + + #[inline] + fn saturating_div(self, rhs: Self) -> Self { + Self::saturating_div(self, rhs) + } + + #[inline] + fn saturating_pow(self, exp: u32) -> Self { + Self::saturating_pow(self, exp) + } + + #[inline] + fn wrapping_add(self, rhs: Self) -> Self { + Self::wrapping_add(self, rhs) + } + + #[inline] + fn wrapping_sub(self, rhs: Self) -> Self { + Self::wrapping_sub(self, rhs) + } + + #[inline] + fn wrapping_mul(self, rhs: Self) -> Self { + Self::wrapping_mul(self, rhs) + } + + #[inline] + fn wrapping_div(self, rhs: Self) -> Self { + Self::wrapping_div(self, rhs) + } + + #[inline] + fn wrapping_div_euclid(self, rhs: Self) -> Self { + Self::wrapping_div_euclid(self, rhs) + } + + #[inline] + fn wrapping_rem(self, rhs: Self) -> Self { + Self::wrapping_rem(self, rhs) + } + + #[inline] + fn wrapping_rem_euclid(self, rhs: Self) -> Self { + Self::wrapping_rem_euclid(self, rhs) + } + + #[inline] + fn wrapping_neg(self) -> Self { + Self::wrapping_neg(self) + } + + #[inline] + fn wrapping_shl(self, rhs: u32) -> Self { + Self::wrapping_shl(self, rhs) + } + + #[inline] + fn wrapping_shr(self, rhs: u32) -> Self { + Self::wrapping_shr(self, rhs) + } + + #[inline] + fn wrapping_pow(self, exp: u32) -> Self { + Self::wrapping_pow(self, exp) + } + + #[inline] + fn overflowing_add(self, rhs: Self) -> (Self, bool) { + Self::overflowing_add(self, rhs) + } + + #[inline] + fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + Self::overflowing_sub(self, rhs) + } + + #[inline] + fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + Self::overflowing_mul(self, rhs) + } + + #[inline] + fn overflowing_div(self, rhs: Self) -> (Self, bool) { + Self::overflowing_div(self, rhs) + } + + #[inline] + fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + Self::overflowing_div_euclid(self, rhs) + } + + #[inline] + fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + Self::overflowing_rem(self, rhs) + } + + #[inline] + fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + Self::overflowing_rem_euclid(self, rhs) + } + + #[inline] + fn overflowing_neg(self) -> (Self, bool) { + Self::overflowing_neg(self) + } + + #[inline] + fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + Self::overflowing_shl(self, rhs) + } + + #[inline] + fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + Self::overflowing_shr(self, rhs) + } + + #[inline] + fn overflowing_pow(self, exp: u32) -> (Self, bool) { + Self::overflowing_pow(self, exp) + } + + #[inline] + fn pow(self, exp: u32) -> Self { + Self::pow(self, exp) + } + + #[inline] + fn isqrt(self) -> Self { + Self::isqrt(self) + } + + #[inline] + fn div_euclid(self, rhs: Self) -> Self { + Self::div_euclid(self, rhs) + } + + #[inline] + fn rem_euclid(self, rhs: Self) -> Self { + Self::rem_euclid(self, rhs) + } + + #[inline] + fn div_floor(self, rhs: Self) -> Self { + Self::div_floor(self, rhs) + } + + #[inline] + fn div_ceil(self, rhs: Self) -> Self { + Self::div_ceil(self, rhs) + } + + #[inline] + fn next_multiple_of(self, rhs: Self) -> Self { + Self::next_multiple_of(self, rhs) + } + + #[inline] + fn checked_next_multiple_of(self, rhs: Self) -> Option { + Self::checked_next_multiple_of(self, rhs) + } + + #[inline] + #[allow(deprecated_in_future)] + fn min_value() -> Self { + Self::min_value() + } + + #[inline] + #[allow(deprecated_in_future)] + fn max_value() -> Self { + Self::max_value() + } + }; +} diff --git a/library/core/src/primitive/mod.rs b/library/core/src/primitive/mod.rs new file mode 100644 index 0000000000000..509e4705c8fba --- /dev/null +++ b/library/core/src/primitive/mod.rs @@ -0,0 +1,367 @@ +//! This module reexports the primitive types to allow usage that is not +//! possibly shadowed by other declared types. +//! +//! This is normally only useful in macro generated code. +//! +//! An example of this is when generating a new struct and an impl for it: +//! +//! ```rust,compile_fail +//! pub struct bool; +//! +//! impl QueryId for bool { +//! const SOME_PROPERTY: bool = true; +//! } +//! +//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; } +//! ``` +//! +//! Note that the `SOME_PROPERTY` associated constant would not compile, as its +//! type `bool` refers to the struct, rather than to the primitive bool type. +//! +//! A correct implementation could look like: +//! +//! ```rust +//! # #[allow(non_camel_case_types)] +//! pub struct bool; +//! +//! impl QueryId for bool { +//! const SOME_PROPERTY: core::primitive::bool = true; +//! } +//! +//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; } +//! ``` + +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use bool; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use char; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use f32; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use f64; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use i128; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use i16; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use i32; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use i64; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use i8; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use isize; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use str; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use u128; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use u16; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use u32; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use u64; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use u8; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use usize; + +mod sealed { + /// This trait being unreachable from outside the crate prevents downstream + /// implementations, permitting extension of the subtraits without breakage. + #[unstable( + feature = "primitive_abstraction_internals", + reason = "should be replaced by #[sealed] once available", + issue = "none" + )] + pub trait Sealed {} +} + +#[macro_use] +mod int_macros; // import int_decl!, int_impl! +#[macro_use] +mod float_macros; // import float_decl!, float_impl! + +use crate::{fmt, hash, iter, ops, panic}; +use sealed::Sealed; + +/// A trait implemented by all *primitive* integer types, signed or unsigned. +/// +/// This trait is sealed and cannot be implemented for types outside of the +/// standard library. It is not intended to be a general-purpose numerical +/// abstraction. By being limited to primitive integers, this trait can add +/// new functionality as it is provided without risk of breaking implementors. +#[fundamental] +#[unstable(feature = "primitive_abstraction", issue = "none")] +pub trait Integer: + 'static + sealed::Sealed + // core::marker + + Sized + Copy + Clone + Send + Sync + Unpin + // core::panic + + panic::UnwindSafe + panic::RefUnwindSafe + // core::fmt + + fmt::Debug + fmt::Display + fmt::Binary + fmt::Octal + + fmt::LowerHex + fmt::UpperHex + fmt::LowerExp + fmt::UpperExp + // core::default + + Default + // core::cmp + + PartialEq + Eq + PartialOrd + Ord + // core::hash + + hash::Hash + // core::str + + crate::str::FromStr + // core::convert + + TryFrom + TryInto + + TryFrom + TryInto + + TryFrom + TryInto + + TryFrom + TryInto + + TryFrom + TryInto + + TryFrom + TryInto + + TryFrom + TryInto + + TryFrom + TryInto + + TryFrom + TryInto + + TryFrom + TryInto + + TryFrom + TryInto + + TryFrom + TryInto + // core::ops + + ops::Add + for<'a> ops::Add<&'a Self, Output = Self> + + ops::Sub + for<'a> ops::Sub<&'a Self, Output = Self> + + ops::Mul + for<'a> ops::Mul<&'a Self, Output = Self> + + ops::Div + for<'a> ops::Div<&'a Self, Output = Self> + + ops::Rem + for<'a> ops::Rem<&'a Self, Output = Self> + + ops::AddAssign + for<'a> ops::AddAssign<&'a Self> + + ops::SubAssign + for<'a> ops::SubAssign<&'a Self> + + ops::MulAssign + for<'a> ops::MulAssign<&'a Self> + + ops::DivAssign + for<'a> ops::DivAssign<&'a Self> + + ops::RemAssign + for<'a> ops::RemAssign<&'a Self> + + ops::Not + + ops::BitAnd + for<'a> ops::BitAnd<&'a Self, Output = Self> + + ops::BitOr + for<'a> ops::BitOr<&'a Self, Output = Self> + + ops::BitXor + for<'a> ops::BitXor<&'a Self, Output = Self> + + ops::BitAndAssign + for<'a> ops::BitAndAssign<&'a Self> + + ops::BitOrAssign + for<'a> ops::BitOrAssign<&'a Self> + + ops::BitXorAssign + for<'a> ops::BitXorAssign<&'a Self> + + ops::Shl + for<'a> ops::Shl<&'a u8, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a u16, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a u32, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a u64, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a u128, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a usize, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a i8, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a i16, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a i32, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a i64, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a i128, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a isize, Output = Self> + + ops::Shl + for<'a> ops::Shl<&'a Self, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a u8, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a u16, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a u32, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a u64, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a u128, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a usize, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a i8, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a i16, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a i32, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a i64, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a i128, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a isize, Output = Self> + + ops::Shr + for<'a> ops::Shr<&'a Self, Output = Self> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a u8> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a u16> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a u32> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a u64> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a u128> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a usize> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a i8> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a i16> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a i32> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a i64> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a i128> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a isize> + + ops::ShlAssign + for<'a> ops::ShlAssign<&'a Self> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a u8> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a u16> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a u32> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a u64> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a u128> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a usize> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a i8> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a i16> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a i32> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a i64> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a i128> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a isize> + + ops::ShrAssign + for<'a> ops::ShrAssign<&'a Self> + // core::iter + + iter::Sum + for<'a> iter::Sum<&'a Self> + + iter::Product + for<'a> iter::Product<&'a Self> +{ + int_decl!(); +} + +/// A trait implemented by all *primitive* floating point types. +/// +/// This trait is sealed and cannot be implemented for types outside of the +/// standard library. It is not intended to be a general-purpose numerical +/// abstraction. By being limited to primitive floating point, this trait can add +/// new functionality as it is provided without risk of breaking implementors. +#[fundamental] +#[unstable(feature = "primitive_abstraction", issue = "none")] +pub trait Float: + 'static + sealed::Sealed + // core::marker + + Sized + Copy + Clone + Send + Sync + Unpin + // core::panic + + panic::UnwindSafe + panic::RefUnwindSafe + // core::fmt + + fmt::Debug // + fmt::Display + fmt::LowerExp + fmt::UpperExp + // core::default + + Default + // core::cmp + + PartialEq + PartialOrd + // core::ops + + ops::Add + for<'a> ops::Add<&'a Self, Output = Self> + + ops::Sub + for<'a> ops::Sub<&'a Self, Output = Self> + + ops::Mul + for<'a> ops::Mul<&'a Self, Output = Self> + + ops::Div + for<'a> ops::Div<&'a Self, Output = Self> + + ops::Rem + for<'a> ops::Rem<&'a Self, Output = Self> + + ops::AddAssign + for<'a> ops::AddAssign<&'a Self> + + ops::SubAssign + for<'a> ops::SubAssign<&'a Self> + + ops::MulAssign + for<'a> ops::MulAssign<&'a Self> + + ops::DivAssign + for<'a> ops::DivAssign<&'a Self> + + ops::RemAssign + for<'a> ops::RemAssign<&'a Self> + + ops::Neg +{ + float_decl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for u8 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for u8 { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for u16 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for u16 { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for u32 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for u32 { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for u64 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for u64 { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for u128 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for u128 { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for usize {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for usize { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for i8 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for i8 { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for i16 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for i16 { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for i32 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for i32 { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for i64 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for i64 { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for i128 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for i128 { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for isize {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Integer for isize { + int_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for f16 {} + +#[cfg(not(bootstrap))] +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Float for f16 { + float_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for f32 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Float for f32 { + float_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for f64 {} + +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Float for f64 { + float_impl!(); +} + +#[unstable(feature = "primitive_abstraction_internals", issue = "none")] +impl Sealed for f128 {} + +#[cfg(not(bootstrap))] +#[unstable(feature = "primitive_abstraction", issue = "none")] +impl Float for f128 { + float_impl!(); +} From 49280f753b48b1f8c8e50ba04cf77ef4a7191f0e Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Sun, 21 Apr 2024 22:37:41 -0400 Subject: [PATCH 2/3] bless ui tests --- tests/ui/const-generics/wrong-normalization.stderr | 5 +++++ tests/ui/intrinsics/unchecked_math_unsafe.stderr | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/ui/const-generics/wrong-normalization.stderr b/tests/ui/const-generics/wrong-normalization.stderr index 379a5593dd640..0db15ba8fc98e 100644 --- a/tests/ui/const-generics/wrong-normalization.stderr +++ b/tests/ui/const-generics/wrong-normalization.stderr @@ -12,10 +12,15 @@ error[E0599]: no associated item named `MIN` found for type `i8` in the current LL | impl as Identity>::Identity { | ^^^ associated item not found in `i8` | + = help: items from traits can only be used if the trait is in scope help: you are looking for the module in `std`, not the primitive type | LL | impl as Identity>::Identity { | +++++ +help: trait `Integer` which provides `MIN` is implemented but not in scope; perhaps you want to import it + | +LL + use std::primitive::Integer; + | error: aborting due to 2 previous errors diff --git a/tests/ui/intrinsics/unchecked_math_unsafe.stderr b/tests/ui/intrinsics/unchecked_math_unsafe.stderr index 31da1a86ca135..bbb832610f78f 100644 --- a/tests/ui/intrinsics/unchecked_math_unsafe.stderr +++ b/tests/ui/intrinsics/unchecked_math_unsafe.stderr @@ -1,4 +1,4 @@ -error[E0133]: call to unsafe function `unchecked_add` is unsafe and requires unsafe function or block +error[E0133]: call to unsafe function `std::intrinsics::unchecked_add` is unsafe and requires unsafe function or block --> $DIR/unchecked_math_unsafe.rs:5:15 | LL | let add = std::intrinsics::unchecked_add(x, y); @@ -6,7 +6,7 @@ LL | let add = std::intrinsics::unchecked_add(x, y); | = note: consult the function's documentation for information on how to avoid undefined behavior -error[E0133]: call to unsafe function `unchecked_sub` is unsafe and requires unsafe function or block +error[E0133]: call to unsafe function `std::intrinsics::unchecked_sub` is unsafe and requires unsafe function or block --> $DIR/unchecked_math_unsafe.rs:6:15 | LL | let sub = std::intrinsics::unchecked_sub(x, y); @@ -14,7 +14,7 @@ LL | let sub = std::intrinsics::unchecked_sub(x, y); | = note: consult the function's documentation for information on how to avoid undefined behavior -error[E0133]: call to unsafe function `unchecked_mul` is unsafe and requires unsafe function or block +error[E0133]: call to unsafe function `std::intrinsics::unchecked_mul` is unsafe and requires unsafe function or block --> $DIR/unchecked_math_unsafe.rs:7:15 | LL | let mul = std::intrinsics::unchecked_mul(x, y); From 473b997f77d1aba98da0b148dd2b3b9c8d3bf121 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Mon, 22 Apr 2024 00:23:23 -0400 Subject: [PATCH 3/3] bless mir-opt tests --- .../issue_101973.inner.GVN.panic-abort.diff | 4 ++-- .../issue_101973.inner.GVN.panic-unwind.diff | 4 ++-- ...sics.unchecked.LowerIntrinsics.panic-abort.diff | 14 +++++++------- ...ics.unchecked.LowerIntrinsics.panic-unwind.diff | 14 +++++++------- ...nsics.wrapping.LowerIntrinsics.panic-abort.diff | 2 +- ...sics.wrapping.LowerIntrinsics.panic-unwind.diff | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff index 311de9e1c93f3..bf206c7129b9f 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff @@ -70,8 +70,8 @@ bb2: { _6 = Shl(move _7, const 1_i32); StorageDead(_7); -- _3 = rotate_right::(move _4, move _6) -> [return: bb3, unwind unreachable]; -+ _3 = rotate_right::(_14, move _6) -> [return: bb3, unwind unreachable]; +- _3 = std::intrinsics::rotate_right::(move _4, move _6) -> [return: bb3, unwind unreachable]; ++ _3 = std::intrinsics::rotate_right::(_14, move _6) -> [return: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff index c5fd042161d27..41c8940c67075 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff @@ -70,8 +70,8 @@ bb2: { _6 = Shl(move _7, const 1_i32); StorageDead(_7); -- _3 = rotate_right::(move _4, move _6) -> [return: bb3, unwind unreachable]; -+ _3 = rotate_right::(_14, move _6) -> [return: bb3, unwind unreachable]; +- _3 = std::intrinsics::rotate_right::(move _4, move _6) -> [return: bb3, unwind unreachable]; ++ _3 = std::intrinsics::rotate_right::(_14, move _6) -> [return: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff index 3c9694d0370d8..ad4f3bb5f9aaa 100644 --- a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-abort.diff @@ -67,7 +67,7 @@ _5 = _1; StorageLive(_6); _6 = _2; -- _4 = unchecked_add::(move _5, move _6) -> [return: bb1, unwind unreachable]; +- _4 = std::intrinsics::unchecked_add::(move _5, move _6) -> [return: bb1, unwind unreachable]; + _4 = AddUnchecked(move _5, move _6); + goto -> bb1; } @@ -80,7 +80,7 @@ _8 = _1; StorageLive(_9); _9 = _2; -- _7 = unchecked_sub::(move _8, move _9) -> [return: bb2, unwind unreachable]; +- _7 = std::intrinsics::unchecked_sub::(move _8, move _9) -> [return: bb2, unwind unreachable]; + _7 = SubUnchecked(move _8, move _9); + goto -> bb2; } @@ -93,7 +93,7 @@ _11 = _1; StorageLive(_12); _12 = _2; -- _10 = unchecked_mul::(move _11, move _12) -> [return: bb3, unwind unreachable]; +- _10 = std::intrinsics::unchecked_mul::(move _11, move _12) -> [return: bb3, unwind unreachable]; + _10 = MulUnchecked(move _11, move _12); + goto -> bb3; } @@ -132,7 +132,7 @@ _20 = _1; StorageLive(_21); _21 = _2; -- _19 = unchecked_shl::(move _20, move _21) -> [return: bb6, unwind unreachable]; +- _19 = std::intrinsics::unchecked_shl::(move _20, move _21) -> [return: bb6, unwind unreachable]; + _19 = ShlUnchecked(move _20, move _21); + goto -> bb6; } @@ -145,7 +145,7 @@ _23 = _1; StorageLive(_24); _24 = _2; -- _22 = unchecked_shr::(move _23, move _24) -> [return: bb7, unwind unreachable]; +- _22 = std::intrinsics::unchecked_shr::(move _23, move _24) -> [return: bb7, unwind unreachable]; + _22 = ShrUnchecked(move _23, move _24); + goto -> bb7; } @@ -158,7 +158,7 @@ _26 = _1; StorageLive(_27); _27 = _3; -- _25 = unchecked_shl::(move _26, move _27) -> [return: bb8, unwind unreachable]; +- _25 = std::intrinsics::unchecked_shl::(move _26, move _27) -> [return: bb8, unwind unreachable]; + _25 = ShlUnchecked(move _26, move _27); + goto -> bb8; } @@ -171,7 +171,7 @@ _29 = _1; StorageLive(_30); _30 = _3; -- _28 = unchecked_shr::(move _29, move _30) -> [return: bb9, unwind unreachable]; +- _28 = std::intrinsics::unchecked_shr::(move _29, move _30) -> [return: bb9, unwind unreachable]; + _28 = ShrUnchecked(move _29, move _30); + goto -> bb9; } diff --git a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff index 3c9694d0370d8..ad4f3bb5f9aaa 100644 --- a/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.unchecked.LowerIntrinsics.panic-unwind.diff @@ -67,7 +67,7 @@ _5 = _1; StorageLive(_6); _6 = _2; -- _4 = unchecked_add::(move _5, move _6) -> [return: bb1, unwind unreachable]; +- _4 = std::intrinsics::unchecked_add::(move _5, move _6) -> [return: bb1, unwind unreachable]; + _4 = AddUnchecked(move _5, move _6); + goto -> bb1; } @@ -80,7 +80,7 @@ _8 = _1; StorageLive(_9); _9 = _2; -- _7 = unchecked_sub::(move _8, move _9) -> [return: bb2, unwind unreachable]; +- _7 = std::intrinsics::unchecked_sub::(move _8, move _9) -> [return: bb2, unwind unreachable]; + _7 = SubUnchecked(move _8, move _9); + goto -> bb2; } @@ -93,7 +93,7 @@ _11 = _1; StorageLive(_12); _12 = _2; -- _10 = unchecked_mul::(move _11, move _12) -> [return: bb3, unwind unreachable]; +- _10 = std::intrinsics::unchecked_mul::(move _11, move _12) -> [return: bb3, unwind unreachable]; + _10 = MulUnchecked(move _11, move _12); + goto -> bb3; } @@ -132,7 +132,7 @@ _20 = _1; StorageLive(_21); _21 = _2; -- _19 = unchecked_shl::(move _20, move _21) -> [return: bb6, unwind unreachable]; +- _19 = std::intrinsics::unchecked_shl::(move _20, move _21) -> [return: bb6, unwind unreachable]; + _19 = ShlUnchecked(move _20, move _21); + goto -> bb6; } @@ -145,7 +145,7 @@ _23 = _1; StorageLive(_24); _24 = _2; -- _22 = unchecked_shr::(move _23, move _24) -> [return: bb7, unwind unreachable]; +- _22 = std::intrinsics::unchecked_shr::(move _23, move _24) -> [return: bb7, unwind unreachable]; + _22 = ShrUnchecked(move _23, move _24); + goto -> bb7; } @@ -158,7 +158,7 @@ _26 = _1; StorageLive(_27); _27 = _3; -- _25 = unchecked_shl::(move _26, move _27) -> [return: bb8, unwind unreachable]; +- _25 = std::intrinsics::unchecked_shl::(move _26, move _27) -> [return: bb8, unwind unreachable]; + _25 = ShlUnchecked(move _26, move _27); + goto -> bb8; } @@ -171,7 +171,7 @@ _29 = _1; StorageLive(_30); _30 = _3; -- _28 = unchecked_shr::(move _29, move _30) -> [return: bb9, unwind unreachable]; +- _28 = std::intrinsics::unchecked_shr::(move _29, move _30) -> [return: bb9, unwind unreachable]; + _28 = ShrUnchecked(move _29, move _30); + goto -> bb9; } diff --git a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff index 2acb193e054d5..720fa0179e147 100644 --- a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-abort.diff @@ -56,7 +56,7 @@ _10 = _1; StorageLive(_11); _11 = _2; -- _9 = wrapping_mul::(move _10, move _11) -> [return: bb3, unwind unreachable]; +- _9 = std::intrinsics::wrapping_mul::(move _10, move _11) -> [return: bb3, unwind unreachable]; + _9 = Mul(move _10, move _11); + goto -> bb3; } diff --git a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff index 2acb193e054d5..720fa0179e147 100644 --- a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.panic-unwind.diff @@ -56,7 +56,7 @@ _10 = _1; StorageLive(_11); _11 = _2; -- _9 = wrapping_mul::(move _10, move _11) -> [return: bb3, unwind unreachable]; +- _9 = std::intrinsics::wrapping_mul::(move _10, move _11) -> [return: bb3, unwind unreachable]; + _9 = Mul(move _10, move _11); + goto -> bb3; }