diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index c3460a6409069..672e56a0e56d6 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1019,25 +1019,29 @@ macro_rules! int_impl { } } - /// Checked integer division without remainder. Computes `self / rhs`. + /// Integer division without remainder. Computes `self / rhs`, returning `None` if `self % rhs != 0`. /// /// # Panics /// - /// This function will panic if `rhs == 0`, the division results in overflow, - /// or `self % rhs != 0`. + /// This function will panic if `rhs == 0`. + /// + /// ## Overflow behavior + /// + /// On overflow, this function will panic if overflow checks are enabled (default in debug + /// mode) and wrap if overflow checks are disabled (default in release mode). /// /// # Examples /// /// ``` /// #![feature(exact_div)] - #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), 32);")] - #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), 2);")] - #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).exact_div(-1), ", stringify!($Max), ");")] + #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), Some(32));")] + #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), Some(2));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).exact_div(-1), Some(", stringify!($Max), "));")] + #[doc = concat!("assert_eq!(65", stringify!($SelfT), ".exact_div(2), None);")] /// ``` - /// /// ```should_panic /// #![feature(exact_div)] - #[doc = concat!("let _ = 65", stringify!($SelfT), ".exact_div(2);")] + #[doc = concat!("let _ = 64", stringify!($SelfT),".exact_div(0);")] /// ``` /// ```should_panic /// #![feature(exact_div)] @@ -1050,10 +1054,12 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub const fn exact_div(self, rhs: Self) -> Self { - match self.checked_exact_div(rhs) { - Some(x) => x, - None => panic!("Failed to divide without remainder"), + #[rustc_inherit_overflow_checks] + pub const fn exact_div(self, rhs: Self) -> Option { + if self % rhs != 0 { + None + } else { + Some(self / rhs) } } diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index b5b768cf677aa..1f05f883c93fa 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1249,23 +1249,19 @@ macro_rules! uint_impl { } } - /// Checked integer division without remainder. Computes `self / rhs`. + /// Integer division without remainder. Computes `self / rhs`, returning `None` if `self % rhs != 0`. /// /// # Panics /// - /// This function will panic if `rhs == 0` or `self % rhs != 0`. + /// This function will panic if `rhs == 0`. /// /// # Examples /// /// ``` /// #![feature(exact_div)] - #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), 32);")] - #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), 2);")] - /// ``` - /// - /// ```should_panic - /// #![feature(exact_div)] - #[doc = concat!("let _ = 65", stringify!($SelfT), ".exact_div(2);")] + #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), Some(32));")] + #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), Some(2));")] + #[doc = concat!("assert_eq!(65", stringify!($SelfT), ".exact_div(2), None);")] /// ``` #[unstable( feature = "exact_div", @@ -1274,10 +1270,12 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub const fn exact_div(self, rhs: Self) -> Self { - match self.checked_exact_div(rhs) { - Some(x) => x, - None => panic!("Failed to divide without remainder"), + #[rustc_inherit_overflow_checks] + pub const fn exact_div(self, rhs: Self) -> Option { + if self % rhs != 0 { + None + } else { + Some(self / rhs) } } diff --git a/library/coretests/tests/num/int_macros.rs b/library/coretests/tests/num/int_macros.rs index 1611a6466f5ab..e640b7853bd94 100644 --- a/library/coretests/tests/num/int_macros.rs +++ b/library/coretests/tests/num/int_macros.rs @@ -741,22 +741,23 @@ macro_rules! int_module { fn test_exact_div() { // 42 / 6 assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND1, EXACT_DIV_SUCCESS_DIVISOR1), Some(EXACT_DIV_SUCCESS_QUOTIENT1)); - assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND1, EXACT_DIV_SUCCESS_DIVISOR1), EXACT_DIV_SUCCESS_QUOTIENT1); + assert_eq_const_safe!(Option<$T>: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND1, EXACT_DIV_SUCCESS_DIVISOR1), Some(EXACT_DIV_SUCCESS_QUOTIENT1)); // 18 / 3 assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND2, EXACT_DIV_SUCCESS_DIVISOR2), Some(EXACT_DIV_SUCCESS_QUOTIENT2)); - assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND2, EXACT_DIV_SUCCESS_DIVISOR2), EXACT_DIV_SUCCESS_QUOTIENT2); + assert_eq_const_safe!(Option<$T>: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND2, EXACT_DIV_SUCCESS_DIVISOR2), Some(EXACT_DIV_SUCCESS_QUOTIENT2)); // -91 / 13 assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND3, EXACT_DIV_SUCCESS_DIVISOR3), Some(EXACT_DIV_SUCCESS_QUOTIENT3)); - assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND3, EXACT_DIV_SUCCESS_DIVISOR3), EXACT_DIV_SUCCESS_QUOTIENT3); + assert_eq_const_safe!(Option<$T>: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND3, EXACT_DIV_SUCCESS_DIVISOR3), Some(EXACT_DIV_SUCCESS_QUOTIENT3)); // -57 / -3 assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND4, EXACT_DIV_SUCCESS_DIVISOR4), Some(EXACT_DIV_SUCCESS_QUOTIENT4)); - assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND4, EXACT_DIV_SUCCESS_DIVISOR4), EXACT_DIV_SUCCESS_QUOTIENT4); + assert_eq_const_safe!(Option<$T>: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND4, EXACT_DIV_SUCCESS_DIVISOR4), Some(EXACT_DIV_SUCCESS_QUOTIENT4)); // failures assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(1, 2), None); + assert_eq_const_safe!(Option<$T>: <$T>::exact_div(1, 2), None); assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(<$T>::MIN, -1), None); assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(0, 0), None); } diff --git a/library/coretests/tests/num/uint_macros.rs b/library/coretests/tests/num/uint_macros.rs index 63be8a45b5cfd..c1cfc448f14f5 100644 --- a/library/coretests/tests/num/uint_macros.rs +++ b/library/coretests/tests/num/uint_macros.rs @@ -606,14 +606,15 @@ macro_rules! uint_module { fn test_exact_div() { // 42 / 6 assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND1, EXACT_DIV_SUCCESS_DIVISOR1), Some(EXACT_DIV_SUCCESS_QUOTIENT1)); - assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND1, EXACT_DIV_SUCCESS_DIVISOR1), EXACT_DIV_SUCCESS_QUOTIENT1); + assert_eq_const_safe!(Option<$T>: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND1, EXACT_DIV_SUCCESS_DIVISOR1), Some(EXACT_DIV_SUCCESS_QUOTIENT1)); // 18 / 3 assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND2, EXACT_DIV_SUCCESS_DIVISOR2), Some(EXACT_DIV_SUCCESS_QUOTIENT2)); - assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND2, EXACT_DIV_SUCCESS_DIVISOR2), EXACT_DIV_SUCCESS_QUOTIENT2); + assert_eq_const_safe!(Option<$T>: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND2, EXACT_DIV_SUCCESS_DIVISOR2), Some(EXACT_DIV_SUCCESS_QUOTIENT2)); // failures assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(1, 2), None); + assert_eq_const_safe!(Option<$T>: <$T>::exact_div(1, 2), None); assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(0, 0), None); } }