@@ -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 }
495505
496506 /// 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 }
637657
638658 /// 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 }
779809
780810 /// 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 }
11181161
11191162 /// 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 }
12411294
12421295 /// 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 }
13301393
13311394 /// Checked absolute value. Computes `self.abs()`, returning `None` if
0 commit comments