@@ -510,9 +510,14 @@ macro_rules! int_impl {
510
510
#[ inline( always) ]
511
511
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
512
512
pub const unsafe fn unchecked_add( self , rhs: Self ) -> Self {
513
- // SAFETY: the caller must uphold the safety contract for
514
- // `unchecked_add`.
515
- unsafe { intrinsics:: unchecked_add( self , rhs) }
513
+ debug_assert_nounwind!(
514
+ !self . overflowing_add( rhs) . 1 ,
515
+ concat!( stringify!( $SelfT) , "::unchecked_add cannot overflow" ) ,
516
+ ) ;
517
+ // SAFETY: this is guaranteed to be safe by the caller.
518
+ unsafe {
519
+ intrinsics:: unchecked_add( self , rhs)
520
+ }
516
521
}
517
522
518
523
/// Checked addition with an unsigned integer. Computes `self + rhs`,
@@ -648,9 +653,14 @@ macro_rules! int_impl {
648
653
#[ inline( always) ]
649
654
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
650
655
pub const unsafe fn unchecked_sub( self , rhs: Self ) -> Self {
651
- // SAFETY: the caller must uphold the safety contract for
652
- // `unchecked_sub`.
653
- unsafe { intrinsics:: unchecked_sub( self , rhs) }
656
+ debug_assert_nounwind!(
657
+ !self . overflowing_sub( rhs) . 1 ,
658
+ concat!( stringify!( $SelfT) , "::unchecked_sub cannot overflow" ) ,
659
+ ) ;
660
+ // SAFETY: this is guaranteed to be safe by the caller.
661
+ unsafe {
662
+ intrinsics:: unchecked_sub( self , rhs)
663
+ }
654
664
}
655
665
656
666
/// Checked subtraction with an unsigned integer. Computes `self - rhs`,
@@ -786,9 +796,14 @@ macro_rules! int_impl {
786
796
#[ inline( always) ]
787
797
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
788
798
pub const unsafe fn unchecked_mul( self , rhs: Self ) -> Self {
789
- // SAFETY: the caller must uphold the safety contract for
790
- // `unchecked_mul`.
791
- unsafe { intrinsics:: unchecked_mul( self , rhs) }
799
+ debug_assert_nounwind!(
800
+ !self . overflowing_mul( rhs) . 1 ,
801
+ concat!( stringify!( $SelfT) , "::unchecked_mul cannot overflow" ) ,
802
+ ) ;
803
+ // SAFETY: this is guaranteed to be safe by the caller.
804
+ unsafe {
805
+ intrinsics:: unchecked_mul( self , rhs)
806
+ }
792
807
}
793
808
794
809
/// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`
@@ -1125,9 +1140,15 @@ macro_rules! int_impl {
1125
1140
#[ inline( always) ]
1126
1141
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1127
1142
pub const unsafe fn unchecked_neg( self ) -> Self {
1128
- // SAFETY: the caller must uphold the safety contract for
1129
- // `unchecked_neg`.
1130
- unsafe { intrinsics:: unchecked_sub( 0 , self ) }
1143
+ debug_assert_nounwind!(
1144
+ !self . overflowing_neg( ) . 1 ,
1145
+ concat!( stringify!( $SelfT) , "::unchecked_neg cannot overflow" ) ,
1146
+ ) ;
1147
+ // SAFETY: this is guaranteed to be safe by the caller.
1148
+ unsafe {
1149
+ let n = self ;
1150
+ intrinsics:: unchecked_sub( 0 , n)
1151
+ }
1131
1152
}
1132
1153
1133
1154
/// Strict negation. Computes `-self`, panicking if `self == MIN`.
@@ -1179,7 +1200,7 @@ macro_rules! int_impl {
1179
1200
#[ rustc_const_stable( feature = "const_checked_int_methods" , since = "1.47.0" ) ]
1180
1201
#[ must_use = "this returns the result of the operation, \
1181
1202
without modifying the original"]
1182
- #[ inline]
1203
+ #[ inline( always ) ]
1183
1204
pub const fn checked_shl( self , rhs: u32 ) -> Option <Self > {
1184
1205
let ( a, b) = self . overflowing_shl( rhs) ;
1185
1206
if unlikely!( b) { None } else { Some ( a) }
@@ -1241,10 +1262,15 @@ macro_rules! int_impl {
1241
1262
#[ inline( always) ]
1242
1263
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1243
1264
pub const unsafe fn unchecked_shl( self , rhs: u32 ) -> Self {
1244
- // SAFETY: the caller must uphold the safety contract for
1245
- // `unchecked_shl`.
1265
+ debug_assert_nounwind!(
1266
+ rhs < Self :: BITS ,
1267
+ concat!( stringify!( $SelfT) , "::unchecked_shl cannot overflow" ) ,
1268
+ ) ;
1269
+ // SAFETY: this is guaranteed to be safe by the caller.
1246
1270
// Any legal shift amount is losslessly representable in the self type.
1247
- unsafe { intrinsics:: unchecked_shl( self , conv_rhs_for_unchecked_shift!( $SelfT, rhs) ) }
1271
+ unsafe {
1272
+ intrinsics:: unchecked_shl( self , conv_rhs_for_unchecked_shift!( $SelfT, rhs) )
1273
+ }
1248
1274
}
1249
1275
1250
1276
/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
@@ -1262,7 +1288,7 @@ macro_rules! int_impl {
1262
1288
#[ rustc_const_stable( feature = "const_checked_int_methods" , since = "1.47.0" ) ]
1263
1289
#[ must_use = "this returns the result of the operation, \
1264
1290
without modifying the original"]
1265
- #[ inline]
1291
+ #[ inline( always ) ]
1266
1292
pub const fn checked_shr( self , rhs: u32 ) -> Option <Self > {
1267
1293
let ( a, b) = self . overflowing_shr( rhs) ;
1268
1294
if unlikely!( b) { None } else { Some ( a) }
@@ -1324,10 +1350,15 @@ macro_rules! int_impl {
1324
1350
#[ inline( always) ]
1325
1351
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1326
1352
pub const unsafe fn unchecked_shr( self , rhs: u32 ) -> Self {
1327
- // SAFETY: the caller must uphold the safety contract for
1328
- // `unchecked_shr`.
1353
+ debug_assert_nounwind!(
1354
+ rhs < Self :: BITS ,
1355
+ concat!( stringify!( $SelfT) , "::unchecked_shr cannot overflow" ) ,
1356
+ ) ;
1357
+ // SAFETY: this is guaranteed to be safe by the caller.
1329
1358
// Any legal shift amount is losslessly representable in the self type.
1330
- unsafe { intrinsics:: unchecked_shr( self , conv_rhs_for_unchecked_shift!( $SelfT, rhs) ) }
1359
+ unsafe {
1360
+ intrinsics:: unchecked_shr( self , conv_rhs_for_unchecked_shift!( $SelfT, rhs) )
1361
+ }
1331
1362
}
1332
1363
1333
1364
/// Checked absolute value. Computes `self.abs()`, returning `None` if
@@ -1991,7 +2022,9 @@ macro_rules! int_impl {
1991
2022
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
1992
2023
// out of bounds
1993
2024
unsafe {
1994
- self . unchecked_shl( rhs & ( Self :: BITS - 1 ) )
2025
+ // FIXME: we can't optimize out the extra check here,
2026
+ // so, we can't just call the method for now
2027
+ intrinsics:: unchecked_shl( self , conv_rhs_for_unchecked_shift!( $SelfT, rhs & ( Self :: BITS - 1 ) ) )
1995
2028
}
1996
2029
}
1997
2030
@@ -2021,7 +2054,9 @@ macro_rules! int_impl {
2021
2054
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
2022
2055
// out of bounds
2023
2056
unsafe {
2024
- self . unchecked_shr( rhs & ( Self :: BITS - 1 ) )
2057
+ // FIXME: we can't optimize out the extra check here,
2058
+ // so, we can't just call the method for now
2059
+ intrinsics:: unchecked_shr( self , conv_rhs_for_unchecked_shift!( $SelfT, rhs & ( Self :: BITS - 1 ) ) )
2025
2060
}
2026
2061
}
2027
2062
0 commit comments