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