diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index a88927f0a9c8c..70118e8c0a9f5 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -816,7 +816,9 @@ assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_div_euclid(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { @@ -825,6 +827,20 @@ assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_div_euclid(self, rhs: Self) -> Option { + if rhs == 0 || (self == Self::min_value() && rhs == -1) { + None + } else { + Some(self.div_euclid(rhs)) + } + } + doc_comment! { concat!("Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0` or the division results in overflow. @@ -874,7 +890,9 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_rem_euclid(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { @@ -883,6 +901,20 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_rem_euclid(self, rhs: Self) -> Option { + if rhs == 0 || (self == Self::min_value() && rhs == -1) { + None + } else { + Some(self.rem_euclid(rhs)) + } + } + doc_comment! { concat!("Checked negation. Computes `-self`, returning `None` if `self == MIN`. @@ -1406,11 +1438,23 @@ assert_eq!((-128i8).wrapping_div_euclid(-1), -128); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { self.overflowing_div_euclid(rhs).0 } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + self.overflowing_div_euclid(rhs).0 + } + doc_comment! { concat!("Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the boundary of the type. @@ -1476,11 +1520,23 @@ assert_eq!((-128i8).wrapping_rem_euclid(-1), 0); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { self.overflowing_rem_euclid(rhs).0 } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + self.overflowing_rem_euclid(rhs).0 + } + doc_comment! { concat!("Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary of the type. @@ -1807,7 +1863,9 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi #[stable(feature = "euclidean_division", since = "1.38.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (self, true) } else { @@ -1816,6 +1874,20 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi } } + /// No docs for bootstrap. + #[inline] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg(bootstrap)] + pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + if self == Self::min_value() && rhs == -1 { + (self, true) + } else { + (self.div_euclid(rhs), false) + } + } + doc_comment! { concat!("Calculates the remainder when `self` is divided by `rhs`. @@ -1890,7 +1962,9 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (0, true) } else { @@ -1899,6 +1973,20 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + if self == Self::min_value() && rhs == -1 { + (0, true) + } else { + (self.rem_euclid(rhs), false) + } + } + doc_comment! { concat!("Negates self, overflowing if this is equal to the minimum value. @@ -2130,7 +2218,9 @@ assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn div_euclid(self, rhs: Self) -> Self { let q = self / rhs; if self % rhs < 0 { return if rhs > 0 { q - 1 } else { q + 1 } @@ -2139,6 +2229,21 @@ assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + #[cfg(bootstrap)] + pub fn div_euclid(self, rhs: Self) -> Self { + let q = self / rhs; + if self % rhs < 0 { + return if rhs > 0 { q - 1 } else { q + 1 } + } + q + } + doc_comment! { concat!("Calculates the least nonnegative remainder of `self (mod rhs)`. @@ -2169,7 +2274,9 @@ assert_eq!((-a).rem_euclid(-b), 1); without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn rem_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn rem_euclid(self, rhs: Self) -> Self { let r = self % rhs; if r < 0 { if rhs < 0 { @@ -2183,6 +2290,26 @@ assert_eq!((-a).rem_euclid(-b), 1); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + #[cfg(bootstrap)] + pub fn rem_euclid(self, rhs: Self) -> Self { + let r = self % rhs; + if r < 0 { + if rhs < 0 { + r - rhs + } else { + r + rhs + } + } else { + r + } + } + doc_comment! { concat!("Computes the absolute value of `self`. @@ -3092,7 +3219,9 @@ assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_div_euclid(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { @@ -3101,6 +3230,20 @@ assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_div_euclid(self, rhs: Self) -> Option { + if rhs == 0 { + None + } else { + Some(self.div_euclid(rhs)) + } + } + doc_comment! { concat!("Checked integer remainder. Computes `self % rhs`, returning `None` @@ -3163,7 +3306,9 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_rem_euclid(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { @@ -3172,6 +3317,20 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_rem_euclid(self, rhs: Self) -> Option { + if rhs == 0 { + None + } else { + Some(self.rem_euclid(rhs)) + } + } + doc_comment! { concat!("Checked negation. Computes `-self`, returning `None` unless `self == 0`. @@ -3547,11 +3706,23 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { self / rhs } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + self / rhs + } + doc_comment! { concat!("Wrapping (modular) remainder. Computes `self % rhs`. Wrapped remainder calculation on unsigned types is @@ -3610,11 +3781,23 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { self % rhs } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + self % rhs + } + /// Wrapping (modular) negation. Computes `-self`, /// wrapping around at the boundary of the type. /// @@ -3900,11 +4083,22 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); #[stable(feature = "euclidean_division", since = "1.38.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { (self / rhs, false) } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg(bootstrap)] + pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + (self / rhs, false) + } + doc_comment! { concat!("Calculates the remainder when `self` is divided by `rhs`. @@ -3971,11 +4165,23 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); #[stable(feature = "euclidean_division", since = "1.38.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { (self % rhs, false) } } + /// No docs for bootstrap. + #[inline] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg(bootstrap)] + pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + (self % rhs, false) + } + doc_comment! { concat!("Negates self in an overflowing fashion. @@ -4166,11 +4372,24 @@ assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn div_euclid(self, rhs: Self) -> Self { self / rhs } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + #[cfg(bootstrap)] + pub fn div_euclid(self, rhs: Self) -> Self { + self / rhs + } + doc_comment! { concat!("Calculates the least remainder of `self (mod rhs)`. diff --git a/src/test/ui/consts/const-int-euclidean.rs b/src/test/ui/consts/const-int-euclidean.rs new file mode 100644 index 0000000000000..447d0ef39d344 --- /dev/null +++ b/src/test/ui/consts/const-int-euclidean.rs @@ -0,0 +1,51 @@ +// run-pass +#![feature(const_int_euclidean)] +#![feature(saturating_neg)] + +macro_rules! assert_same_const { + ($(const $ident:ident: $ty:ty = $exp:expr;)+) => { + $(const $ident: $ty = $exp;)+ + + pub fn main() { + $(assert_eq!($exp, $ident);)+ + } + } +} + +assert_same_const! { + const CHECKED_DIV_I32_A: Option = 5i32.checked_div_euclid(7777); + const CHECKED_DIV_I8_A: Option = (-127 as i8).checked_div_euclid(-99); + const CHECKED_DIV_I8_B: Option = (-127 as i8).checked_div_euclid(1); + const CHECKED_DIV_I8_C: Option = i8::min_value().checked_div_euclid(-1); + const CHECKED_DIV_U8_A: Option = 1u8.checked_div_euclid(3); + + const CHECKED_REM_I32_A: Option = 5i32.checked_rem_euclid(7777); + const CHECKED_REM_I8_A: Option = (-127 as i8).checked_rem_euclid(-99); + const CHECKED_REM_I8_B: Option = (-127 as i8).checked_rem_euclid(0); + const CHECKED_REM_I8_C: Option = i8::min_value().checked_rem_euclid(-1); + const CHECKED_REM_U8_A: Option = 1u8.checked_rem_euclid(3); + + const WRAPPING_DIV_I32_A: i32 = 5i32.wrapping_div_euclid(7777); + const WRAPPING_DIV_I8_A: i8 = (-127 as i8).wrapping_div_euclid(-99); + const WRAPPING_DIV_I8_B: i8 = (-127 as i8).wrapping_div_euclid(1); + const WRAPPING_DIV_I8_C: i8 = i8::min_value().wrapping_div_euclid(-1); + const WRAPPING_DIV_U8_A: u8 = 1u8.wrapping_div_euclid(3); + + const WRAPPING_REM_I32_A: i32 = 5i32.wrapping_rem_euclid(7777); + const WRAPPING_REM_I8_A: i8 = (-127 as i8).wrapping_rem_euclid(-99); + const WRAPPING_REM_I8_B: i8 = (-127 as i8).wrapping_rem_euclid(1); + const WRAPPING_REM_I8_C: i8 = i8::min_value().wrapping_rem_euclid(-1); + const WRAPPING_REM_U8_A: u8 = 1u8.wrapping_rem_euclid(3); + + const OVERFLOWING_DIV_I32_A: (i32, bool) = 5i32.overflowing_div_euclid(7777); + const OVERFLOWING_DIV_I8_A: (i8, bool) = (-127 as i8).overflowing_div_euclid(-99); + const OVERFLOWING_DIV_I8_B: (i8, bool) = (-127 as i8).overflowing_div_euclid(1); + const OVERFLOWING_DIV_I8_C: (i8, bool) = i8::min_value().overflowing_div_euclid(-1); + const OVERFLOWING_DIV_U8_A: (u8, bool) = 1u8.overflowing_div_euclid(3); + + const OVERFLOWING_REM_I32_A: (i32, bool) = 5i32.overflowing_rem_euclid(7777); + const OVERFLOWING_REM_I8_A: (i8, bool) = (-127 as i8).overflowing_rem_euclid(-99); + const OVERFLOWING_REM_I8_B: (i8, bool) = (-127 as i8).overflowing_rem_euclid(1); + const OVERFLOWING_REM_I8_C: (i8, bool) = i8::min_value().overflowing_rem_euclid(-1); + const OVERFLOWING_REM_U8_A: (u8, bool) = 1u8.overflowing_rem_euclid(3); +}