@@ -6,6 +6,26 @@ mod private {
66 /// which allows potentially adding more trait methods after the trait is `#[stable]`.
77 #[ unstable( feature = "convert_float_to_int" , issue = "67057" ) ]
88 pub trait Sealed { }
9+
10+ /// This trait being unreachable from outside the crate prevents other
11+ /// implementations of the integer cast traits.
12+ ///
13+ /// `Cast<T> : SealedCast<T>` avoids the orphan rule, which would otherwise
14+ /// allow e.g. implementing `Cast<Foo>` for `u8`.
15+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
16+ pub trait SealedCast < T > : Sealed { }
17+
18+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
19+ impl < T : Sealed , U : Sealed > SealedCast < T > for U { }
20+
21+ macro_rules! impl_sealed_int {
22+ ( [ $( $T: ty) ,* ] ) => { $(
23+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
24+ impl Sealed for $T { }
25+ ) * } ;
26+ }
27+
28+ impl_sealed_int ! ( [ u8 , u16 , u32 , u64 , u128 , usize , i8 , i16 , i32 , i64 , i128 , isize ] ) ;
929}
1030
1131/// Supporting trait for inherent methods of `f32` and `f64` such as `to_int_unchecked`.
@@ -640,3 +660,98 @@ impl_nonzero_int_try_from_nonzero_int!(i32 => u8, u16, u32, u64, u128, usize);
640660impl_nonzero_int_try_from_nonzero_int ! ( i64 => u8 , u16 , u32 , u64 , u128 , usize ) ;
641661impl_nonzero_int_try_from_nonzero_int ! ( i128 => u8 , u16 , u32 , u64 , u128 , usize ) ;
642662impl_nonzero_int_try_from_nonzero_int ! ( isize => u8 , u16 , u32 , u64 , u128 , usize ) ;
663+
664+ /// Conversion between integers, wrapping around or saturating at the target type's boundaries.
665+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
666+ #[ rustc_const_unstable( feature = "integer_casts" , issue = "157388" ) ]
667+ pub const trait BoundedCastFromInt <T >: private:: SealedCast < T > + Sized {
668+ /// Converts `value` to this type, wrapping around at the boundary of the type.
669+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
670+ fn wrapping_cast_from ( value : T ) -> Self ;
671+
672+ /// Converts `value` to this type, saturating at the numeric bounds instead of overflowing.
673+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
674+ fn saturating_cast_from ( value : T ) -> Self ;
675+ }
676+
677+ /// Fallible conversion between integers.
678+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
679+ #[ rustc_const_unstable( feature = "integer_casts" , issue = "157388" ) ]
680+ pub const trait CheckedCastFromInt <T >: private:: SealedCast < T > + Sized {
681+ /// Converts `value` to this type, returning `None` if overflow would have occurred.
682+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
683+ fn checked_cast_from ( value : T ) -> Option < Self > ;
684+
685+ /// Converts `value` to this type, assuming overflow cannot occur.
686+ ///
687+ /// # Safety
688+ ///
689+ /// This results in undefined behavior when `value` will overflow when
690+ /// converted to this type.
691+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
692+ unsafe fn unchecked_cast_from ( value : T ) -> Self ;
693+
694+ /// Converts `value` to this type, panicking on overflow.
695+ ///
696+ /// # Panics
697+ ///
698+ /// This function will always panic on overflow, regardless of whether overflow checks are enabled.
699+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
700+ fn strict_cast_from ( value : T ) -> Self ;
701+ }
702+
703+ macro_rules! impl_int_cast {
704+ ( $Src: ty as [ $( $Dst: ty) ,* ] ) => { $(
705+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
706+ #[ rustc_const_unstable( feature = "integer_casts" , issue = "157388" ) ]
707+ impl const CheckedCastFromInt <$Src> for $Dst {
708+ #[ inline]
709+ fn checked_cast_from( value: $Src) -> Option <Self > {
710+ value. try_into( ) . ok( )
711+ }
712+
713+ #[ inline( always) ]
714+ unsafe fn unchecked_cast_from( value: $Src) -> Self {
715+ // SAFETY: the safety contract must be upheld by the caller.
716+ unsafe { value. try_into( ) . unwrap_unchecked( ) }
717+ }
718+
719+ #[ inline]
720+ #[ track_caller]
721+ fn strict_cast_from( value: $Src) -> Self {
722+ match value. try_into( ) {
723+ Ok ( x) => x,
724+ Err ( _) => core:: num:: imp:: overflow_panic:: cast_integer( )
725+ }
726+ }
727+ }
728+
729+ #[ unstable( feature = "integer_casts" , issue = "157388" ) ]
730+ #[ rustc_const_unstable( feature = "integer_casts" , issue = "157388" ) ]
731+ impl const BoundedCastFromInt <$Src> for $Dst {
732+ #[ inline( always) ]
733+ fn wrapping_cast_from( value: $Src) -> Self {
734+ value as Self
735+ }
736+
737+ #[ inline]
738+ #[ allow( unused_comparisons) ]
739+ #[ allow( irrefutable_let_patterns) ]
740+ fn saturating_cast_from( value: $Src) -> Self {
741+ if let Ok ( x) = value. try_into( ) {
742+ return x;
743+ }
744+
745+ if value < 0 { <$Dst>:: MIN } else { <$Dst>:: MAX }
746+ }
747+ }
748+ ) * } ;
749+ }
750+
751+ macro_rules! impl_all_int_casts {
752+ ( [ $( $Src: ty) ,* ] ) => { $(
753+ impl_int_cast!( $Src as [ u8 , u16 , u32 , u64 , u128 , usize , i8 , i16 , i32 , i64 , i128 , isize ] ) ;
754+ ) * } ;
755+ }
756+
757+ impl_all_int_casts ! ( [ u8 , u16 , u32 , u64 , u128 , usize , i8 , i16 , i32 , i64 , i128 , isize ] ) ;
0 commit comments