@@ -377,13 +377,6 @@ pub enum ErrKind {
377
377
NotOn ( ConstVal ) ,
378
378
CallOn ( ConstVal ) ,
379
379
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 ) ,
387
380
DivideByZero ,
388
381
DivideWithOverflow ,
389
382
ModuloByZero ,
@@ -415,6 +408,7 @@ pub enum ErrKind {
415
408
TypeMismatch ( String , ConstInt ) ,
416
409
BadType ( ConstVal ) ,
417
410
ErroneousReferencedConstant ( Box < ConstEvalErr > ) ,
411
+ CharCast ( ConstInt ) ,
418
412
}
419
413
420
414
impl From < ConstMathErr > for ErrKind {
@@ -439,13 +433,6 @@ impl ConstEvalErr {
439
433
NotOn ( ref const_val) => format ! ( "not on {}" , const_val. description( ) ) . into_cow ( ) ,
440
434
CallOn ( ref const_val) => format ! ( "call on {}" , const_val. description( ) ) . into_cow ( ) ,
441
435
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 ( ) ,
449
436
DivideByZero => "attempted to divide by zero" . into_cow ( ) ,
450
437
DivideWithOverflow => "attempted to divide with overflow" . into_cow ( ) ,
451
438
ModuloByZero => "attempted remainder with a divisor of zero" . into_cow ( ) ,
@@ -482,6 +469,9 @@ impl ConstEvalErr {
482
469
} ,
483
470
BadType ( ref i) => format ! ( "value of wrong type: {:?}" , i) . into_cow ( ) ,
484
471
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
+ } ,
485
475
}
486
476
}
487
477
}
@@ -824,7 +814,10 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
824
814
debug ! ( "const call({:?})" , call_args) ;
825
815
eval_const_expr_partial ( tcx, & result, ty_hint, Some ( & call_args) ) ?
826
816
} ,
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
+ } ,
828
821
hir:: ExprBlock ( ref block) => {
829
822
match block. expr {
830
823
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>,
930
923
} ;
931
924
932
925
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
+ } ,
934
930
( _, result) => Ok ( result) ,
935
931
}
936
932
}
@@ -939,15 +935,9 @@ fn infer<'tcx>(
939
935
i : ConstInt ,
940
936
tcx : & TyCtxt < ' tcx > ,
941
937
ty_hint : & ty:: TypeVariants < ' tcx > ,
942
- span : Span
943
- ) -> Result < ConstInt , ConstEvalErr > {
938
+ ) -> Result < ConstInt , ErrKind > {
944
939
use syntax:: ast:: * ;
945
940
946
- let err = |e| ConstEvalErr {
947
- span : span,
948
- kind : e,
949
- } ;
950
-
951
941
match ( ty_hint, i) {
952
942
( & ty:: TyInt ( IntTy :: I8 ) , result @ I8 ( _) ) => Ok ( result) ,
953
943
( & ty:: TyInt ( IntTy :: I16 ) , result @ I16 ( _) ) => Ok ( result) ,
@@ -993,17 +983,17 @@ fn infer<'tcx>(
993
983
Err ( _) => Ok ( Usize ( ConstUsize :: Us32 ( i as u32 ) ) ) ,
994
984
}
995
985
} ,
996
- ( & ty:: TyUint ( _) , InferSigned ( _) ) => Err ( err ( IntermediateUnsignedNegative ) ) ,
986
+ ( & ty:: TyUint ( _) , InferSigned ( _) ) => Err ( IntermediateUnsignedNegative ) ,
997
987
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) ) ,
1000
990
1001
991
( & ty:: TyEnum ( ref adt, _) , i) => {
1002
992
let hints = tcx. lookup_repr_hints ( adt. did ) ;
1003
993
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 )
1005
995
} ,
1006
- ( _, i) => Err ( err ( BadType ( ConstVal :: Integral ( i) ) ) ) ,
996
+ ( _, i) => Err ( BadType ( ConstVal :: Integral ( i) ) ) ,
1007
997
}
1008
998
}
1009
999
@@ -1089,23 +1079,22 @@ fn cast_const_int<'tcx>(tcx: &TyCtxt<'tcx>, val: ConstInt, ty: ty::Ty) -> CastRe
1089
1079
Err ( _) => Ok ( Integral ( Usize ( ConstUsize :: Us32 ( v as u32 ) ) ) ) ,
1090
1080
}
1091
1081
} ,
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" ) ,
1099
1086
} ,
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" ) ,
1106
1091
} ,
1107
- ty:: TyFloat ( ast:: FloatTy :: F32 ) => Ok ( Float ( val. to_u64 ( ) . unwrap ( ) as f32 as f64 ) ) ,
1108
1092
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
+ } ,
1109
1098
_ => Err ( CannotCast ) ,
1110
1099
}
1111
1100
}
@@ -1136,36 +1125,36 @@ fn lit_to_const<'tcx>(lit: &ast::LitKind,
1136
1125
tcx : & TyCtxt < ' tcx > ,
1137
1126
ty_hint : Option < Ty < ' tcx > > ,
1138
1127
span : Span ,
1139
- ) -> Result < ConstVal , ConstEvalErr > {
1128
+ ) -> Result < ConstVal , ErrKind > {
1140
1129
use syntax:: ast:: * ;
1141
1130
use syntax:: ast:: LitIntType :: * ;
1142
1131
match * lit {
1143
1132
LitKind :: Str ( ref s, _) => Ok ( Str ( ( * s) . clone ( ) ) ) ,
1144
1133
LitKind :: ByteStr ( ref data) => Ok ( ByteStr ( data. clone ( ) ) ) ,
1145
1134
LitKind :: Byte ( n) => Ok ( Integral ( U8 ( n) ) ) ,
1146
1135
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 )
1148
1137
} ,
1149
1138
1150
1139
LitKind :: Int ( n, Unsuffixed ) => {
1151
1140
match ty_hint. map ( |t| & t. sty ) {
1152
1141
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 )
1154
1143
} ,
1155
1144
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 )
1157
1146
} ,
1158
1147
None => Ok ( Integral ( Infer ( n) ) ) ,
1159
1148
Some ( & ty:: TyEnum ( ref adt, _) ) => {
1160
1149
let hints = tcx. lookup_repr_hints ( adt. did ) ;
1161
1150
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 )
1163
1152
} ,
1164
1153
Some ( ty_hint) => bug ! ( "bad ty_hint: {:?}, {:?}" , ty_hint, lit) ,
1165
1154
}
1166
1155
} ,
1167
1156
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 )
1169
1158
} ,
1170
1159
1171
1160
LitKind :: Float ( ref n, _) |
0 commit comments