@@ -488,9 +488,19 @@ macro_rules! int_impl {
488
488
#[ inline( always) ]
489
489
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
490
490
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
+ }
494
504
}
495
505
496
506
/// Checked addition with an unsigned integer. Computes `self + rhs`,
@@ -630,9 +640,19 @@ macro_rules! int_impl {
630
640
#[ inline( always) ]
631
641
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
632
642
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
+ }
636
656
}
637
657
638
658
/// Checked subtraction with an unsigned integer. Computes `self - rhs`,
@@ -772,9 +792,19 @@ macro_rules! int_impl {
772
792
#[ inline( always) ]
773
793
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
774
794
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
+ }
778
808
}
779
809
780
810
/// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`
@@ -1111,9 +1141,22 @@ macro_rules! int_impl {
1111
1141
#[ inline( always) ]
1112
1142
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1113
1143
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
+ }
1117
1160
}
1118
1161
1119
1162
/// Strict negation. Computes `-self`, panicking if `self == MIN`.
@@ -1234,9 +1277,19 @@ macro_rules! int_impl {
1234
1277
#[ inline( always) ]
1235
1278
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1236
1279
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
+ }
1240
1293
}
1241
1294
1242
1295
/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
@@ -1323,9 +1376,19 @@ macro_rules! int_impl {
1323
1376
#[ inline( always) ]
1324
1377
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1325
1378
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
+ }
1329
1392
}
1330
1393
1331
1394
/// Checked absolute value. Computes `self.abs()`, returning `None` if
0 commit comments