55use crate :: ascii;
66use crate :: intrinsics;
77use crate :: mem;
8+ use crate :: ops:: { Add , Mul , Sub } ;
89use crate :: str:: FromStr ;
910
1011// Used because the `?` operator is not allowed in a const context.
@@ -969,14 +970,14 @@ pub enum FpCategory {
969970}
970971
971972#[ doc( hidden) ]
972- trait FromStrRadixHelper : PartialOrd + Copy + Default {
973+ trait FromStrRadixHelper :
974+ PartialOrd + Copy + Default + Add < Output = Self > + Sub < Output = Self > + Mul < Output = Self >
975+ {
973976 const MIN : Self ;
977+ fn from_u32 ( u : u32 ) -> Self ;
974978 fn checked_mul ( & self , other : u32 ) -> Option < Self > ;
975979 fn checked_sub ( & self , other : u32 ) -> Option < Self > ;
976980 fn checked_add ( & self , other : u32 ) -> Option < Self > ;
977- unsafe fn unchecked_mul ( self , other : u32 ) -> Self ;
978- unsafe fn unchecked_sub ( self , other : u32 ) -> Self ;
979- unsafe fn unchecked_add ( self , other : u32 ) -> Self ;
980981}
981982
982983macro_rules! from_str_radix_int_impl {
@@ -996,6 +997,8 @@ macro_rules! impl_helper_for {
996997 ( $( $t: ty) * ) => ( $( impl FromStrRadixHelper for $t {
997998 const MIN : Self = Self :: MIN ;
998999 #[ inline]
1000+ fn from_u32( u: u32 ) -> Self { u as Self }
1001+ #[ inline]
9991002 fn checked_mul( & self , other: u32 ) -> Option <Self > {
10001003 Self :: checked_mul( * self , other as Self )
10011004 }
@@ -1007,27 +1010,6 @@ macro_rules! impl_helper_for {
10071010 fn checked_add( & self , other: u32 ) -> Option <Self > {
10081011 Self :: checked_add( * self , other as Self )
10091012 }
1010- #[ inline]
1011- unsafe fn unchecked_mul( self , other: u32 ) -> Self {
1012- // SAFETY: Conditions of `Self::unchecked_mul` must be upheld by the caller.
1013- unsafe {
1014- Self :: unchecked_mul( self , other as Self )
1015- }
1016- }
1017- #[ inline]
1018- unsafe fn unchecked_sub( self , other: u32 ) -> Self {
1019- // SAFETY: Conditions of `Self::unchecked_sub` must be upheld by the caller.
1020- unsafe {
1021- Self :: unchecked_sub( self , other as Self )
1022- }
1023- }
1024- #[ inline]
1025- unsafe fn unchecked_add( self , other: u32 ) -> Self {
1026- // SAFETY: Conditions of `Self::unchecked_add` must be upheld by the caller.
1027- unsafe {
1028- Self :: unchecked_add( self , other as Self )
1029- }
1030- }
10311013 } ) * )
10321014}
10331015impl_helper_for ! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
@@ -1077,30 +1059,28 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
10771059 let mut result = T :: default ( ) ;
10781060
10791061 if can_not_overflow :: < T > ( radix, is_signed_ty, digits) {
1080- // SAFETY: If the len of the str is short compared to the range of the type
1062+ // If the len of the str is short compared to the range of the type
10811063 // we are parsing into, then we can be certain that an overflow will not occur.
10821064 // This bound is when `radix.pow(digits.len()) - 1 <= T::MAX` but the condition
10831065 // above is a faster (conservative) approximation of this.
10841066 //
10851067 // Consider radix 16 as it has the highest information density per digit and will thus overflow the earliest:
10861068 // `u8::MAX` is `ff` - any str of len 2 is guaranteed to not overflow.
10871069 // `i8::MAX` is `7f` - only a str of len 1 is guaranteed to not overflow.
1088- unsafe {
1089- macro_rules! run_unchecked_loop {
1090- ( $unchecked_additive_op: ident) => {
1091- for & c in digits {
1092- result = result. unchecked_mul( radix) ;
1093- let x = ( c as char ) . to_digit( radix) . ok_or( PIE { kind: InvalidDigit } ) ?;
1094- result = T :: $unchecked_additive_op( result, x) ;
1095- }
1096- } ;
1097- }
1098- if is_positive {
1099- run_unchecked_loop ! ( unchecked_add)
1100- } else {
1101- run_unchecked_loop ! ( unchecked_sub)
1070+ macro_rules! run_unchecked_loop {
1071+ ( $unchecked_additive_op: expr) => {
1072+ for & c in digits {
1073+ result = result * T :: from_u32( radix) ;
1074+ let x = ( c as char ) . to_digit( radix) . ok_or( PIE { kind: InvalidDigit } ) ?;
1075+ result = $unchecked_additive_op( result, T :: from_u32( x) ) ;
1076+ }
11021077 } ;
11031078 }
1079+ if is_positive {
1080+ run_unchecked_loop ! ( <T as core:: ops:: Add >:: add)
1081+ } else {
1082+ run_unchecked_loop ! ( <T as core:: ops:: Sub >:: sub)
1083+ } ;
11041084 } else {
11051085 macro_rules! run_checked_loop {
11061086 ( $checked_additive_op: ident, $overflow_err: expr) => {
0 commit comments