@@ -510,9 +510,14 @@ 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+ intrinsics:: unchecked_add( self , rhs)
520+ }
516521 }
517522
518523 /// Checked addition with an unsigned integer. Computes `self + rhs`,
@@ -648,9 +653,14 @@ macro_rules! int_impl {
648653 #[ inline( always) ]
649654 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
650655 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+ }
654664 }
655665
656666 /// Checked subtraction with an unsigned integer. Computes `self - rhs`,
@@ -786,9 +796,14 @@ macro_rules! int_impl {
786796 #[ inline( always) ]
787797 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
788798 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+ }
792807 }
793808
794809 /// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`
@@ -1125,9 +1140,15 @@ macro_rules! int_impl {
11251140 #[ inline( always) ]
11261141 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
11271142 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+ }
11311152 }
11321153
11331154 /// Strict negation. Computes `-self`, panicking if `self == MIN`.
@@ -1179,7 +1200,7 @@ macro_rules! int_impl {
11791200 #[ rustc_const_stable( feature = "const_checked_int_methods" , since = "1.47.0" ) ]
11801201 #[ must_use = "this returns the result of the operation, \
11811202 without modifying the original"]
1182- #[ inline]
1203+ #[ inline( always ) ]
11831204 pub const fn checked_shl( self , rhs: u32 ) -> Option <Self > {
11841205 let ( a, b) = self . overflowing_shl( rhs) ;
11851206 if unlikely!( b) { None } else { Some ( a) }
@@ -1241,10 +1262,15 @@ macro_rules! int_impl {
12411262 #[ inline( always) ]
12421263 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
12431264 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.
12461270 // 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+ }
12481274 }
12491275
12501276 /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
@@ -1262,7 +1288,7 @@ macro_rules! int_impl {
12621288 #[ rustc_const_stable( feature = "const_checked_int_methods" , since = "1.47.0" ) ]
12631289 #[ must_use = "this returns the result of the operation, \
12641290 without modifying the original"]
1265- #[ inline]
1291+ #[ inline( always ) ]
12661292 pub const fn checked_shr( self , rhs: u32 ) -> Option <Self > {
12671293 let ( a, b) = self . overflowing_shr( rhs) ;
12681294 if unlikely!( b) { None } else { Some ( a) }
@@ -1324,10 +1350,15 @@ macro_rules! int_impl {
13241350 #[ inline( always) ]
13251351 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
13261352 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.
13291358 // 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+ }
13311362 }
13321363
13331364 /// Checked absolute value. Computes `self.abs()`, returning `None` if
@@ -1991,7 +2022,9 @@ macro_rules! int_impl {
19912022 // SAFETY: the masking by the bitsize of the type ensures that we do not shift
19922023 // out of bounds
19932024 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 ) ) )
19952028 }
19962029 }
19972030
@@ -2021,7 +2054,9 @@ macro_rules! int_impl {
20212054 // SAFETY: the masking by the bitsize of the type ensures that we do not shift
20222055 // out of bounds
20232056 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 ) ) )
20252060 }
20262061 }
20272062
0 commit comments