diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 74221e2168751..f5314baf55a55 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -898,6 +898,39 @@ macro_rules! int_impl { } } + /// Unchecked integer division. Computes `self / rhs`, assuming `rhs != 0` and + /// overflow cannot occur. + /// + /// Calling `x.unchecked_div(y)` is semantically equivalent to calling + /// `x.`[`checked_div`]`(y).`[`unwrap_unchecked`]`()`. + /// + /// # Safety + /// + /// This results in undefined behavior when `rhs == 0` or + #[doc = concat!("(`self == ", stringify!($SelfT), "::MIN` and `rhs == -1`),")] + /// i.e. when [`checked_div`] would return `None`. + /// + /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked + #[doc = concat!("[`checked_div`]: ", stringify!($SelfT), "::checked_div")] + #[doc = concat!("[`wrapping_div`]: ", stringify!($SelfT), "::wrapping_div")] + #[unstable(feature = "unchecked_div_rem", issue = "136716")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_div(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_div cannot overflow or divide by zero"), + ( + lhs: $SelfT = self, + rhs: $SelfT = rhs + ) => rhs != 0 && !lhs.overflowing_div(rhs).1, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { intrinsics::unchecked_div(self, rhs) } + } + /// Strict integer division. Computes `self / rhs`, panicking /// if overflow occurred. /// @@ -1044,6 +1077,36 @@ macro_rules! int_impl { } } + /// Unchecked integer remainder. Computes `self % rhs`, assuming `rhs != 0` + /// and overflow cannot occur. + /// + /// # Safety + /// + /// This results in undefined behavior when `rhs == 0` or + #[doc = concat!("(`self == ", stringify!($SelfT), "::MIN` and `rhs == -1`),")] + /// i.e. when [`checked_rem`] would return `None`. + /// + #[doc = concat!("[`checked_rem`]: ", stringify!($SelfT), "::checked_rem")] + #[unstable(feature = "unchecked_div_rem", issue = "136716")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_rem(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_rem cannot overflow or divide by zero"), + ( + lhs: $SelfT = self, + rhs: $SelfT = rhs + ) => rhs != 0 && !lhs.overflowing_rem(rhs).1, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_rem(self, rhs) + } + } + /// Strict integer remainder. Computes `self % rhs`, panicking if /// the division results in overflow. /// diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 2682273b7f185..6d5f32e321348 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1017,6 +1017,36 @@ macro_rules! uint_impl { } } + /// Unchecked integer division. Computes `self / rhs`, assuming `rhs` is not zero. + /// + /// Calling `x.unchecked_div(y)` is semantically equivalent to calling + /// `x.`[`checked_div`]`(y).`[`unwrap_unchecked`]`()`. + /// + /// # Safety + /// + /// This results in undefined behavior when `rhs == 0`, + /// i.e. when [`checked_div`] would return `None`. + /// + /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked + #[doc = concat!("[`checked_div`]: ", stringify!($SelfT), "::checked_div")] + #[doc = concat!("[`wrapping_div`]: ", stringify!($SelfT), "::wrapping_div")] + #[unstable(feature = "unchecked_div_rem", issue = "136716")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_div(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_div cannot divide by zero"), + ( + rhs: $SelfT = rhs + ) => rhs != 0, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { intrinsics::unchecked_div(self, rhs) } + } + /// Strict integer division. Computes `self / rhs`. /// /// Strict division on unsigned types is just normal division. There's no @@ -1136,6 +1166,33 @@ macro_rules! uint_impl { } } + /// Unchecked integer remainder. Computes `self % rhs`, assuming `rhs` is not zero. + /// + /// # Safety + /// + /// This results in undefined behavior when `rhs == 0`, + /// i.e. when [`checked_rem`] would return `None`. + /// + #[doc = concat!("[`checked_rem`]: ", stringify!($SelfT), "::checked_rem")] + #[unstable(feature = "unchecked_div_rem", issue = "136716")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_rem(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_rem cannot divide by zero"), + ( + rhs: $SelfT = rhs + ) => rhs != 0, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_rem(self, rhs) + } + } + /// Strict integer remainder. Computes `self % rhs`. /// /// Strict remainder calculation on unsigned types is just the regular