@@ -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,18 @@ 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
+ assert_unsafe_precondition!(
1145
+ check_language_ub,
1146
+ concat!( stringify!( $SelfT) , "::unchecked_neg cannot overflow" ) ,
1147
+ (
1148
+ lhs: $SelfT = self ,
1149
+ ) => !lhs. overflowing_neg( ) . 1 ,
1150
+ ) ;
1151
+
1152
+ // SAFETY: this is guaranteed to be safe by the caller.
1153
+ unsafe {
1154
+ intrinsics:: unchecked_sub( 0 , self )
1155
+ }
1117
1156
}
1118
1157
1119
1158
/// Strict negation. Computes `-self`, panicking if `self == MIN`.
@@ -1235,9 +1274,19 @@ macro_rules! int_impl {
1235
1274
}
1236
1275
#[ cfg( not( bootstrap) ) ]
1237
1276
{
1238
- // SAFETY: the caller must uphold the safety contract for
1239
- // `unchecked_shl`.
1240
- unsafe { intrinsics:: unchecked_shl( self , rhs) }
1277
+ assert_unsafe_precondition!(
1278
+ check_language_ub,
1279
+ concat!( stringify!( $SelfT) , "::unchecked_shl cannot overflow" ) ,
1280
+ (
1281
+ rhs: u32 = rhs,
1282
+ bits: u32 = Self :: BITS ,
1283
+ ) => rhs < bits,
1284
+ ) ;
1285
+
1286
+ // SAFETY: this is guaranteed to be safe by the caller.
1287
+ unsafe {
1288
+ intrinsics:: unchecked_shl( self , rhs)
1289
+ }
1241
1290
}
1242
1291
}
1243
1292
@@ -1326,9 +1375,20 @@ macro_rules! int_impl {
1326
1375
}
1327
1376
#[ cfg( not( bootstrap) ) ]
1328
1377
{
1329
- // SAFETY: the caller must uphold the safety contract for
1330
- // `unchecked_shr`.
1331
- unsafe { intrinsics:: unchecked_shr( self , rhs) }
1378
+ assert_unsafe_precondition!(
1379
+ check_language_ub,
1380
+ concat!( stringify!( $SelfT) , "::unchecked_shr cannot overflow" ) ,
1381
+ (
1382
+ rhs: u32 = rhs,
1383
+ bits: u32 = Self :: BITS ,
1384
+ ) => rhs < bits,
1385
+ ) ;
1386
+
1387
+ // SAFETY: this is guaranteed to be safe by the caller.
1388
+ // Any legal shift amount is losslessly representable in the self type.
1389
+ unsafe {
1390
+ intrinsics:: unchecked_shr( self , rhs)
1391
+ }
1332
1392
}
1333
1393
}
1334
1394
0 commit comments