@@ -510,9 +510,15 @@ macro_rules! int_impl {
510510 #[ inline( always) ]
511511 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
512512 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+ }
516522 }
517523
518524 /// Checked addition with an unsigned integer. Computes `self + rhs`,
@@ -648,9 +654,15 @@ macro_rules! int_impl {
648654 #[ inline( always) ]
649655 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
650656 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+ }
654666 }
655667
656668 /// Checked subtraction with an unsigned integer. Computes `self - rhs`,
@@ -786,9 +798,15 @@ macro_rules! int_impl {
786798 #[ inline( always) ]
787799 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
788800 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+ }
792810 }
793811
794812 /// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`
@@ -1125,9 +1143,15 @@ macro_rules! int_impl {
11251143 #[ inline( always) ]
11261144 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
11271145 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+ }
11311155 }
11321156
11331157 /// Strict negation. Computes `-self`, panicking if `self == MIN`.
@@ -1179,7 +1203,7 @@ macro_rules! int_impl {
11791203 #[ rustc_const_stable( feature = "const_checked_int_methods" , since = "1.47.0" ) ]
11801204 #[ must_use = "this returns the result of the operation, \
11811205 without modifying the original"]
1182- #[ inline]
1206+ #[ inline( always ) ]
11831207 pub const fn checked_shl( self , rhs: u32 ) -> Option <Self > {
11841208 let ( a, b) = self . overflowing_shl( rhs) ;
11851209 if unlikely!( b) { None } else { Some ( a) }
@@ -1241,10 +1265,17 @@ macro_rules! int_impl {
12411265 #[ inline( always) ]
12421266 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
12431267 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.
12461273 // 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+ }
12481279 }
12491280
12501281 /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
@@ -1262,7 +1293,7 @@ macro_rules! int_impl {
12621293 #[ rustc_const_stable( feature = "const_checked_int_methods" , since = "1.47.0" ) ]
12631294 #[ must_use = "this returns the result of the operation, \
12641295 without modifying the original"]
1265- #[ inline]
1296+ #[ inline( always ) ]
12661297 pub const fn checked_shr( self , rhs: u32 ) -> Option <Self > {
12671298 let ( a, b) = self . overflowing_shr( rhs) ;
12681299 if unlikely!( b) { None } else { Some ( a) }
@@ -1324,10 +1355,17 @@ macro_rules! int_impl {
13241355 #[ inline( always) ]
13251356 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
13261357 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.
13291363 // 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+ }
13311369 }
13321370
13331371 /// Checked absolute value. Computes `self.abs()`, returning `None` if
@@ -1991,7 +2029,10 @@ macro_rules! int_impl {
19912029 // SAFETY: the masking by the bitsize of the type ensures that we do not shift
19922030 // out of bounds
19932031 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)
19952036 }
19962037 }
19972038
@@ -2021,7 +2062,10 @@ macro_rules! int_impl {
20212062 // SAFETY: the masking by the bitsize of the type ensures that we do not shift
20222063 // out of bounds
20232064 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)
20252069 }
20262070 }
20272071
0 commit comments