@@ -475,9 +475,15 @@ macro_rules! int_impl {
475475 #[ inline( always) ]
476476 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
477477 pub const unsafe fn unchecked_add( self , rhs: Self ) -> Self {
478- // SAFETY: the caller must uphold the safety contract for
479- // `unchecked_add`.
480- unsafe { intrinsics:: unchecked_add( self , rhs) }
478+ // SAFETY: this is guaranteed to be safe by the caller.
479+ unsafe {
480+ let lhs = self ;
481+ intrinsics:: assert_unsafe_precondition!(
482+ concat!( stringify!( $SelfT) , "::unchecked_add cannot overflow" ) ,
483+ ( lhs: $SelfT, rhs: $SelfT) => !lhs. overflowing_add( rhs) . 1
484+ ) ;
485+ intrinsics:: unchecked_add( lhs, rhs)
486+ }
481487 }
482488
483489 /// Checked addition with an unsigned integer. Computes `self + rhs`,
@@ -543,9 +549,15 @@ macro_rules! int_impl {
543549 #[ inline( always) ]
544550 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
545551 pub const unsafe fn unchecked_sub( self , rhs: Self ) -> Self {
546- // SAFETY: the caller must uphold the safety contract for
547- // `unchecked_sub`.
548- unsafe { intrinsics:: unchecked_sub( self , rhs) }
552+ // SAFETY: this is guaranteed to be safe by the caller.
553+ unsafe {
554+ let lhs = self ;
555+ intrinsics:: assert_unsafe_precondition!(
556+ concat!( stringify!( $SelfT) , "::unchecked_sub cannot overflow" ) ,
557+ ( lhs: $SelfT, rhs: $SelfT) => !lhs. overflowing_sub( rhs) . 1
558+ ) ;
559+ intrinsics:: unchecked_sub( lhs, rhs)
560+ }
549561 }
550562
551563 /// Checked subtraction with an unsigned integer. Computes `self - rhs`,
@@ -611,9 +623,15 @@ macro_rules! int_impl {
611623 #[ inline( always) ]
612624 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
613625 pub const unsafe fn unchecked_mul( self , rhs: Self ) -> Self {
614- // SAFETY: the caller must uphold the safety contract for
615- // `unchecked_mul`.
616- unsafe { intrinsics:: unchecked_mul( self , rhs) }
626+ // SAFETY: this is guaranteed to be safe by the caller.
627+ unsafe {
628+ let lhs = self ;
629+ intrinsics:: assert_unsafe_precondition!(
630+ concat!( stringify!( $SelfT) , "::unchecked_mul cannot overflow" ) ,
631+ ( lhs: $SelfT, rhs: $SelfT) => !lhs. overflowing_mul( rhs) . 1
632+ ) ;
633+ intrinsics:: unchecked_mul( lhs, rhs)
634+ }
617635 }
618636
619637 /// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`
@@ -760,9 +778,15 @@ macro_rules! int_impl {
760778 #[ inline( always) ]
761779 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
762780 pub const unsafe fn unchecked_neg( self ) -> Self {
763- // SAFETY: the caller must uphold the safety contract for
764- // `unchecked_neg`.
765- unsafe { intrinsics:: unchecked_sub( 0 , self ) }
781+ // SAFETY: this is guaranteed to be safe by the caller.
782+ unsafe {
783+ let n = self ;
784+ intrinsics:: assert_unsafe_precondition!(
785+ concat!( stringify!( $SelfT) , "::unchecked_neg cannot overflow" ) ,
786+ ( n: $SelfT) => !n. overflowing_neg( ) . 1
787+ ) ;
788+ intrinsics:: unchecked_sub( 0 , n)
789+ }
766790 }
767791
768792 /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger
@@ -807,10 +831,17 @@ macro_rules! int_impl {
807831 #[ inline( always) ]
808832 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
809833 pub const unsafe fn unchecked_shl( self , rhs: u32 ) -> Self {
810- // SAFETY: the caller must uphold the safety contract for
811- // `unchecked_shl`.
834+ // SAFETY: this is guaranteed to be safe by the caller.
812835 // Any legal shift amount is losslessly representable in the self type.
813- unsafe { intrinsics:: unchecked_shl( self , conv_rhs_for_unchecked_shift!( $SelfT, rhs) ) }
836+ unsafe {
837+ let lhs = self ;
838+ intrinsics:: assert_unsafe_precondition!(
839+ concat!( stringify!( $SelfT) , "::unchecked_shl cannot overflow" ) ,
840+ ( rhs: u32 ) => rhs < <$SelfT>:: BITS
841+ ) ;
842+ let rhs = conv_rhs_for_unchecked_shift!( $SelfT, rhs) ;
843+ intrinsics:: unchecked_shl( lhs, rhs)
844+ }
814845 }
815846
816847 /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
@@ -855,10 +886,17 @@ macro_rules! int_impl {
855886 #[ inline( always) ]
856887 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
857888 pub const unsafe fn unchecked_shr( self , rhs: u32 ) -> Self {
858- // SAFETY: the caller must uphold the safety contract for
859- // `unchecked_shr`.
889+ // SAFETY: this is guaranteed to be safe by the caller.
860890 // Any legal shift amount is losslessly representable in the self type.
861- unsafe { intrinsics:: unchecked_shr( self , conv_rhs_for_unchecked_shift!( $SelfT, rhs) ) }
891+ unsafe {
892+ let lhs = self ;
893+ intrinsics:: assert_unsafe_precondition!(
894+ concat!( stringify!( $SelfT) , "::unchecked_shr cannot overflow" ) ,
895+ ( rhs: u32 ) => rhs < <$SelfT>:: BITS
896+ ) ;
897+ let rhs = conv_rhs_for_unchecked_shift!( $SelfT, rhs) ;
898+ intrinsics:: unchecked_shr( lhs, rhs)
899+ }
862900 }
863901
864902 /// Checked absolute value. Computes `self.abs()`, returning `None` if
0 commit comments