@@ -377,13 +377,6 @@ pub enum ErrKind {
377377    NotOn ( ConstVal ) , 
378378    CallOn ( ConstVal ) , 
379379
380-     NegateWithOverflow ( i64 ) , 
381-     AddiWithOverflow ( i64 ,  i64 ) , 
382-     SubiWithOverflow ( i64 ,  i64 ) , 
383-     MuliWithOverflow ( i64 ,  i64 ) , 
384-     AdduWithOverflow ( u64 ,  u64 ) , 
385-     SubuWithOverflow ( u64 ,  u64 ) , 
386-     MuluWithOverflow ( u64 ,  u64 ) , 
387380    DivideByZero , 
388381    DivideWithOverflow , 
389382    ModuloByZero , 
@@ -415,6 +408,7 @@ pub enum ErrKind {
415408     TypeMismatch ( String ,  ConstInt ) , 
416409    BadType ( ConstVal ) , 
417410    ErroneousReferencedConstant ( Box < ConstEvalErr > ) , 
411+     CharCast ( ConstInt ) , 
418412} 
419413
420414impl  From < ConstMathErr >  for  ErrKind  { 
@@ -439,13 +433,6 @@ impl ConstEvalErr {
439433            NotOn ( ref  const_val)  => format ! ( "not on {}" ,  const_val. description( ) ) . into_cow ( ) , 
440434            CallOn ( ref  const_val)  => format ! ( "call on {}" ,  const_val. description( ) ) . into_cow ( ) , 
441435
442-             NegateWithOverflow ( ..)  => "attempted to negate with overflow" . into_cow ( ) , 
443-             AddiWithOverflow ( ..)  => "attempted to add with overflow" . into_cow ( ) , 
444-             SubiWithOverflow ( ..)  => "attempted to sub with overflow" . into_cow ( ) , 
445-             MuliWithOverflow ( ..)  => "attempted to mul with overflow" . into_cow ( ) , 
446-             AdduWithOverflow ( ..)  => "attempted to add with overflow" . into_cow ( ) , 
447-             SubuWithOverflow ( ..)  => "attempted to sub with overflow" . into_cow ( ) , 
448-             MuluWithOverflow ( ..)  => "attempted to mul with overflow" . into_cow ( ) , 
449436            DivideByZero          => "attempted to divide by zero" . into_cow ( ) , 
450437            DivideWithOverflow    => "attempted to divide with overflow" . into_cow ( ) , 
451438            ModuloByZero          => "attempted remainder with a divisor of zero" . into_cow ( ) , 
@@ -482,6 +469,9 @@ impl ConstEvalErr {
482469            } , 
483470            BadType ( ref  i)  => format ! ( "value of wrong type: {:?}" ,  i) . into_cow ( ) , 
484471            ErroneousReferencedConstant ( _)  => "could not evaluate referenced constant" . into_cow ( ) , 
472+             CharCast ( ref  got)  => { 
473+                 format ! ( "only `u8` can be cast as `char`, not `{}`" ,  got. description( ) ) . into_cow ( ) 
474+             } , 
485475        } 
486476    } 
487477} 
@@ -824,7 +814,10 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
824814          debug ! ( "const call({:?})" ,  call_args) ; 
825815          eval_const_expr_partial ( tcx,  & result,  ty_hint,  Some ( & call_args) ) ?
826816      } , 
827-       hir:: ExprLit ( ref  lit)  => lit_to_const ( & lit. node ,  tcx,  ety,  lit. span ) ?, 
817+       hir:: ExprLit ( ref  lit)  => match  lit_to_const ( & lit. node ,  tcx,  ety,  lit. span )  { 
818+           Ok ( val)  => val, 
819+           Err ( err)  => signal ! ( e,  err) , 
820+       } , 
828821      hir:: ExprBlock ( ref  block)  => { 
829822        match  block. expr  { 
830823            Some ( ref  expr)  => eval_const_expr_partial ( tcx,  & expr,  ty_hint,  fn_args) ?, 
@@ -930,7 +923,10 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
930923    } ; 
931924
932925    match  ( ety. map ( |t| & t. sty ) ,  result)  { 
933-         ( Some ( ref  ty_hint) ,  Integral ( i) )  => Ok ( Integral ( infer ( i,  tcx,  ty_hint,  e. span ) ?) ) , 
926+         ( Some ( ref  ty_hint) ,  Integral ( i) )  => match  infer ( i,  tcx,  ty_hint)  { 
927+             Ok ( inferred)  => Ok ( Integral ( inferred) ) , 
928+             Err ( err)  => signal ! ( e,  err) , 
929+         } , 
934930        ( _,  result)  => Ok ( result) , 
935931    } 
936932} 
@@ -939,15 +935,9 @@ fn infer<'tcx>(
939935    i :  ConstInt , 
940936    tcx :  & TyCtxt < ' tcx > , 
941937    ty_hint :  & ty:: TypeVariants < ' tcx > , 
942-     span :  Span 
943- )  -> Result < ConstInt ,  ConstEvalErr >  { 
938+ )  -> Result < ConstInt ,  ErrKind >  { 
944939    use  syntax:: ast:: * ; 
945940
946-     let  err = |e| ConstEvalErr  { 
947-         span :  span, 
948-         kind :  e, 
949-     } ; 
950- 
951941    match  ( ty_hint,  i)  { 
952942        ( & ty:: TyInt ( IntTy :: I8 ) ,  result @ I8 ( _) )  => Ok ( result) , 
953943        ( & ty:: TyInt ( IntTy :: I16 ) ,  result @ I16 ( _) )  => Ok ( result) , 
@@ -993,17 +983,17 @@ fn infer<'tcx>(
993983                Err ( _)  => Ok ( Usize ( ConstUsize :: Us32 ( i as  u32 ) ) ) , 
994984            } 
995985        } , 
996-         ( & ty:: TyUint ( _) ,  InferSigned ( _) )  => Err ( err ( IntermediateUnsignedNegative ) ) , 
986+         ( & ty:: TyUint ( _) ,  InferSigned ( _) )  => Err ( IntermediateUnsignedNegative ) , 
997987
998-         ( & ty:: TyInt ( ity) ,  i)  => Err ( err ( TypeMismatch ( ity. to_string ( ) ,  i) ) ) , 
999-         ( & ty:: TyUint ( ity) ,  i)  => Err ( err ( TypeMismatch ( ity. to_string ( ) ,  i) ) ) , 
988+         ( & ty:: TyInt ( ity) ,  i)  => Err ( TypeMismatch ( ity. to_string ( ) ,  i) ) , 
989+         ( & ty:: TyUint ( ity) ,  i)  => Err ( TypeMismatch ( ity. to_string ( ) ,  i) ) , 
1000990
1001991        ( & ty:: TyEnum ( ref  adt,  _) ,  i)  => { 
1002992            let  hints = tcx. lookup_repr_hints ( adt. did ) ; 
1003993            let  int_ty = tcx. enum_repr_type ( hints. iter ( ) . next ( ) ) ; 
1004-             infer ( i,  tcx,  & int_ty. to_ty ( tcx) . sty ,  span ) 
994+             infer ( i,  tcx,  & int_ty. to_ty ( tcx) . sty ) 
1005995        } , 
1006-         ( _,  i)  => Err ( err ( BadType ( ConstVal :: Integral ( i) ) ) ) , 
996+         ( _,  i)  => Err ( BadType ( ConstVal :: Integral ( i) ) ) , 
1007997    } 
1008998} 
1009999
@@ -1089,23 +1079,22 @@ fn cast_const_int<'tcx>(tcx: &TyCtxt<'tcx>, val: ConstInt, ty: ty::Ty) -> CastRe
10891079                Err ( _)  => Ok ( Integral ( Usize ( ConstUsize :: Us32 ( v as  u32 ) ) ) ) , 
10901080            } 
10911081        } , 
1092-         ty:: TyFloat ( ast:: FloatTy :: F64 )  if  val. is_negative ( )  => { 
1093-             // FIXME: this could probably be prettier 
1094-             // there's no easy way to turn an `Infer` into a f64 
1095-             let  val = ( -val) . map_err ( Math ) ?; 
1096-             let  val = val. to_u64 ( ) . unwrap ( )  as  f64 ; 
1097-             let  val = -val; 
1098-             Ok ( Float ( val) ) 
1082+         ty:: TyFloat ( ast:: FloatTy :: F64 )  => match  val. erase_type ( )  { 
1083+             Infer ( u)  => Ok ( Float ( u as  f64 ) ) , 
1084+             InferSigned ( i)  => Ok ( Float ( i as  f64 ) ) , 
1085+             _ => bug ! ( "ConstInt::erase_type returned something other than Infer/InferSigned" ) , 
10991086        } , 
1100-         ty:: TyFloat ( ast:: FloatTy :: F64 )  => Ok ( Float ( val. to_u64 ( ) . unwrap ( )  as  f64 ) ) , 
1101-         ty:: TyFloat ( ast:: FloatTy :: F32 )  if  val. is_negative ( )  => { 
1102-             let  val = ( -val) . map_err ( Math ) ?; 
1103-             let  val = val. to_u64 ( ) . unwrap ( )  as  f32 ; 
1104-             let  val = -val; 
1105-             Ok ( Float ( val as  f64 ) ) 
1087+         ty:: TyFloat ( ast:: FloatTy :: F32 )  => match  val. erase_type ( )  { 
1088+             Infer ( u)  => Ok ( Float ( u as  f32  as  f64 ) ) , 
1089+             InferSigned ( i)  => Ok ( Float ( i as  f32  as  f64 ) ) , 
1090+             _ => bug ! ( "ConstInt::erase_type returned something other than Infer/InferSigned" ) , 
11061091        } , 
1107-         ty:: TyFloat ( ast:: FloatTy :: F32 )  => Ok ( Float ( val. to_u64 ( ) . unwrap ( )  as  f32  as  f64 ) ) , 
11081092        ty:: TyRawPtr ( _)  => Err ( ErrKind :: UnimplementedConstVal ( "casting an address to a raw ptr" ) ) , 
1093+         ty:: TyChar  => match  infer ( val,  tcx,  & ty:: TyUint ( ast:: UintTy :: U8 ) )  { 
1094+             Ok ( U8 ( u) )  => Ok ( Char ( u as  char ) ) , 
1095+             // can only occur before typeck, typeck blocks `T as char` for `T` != `u8` 
1096+             _ => Err ( CharCast ( val) ) , 
1097+         } , 
11091098        _ => Err ( CannotCast ) , 
11101099    } 
11111100} 
@@ -1136,36 +1125,36 @@ fn lit_to_const<'tcx>(lit: &ast::LitKind,
11361125                      tcx :  & TyCtxt < ' tcx > , 
11371126                      ty_hint :  Option < Ty < ' tcx > > , 
11381127                      span :  Span , 
1139-                       )  -> Result < ConstVal ,  ConstEvalErr >  { 
1128+                       )  -> Result < ConstVal ,  ErrKind >  { 
11401129    use  syntax:: ast:: * ; 
11411130    use  syntax:: ast:: LitIntType :: * ; 
11421131    match  * lit { 
11431132        LitKind :: Str ( ref  s,  _)  => Ok ( Str ( ( * s) . clone ( ) ) ) , 
11441133        LitKind :: ByteStr ( ref  data)  => Ok ( ByteStr ( data. clone ( ) ) ) , 
11451134        LitKind :: Byte ( n)  => Ok ( Integral ( U8 ( n) ) ) , 
11461135        LitKind :: Int ( n,  Signed ( ity) )  => { 
1147-             infer ( InferSigned ( n as  i64 ) ,  tcx,  & ty:: TyInt ( ity) ,  span ) . map ( Integral ) 
1136+             infer ( InferSigned ( n as  i64 ) ,  tcx,  & ty:: TyInt ( ity) ) . map ( Integral ) 
11481137        } , 
11491138
11501139        LitKind :: Int ( n,  Unsuffixed )  => { 
11511140            match  ty_hint. map ( |t| & t. sty )  { 
11521141                Some ( & ty:: TyInt ( ity) )  => { 
1153-                     infer ( InferSigned ( n as  i64 ) ,  tcx,  & ty:: TyInt ( ity) ,  span ) . map ( Integral ) 
1142+                     infer ( InferSigned ( n as  i64 ) ,  tcx,  & ty:: TyInt ( ity) ) . map ( Integral ) 
11541143                } , 
11551144                Some ( & ty:: TyUint ( uty) )  => { 
1156-                     infer ( Infer ( n) ,  tcx,  & ty:: TyUint ( uty) ,  span ) . map ( Integral ) 
1145+                     infer ( Infer ( n) ,  tcx,  & ty:: TyUint ( uty) ) . map ( Integral ) 
11571146                } , 
11581147                None  => Ok ( Integral ( Infer ( n) ) ) , 
11591148                Some ( & ty:: TyEnum ( ref  adt,  _) )  => { 
11601149                    let  hints = tcx. lookup_repr_hints ( adt. did ) ; 
11611150                    let  int_ty = tcx. enum_repr_type ( hints. iter ( ) . next ( ) ) ; 
1162-                     infer ( Infer ( n) ,  tcx,  & int_ty. to_ty ( tcx) . sty ,  span ) . map ( Integral ) 
1151+                     infer ( Infer ( n) ,  tcx,  & int_ty. to_ty ( tcx) . sty ) . map ( Integral ) 
11631152                } , 
11641153                Some ( ty_hint)  => bug ! ( "bad ty_hint: {:?}, {:?}" ,  ty_hint,  lit) , 
11651154            } 
11661155        } , 
11671156        LitKind :: Int ( n,  Unsigned ( ity) )  => { 
1168-             infer ( Infer ( n) ,  tcx,  & ty:: TyUint ( ity) ,  span ) . map ( Integral ) 
1157+             infer ( Infer ( n) ,  tcx,  & ty:: TyUint ( ity) ) . map ( Integral ) 
11691158        } , 
11701159
11711160        LitKind :: Float ( ref  n,  _)  |
0 commit comments