@@ -510,9 +510,15 @@ 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
+ let lhs = self ;
520
+ intrinsics:: unchecked_add( lhs, rhs)
521
+ }
516
522
}
517
523
518
524
/// Checked addition with an unsigned integer. Computes `self + rhs`,
@@ -648,9 +654,15 @@ macro_rules! int_impl {
648
654
#[ inline( always) ]
649
655
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
650
656
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) }
657
+ debug_assert_nounwind!(
658
+ !self . overflowing_sub( rhs) . 1 ,
659
+ concat!( stringify!( $SelfT) , "::unchecked_sub cannot overflow" ) ,
660
+ ) ;
661
+ // SAFETY: this is guaranteed to be safe by the caller.
662
+ unsafe {
663
+ let lhs = self ;
664
+ intrinsics:: unchecked_sub( lhs, rhs)
665
+ }
654
666
}
655
667
656
668
/// Checked subtraction with an unsigned integer. Computes `self - rhs`,
@@ -786,9 +798,15 @@ macro_rules! int_impl {
786
798
#[ inline( always) ]
787
799
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
788
800
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) }
801
+ debug_assert_nounwind!(
802
+ !self . overflowing_mul( rhs) . 1 ,
803
+ concat!( stringify!( $SelfT) , "::unchecked_mul cannot overflow" ) ,
804
+ ) ;
805
+ // SAFETY: this is guaranteed to be safe by the caller.
806
+ unsafe {
807
+ let lhs = self ;
808
+ intrinsics:: unchecked_mul( lhs, rhs)
809
+ }
792
810
}
793
811
794
812
/// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`
@@ -1125,9 +1143,15 @@ macro_rules! int_impl {
1125
1143
#[ inline( always) ]
1126
1144
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1127
1145
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 ) }
1146
+ debug_assert_nounwind!(
1147
+ !self . overflowing_neg( ) . 1 ,
1148
+ concat!( stringify!( $SelfT) , "::unchecked_neg cannot overflow" ) ,
1149
+ ) ;
1150
+ // SAFETY: this is guaranteed to be safe by the caller.
1151
+ unsafe {
1152
+ let n = self ;
1153
+ intrinsics:: unchecked_sub( 0 , n)
1154
+ }
1131
1155
}
1132
1156
1133
1157
/// Strict negation. Computes `-self`, panicking if `self == MIN`.
@@ -1179,7 +1203,7 @@ macro_rules! int_impl {
1179
1203
#[ rustc_const_stable( feature = "const_checked_int_methods" , since = "1.47.0" ) ]
1180
1204
#[ must_use = "this returns the result of the operation, \
1181
1205
without modifying the original"]
1182
- #[ inline]
1206
+ #[ inline( always ) ]
1183
1207
pub const fn checked_shl( self , rhs: u32 ) -> Option <Self > {
1184
1208
let ( a, b) = self . overflowing_shl( rhs) ;
1185
1209
if unlikely!( b) { None } else { Some ( a) }
@@ -1241,10 +1265,17 @@ macro_rules! int_impl {
1241
1265
#[ inline( always) ]
1242
1266
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1243
1267
pub const unsafe fn unchecked_shl( self , rhs: u32 ) -> Self {
1244
- // SAFETY: the caller must uphold the safety contract for
1245
- // `unchecked_shl`.
1268
+ debug_assert_nounwind!(
1269
+ rhs < Self :: BITS ,
1270
+ concat!( stringify!( $SelfT) , "::unchecked_shl cannot overflow" ) ,
1271
+ ) ;
1272
+ // SAFETY: this is guaranteed to be safe by the caller.
1246
1273
// Any legal shift amount is losslessly representable in the self type.
1247
- unsafe { intrinsics:: unchecked_shl( self , conv_rhs_for_unchecked_shift!( $SelfT, rhs) ) }
1274
+ unsafe {
1275
+ let lhs = self ;
1276
+ let rhs = conv_rhs_for_unchecked_shift!( $SelfT, rhs) ;
1277
+ intrinsics:: unchecked_shl( lhs, rhs)
1278
+ }
1248
1279
}
1249
1280
1250
1281
/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
@@ -1262,7 +1293,7 @@ macro_rules! int_impl {
1262
1293
#[ rustc_const_stable( feature = "const_checked_int_methods" , since = "1.47.0" ) ]
1263
1294
#[ must_use = "this returns the result of the operation, \
1264
1295
without modifying the original"]
1265
- #[ inline]
1296
+ #[ inline( always ) ]
1266
1297
pub const fn checked_shr( self , rhs: u32 ) -> Option <Self > {
1267
1298
let ( a, b) = self . overflowing_shr( rhs) ;
1268
1299
if unlikely!( b) { None } else { Some ( a) }
@@ -1324,10 +1355,17 @@ macro_rules! int_impl {
1324
1355
#[ inline( always) ]
1325
1356
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1326
1357
pub const unsafe fn unchecked_shr( self , rhs: u32 ) -> Self {
1327
- // SAFETY: the caller must uphold the safety contract for
1328
- // `unchecked_shr`.
1358
+ debug_assert_nounwind!(
1359
+ rhs < Self :: BITS ,
1360
+ concat!( stringify!( $SelfT) , "::unchecked_shr cannot overflow" ) ,
1361
+ ) ;
1362
+ // SAFETY: this is guaranteed to be safe by the caller.
1329
1363
// Any legal shift amount is losslessly representable in the self type.
1330
- unsafe { intrinsics:: unchecked_shr( self , conv_rhs_for_unchecked_shift!( $SelfT, rhs) ) }
1364
+ unsafe {
1365
+ let lhs = self ;
1366
+ let rhs = conv_rhs_for_unchecked_shift!( $SelfT, rhs) ;
1367
+ intrinsics:: unchecked_shr( lhs, rhs)
1368
+ }
1331
1369
}
1332
1370
1333
1371
/// Checked absolute value. Computes `self.abs()`, returning `None` if
@@ -1991,7 +2029,10 @@ macro_rules! int_impl {
1991
2029
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
1992
2030
// out of bounds
1993
2031
unsafe {
1994
- self . unchecked_shl( rhs & ( Self :: BITS - 1 ) )
2032
+ // FIXME: we can't optimize out the extra check here,
2033
+ // so, we can't just call the method for now
2034
+ let rhs = conv_rhs_for_unchecked_shift!( $SelfT, rhs & ( Self :: BITS - 1 ) ) ;
2035
+ intrinsics:: unchecked_shl( self , rhs)
1995
2036
}
1996
2037
}
1997
2038
@@ -2021,7 +2062,10 @@ macro_rules! int_impl {
2021
2062
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
2022
2063
// out of bounds
2023
2064
unsafe {
2024
- self . unchecked_shr( rhs & ( Self :: BITS - 1 ) )
2065
+ // FIXME: we can't optimize out the extra check here,
2066
+ // so, we can't just call the method for now
2067
+ let rhs = conv_rhs_for_unchecked_shift!( $SelfT, rhs & ( Self :: BITS - 1 ) ) ;
2068
+ intrinsics:: unchecked_shr( self , rhs)
2025
2069
}
2026
2070
}
2027
2071
0 commit comments