@@ -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