Auto merge of #121571 - clarfonthey:unchecked-math-preconditions, r=s… · model-checking/verify-rust-std@23bb5bc
@@ -488,9 +488,19 @@ macro_rules! int_impl {
488488 #[inline(always)]
489489 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
490490pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
491-// SAFETY: the caller must uphold the safety contract for
492-// `unchecked_add`.
493-unsafe { intrinsics::unchecked_add(self, rhs) }
491+ assert_unsafe_precondition!(
492+ check_language_ub,
493+ concat!(stringify!($SelfT), "::unchecked_add cannot overflow"),
494+(
495+ lhs: $SelfT = self,
496+ rhs: $SelfT = rhs,
497+) => !lhs.overflowing_add(rhs).1,
498+);
499+500+// SAFETY: this is guaranteed to be safe by the caller.
501+unsafe {
502+ intrinsics::unchecked_add(self, rhs)
503+}
494504}
495505496506/// Checked addition with an unsigned integer. Computes `self + rhs`,
@@ -630,9 +640,19 @@ macro_rules! int_impl {
630640 #[inline(always)]
631641 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
632642pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self {
633-// SAFETY: the caller must uphold the safety contract for
634-// `unchecked_sub`.
635-unsafe { intrinsics::unchecked_sub(self, rhs) }
643+ assert_unsafe_precondition!(
644+ check_language_ub,
645+ concat!(stringify!($SelfT), "::unchecked_sub cannot overflow"),
646+(
647+ lhs: $SelfT = self,
648+ rhs: $SelfT = rhs,
649+) => !lhs.overflowing_sub(rhs).1,
650+);
651+652+// SAFETY: this is guaranteed to be safe by the caller.
653+unsafe {
654+ intrinsics::unchecked_sub(self, rhs)
655+}
636656}
637657638658/// Checked subtraction with an unsigned integer. Computes `self - rhs`,
@@ -772,9 +792,19 @@ macro_rules! int_impl {
772792 #[inline(always)]
773793 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
774794pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self {
775-// SAFETY: the caller must uphold the safety contract for
776-// `unchecked_mul`.
777-unsafe { intrinsics::unchecked_mul(self, rhs) }
795+ assert_unsafe_precondition!(
796+ check_language_ub,
797+ concat!(stringify!($SelfT), "::unchecked_mul cannot overflow"),
798+(
799+ lhs: $SelfT = self,
800+ rhs: $SelfT = rhs,
801+) => !lhs.overflowing_mul(rhs).1,
802+);
803+804+// SAFETY: this is guaranteed to be safe by the caller.
805+unsafe {
806+ intrinsics::unchecked_mul(self, rhs)
807+}
778808}
779809780810/// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`
@@ -1111,9 +1141,22 @@ macro_rules! int_impl {
11111141 #[inline(always)]
11121142 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
11131143pub const unsafe fn unchecked_neg(self) -> Self {
1114-// SAFETY: the caller must uphold the safety contract for
1115-// `unchecked_neg`.
1116-unsafe { intrinsics::unchecked_sub(0, self) }
1144+// ICE resolved by #125184 isn't in bootstrap compiler
1145+ #[cfg(not(bootstrap))]
1146+{
1147+ assert_unsafe_precondition!(
1148+ check_language_ub,
1149+ concat!(stringify!($SelfT), "::unchecked_neg cannot overflow"),
1150+(
1151+ lhs: $SelfT = self,
1152+) => !lhs.overflowing_neg().1,
1153+);
1154+}
1155+1156+// SAFETY: this is guaranteed to be safe by the caller.
1157+unsafe {
1158+ intrinsics::unchecked_sub(0, self)
1159+}
11171160}
1118116111191162/// Strict negation. Computes `-self`, panicking if `self == MIN`.
@@ -1234,9 +1277,19 @@ macro_rules! int_impl {
12341277 #[inline(always)]
12351278 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
12361279pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
1237-// SAFETY: the caller must uphold the safety contract for
1238-// `unchecked_shl`.
1239-unsafe { intrinsics::unchecked_shl(self, rhs) }
1280+ assert_unsafe_precondition!(
1281+ check_language_ub,
1282+ concat!(stringify!($SelfT), "::unchecked_shl cannot overflow"),
1283+(
1284+ rhs: u32 = rhs,
1285+ bits: u32 = Self::BITS,
1286+) => rhs < bits,
1287+);
1288+1289+// SAFETY: this is guaranteed to be safe by the caller.
1290+unsafe {
1291+ intrinsics::unchecked_shl(self, rhs)
1292+}
12401293}
1241129412421295/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
@@ -1323,9 +1376,19 @@ macro_rules! int_impl {
13231376 #[inline(always)]
13241377 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
13251378pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
1326-// SAFETY: the caller must uphold the safety contract for
1327-// `unchecked_shr`.
1328-unsafe { intrinsics::unchecked_shr(self, rhs) }
1379+ assert_unsafe_precondition!(
1380+ check_language_ub,
1381+ concat!(stringify!($SelfT), "::unchecked_shr cannot overflow"),
1382+(
1383+ rhs: u32 = rhs,
1384+ bits: u32 = Self::BITS,
1385+) => rhs < bits,
1386+);
1387+1388+// SAFETY: this is guaranteed to be safe by the caller.
1389+unsafe {
1390+ intrinsics::unchecked_shr(self, rhs)
1391+}
13291392}
1330139313311394/// Checked absolute value. Computes `self.abs()`, returning `None` if