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

490490

pub 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

632642

pub 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

774794

pub 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

11131143

pub 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

12361279

pub 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

13251378

pub 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