@@ -515,6 +515,21 @@ pub enum EvalHint<'tcx> {
515
515
UncheckedExprNoHint ,
516
516
}
517
517
518
+ impl < ' tcx > EvalHint < ' tcx > {
519
+ fn erase_hint ( & self ) -> EvalHint < ' tcx > {
520
+ match * self {
521
+ ExprTypeChecked => ExprTypeChecked ,
522
+ UncheckedExprHint ( _) | UncheckedExprNoHint => UncheckedExprNoHint ,
523
+ }
524
+ }
525
+ fn checked_or ( & self , ty : Ty < ' tcx > ) -> EvalHint < ' tcx > {
526
+ match * self {
527
+ ExprTypeChecked => ExprTypeChecked ,
528
+ _ => UncheckedExprHint ( ty) ,
529
+ }
530
+ }
531
+ }
532
+
518
533
#[ derive( Copy , Clone , PartialEq , Debug ) ]
519
534
pub enum IntTy { I8 , I16 , I32 , I64 }
520
535
#[ derive( Copy , Clone , PartialEq , Debug ) ]
@@ -846,13 +861,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
846
861
}
847
862
hir:: ExprBinary ( op, ref a, ref b) => {
848
863
let b_ty = match op. node {
849
- hir:: BiShl | hir:: BiShr => {
850
- if let ExprTypeChecked = ty_hint {
851
- ExprTypeChecked
852
- } else {
853
- UncheckedExprHint ( tcx. types . usize )
854
- }
855
- }
864
+ hir:: BiShl | hir:: BiShr => ty_hint. checked_or ( tcx. types . usize ) ,
856
865
_ => ty_hint
857
866
} ;
858
867
match ( try!( eval_const_expr_partial ( tcx, & * * a, ty_hint, fn_args) ) ,
@@ -1072,11 +1081,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
1072
1081
try!( eval_const_expr_partial ( tcx, const_expr, item_hint, fn_args) )
1073
1082
}
1074
1083
hir:: ExprCall ( ref callee, ref args) => {
1075
- let sub_ty_hint = if let ExprTypeChecked = ty_hint {
1076
- ExprTypeChecked
1077
- } else {
1078
- UncheckedExprNoHint // we cannot reason about UncheckedExprHint here
1079
- } ;
1084
+ let sub_ty_hint = ty_hint. erase_hint ( ) ;
1080
1085
let callee_val = try!( eval_const_expr_partial ( tcx, callee, sub_ty_hint, fn_args) ) ;
1081
1086
let ( decl, block, constness) = try!( get_fn_def ( tcx, e, callee_val) ) ;
1082
1087
match ( ty_hint, constness) {
@@ -1109,9 +1114,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
1109
1114
debug ! ( "const call({:?})" , call_args) ;
1110
1115
try!( eval_const_expr_partial ( tcx, & * * result, ty_hint, Some ( & call_args) ) )
1111
1116
} ,
1112
- hir:: ExprLit ( ref lit) => {
1113
- lit_to_const ( & * * lit, ety)
1114
- }
1117
+ hir:: ExprLit ( ref lit) => lit_to_const ( & * * lit, ety) ,
1115
1118
hir:: ExprBlock ( ref block) => {
1116
1119
match block. expr {
1117
1120
Some ( ref expr) => try!( eval_const_expr_partial ( tcx, & * * expr, ty_hint, fn_args) ) ,
@@ -1124,17 +1127,9 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
1124
1127
if !tcx. sess . features . borrow ( ) . const_indexing {
1125
1128
signal ! ( e, IndexOpFeatureGated ) ;
1126
1129
}
1127
- let arr_hint = if let ExprTypeChecked = ty_hint {
1128
- ExprTypeChecked
1129
- } else {
1130
- UncheckedExprNoHint
1131
- } ;
1130
+ let arr_hint = ty_hint. erase_hint ( ) ;
1132
1131
let arr = try!( eval_const_expr_partial ( tcx, arr, arr_hint, fn_args) ) ;
1133
- let idx_hint = if let ExprTypeChecked = ty_hint {
1134
- ExprTypeChecked
1135
- } else {
1136
- UncheckedExprHint ( tcx. types . usize )
1137
- } ;
1132
+ let idx_hint = ty_hint. checked_or ( tcx. types . usize ) ;
1138
1133
let idx = match try!( eval_const_expr_partial ( tcx, idx, idx_hint, fn_args) ) {
1139
1134
Int ( i) if i >= 0 => i as u64 ,
1140
1135
Int ( _) => signal ! ( idx, IndexNegative ) ,
@@ -1169,11 +1164,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
1169
1164
}
1170
1165
hir:: ExprVec ( ref v) => Array ( e. id , v. len ( ) as u64 ) ,
1171
1166
hir:: ExprRepeat ( _, ref n) => {
1172
- let len_hint = if let ExprTypeChecked = ty_hint {
1173
- ExprTypeChecked
1174
- } else {
1175
- UncheckedExprHint ( tcx. types . usize )
1176
- } ;
1167
+ let len_hint = ty_hint. checked_or ( tcx. types . usize ) ;
1177
1168
Repeat (
1178
1169
e. id ,
1179
1170
match try!( eval_const_expr_partial ( tcx, & * * n, len_hint, fn_args) ) {
@@ -1185,11 +1176,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
1185
1176
)
1186
1177
} ,
1187
1178
hir:: ExprTupField ( ref base, index) => {
1188
- let base_hint = if let ExprTypeChecked = ty_hint {
1189
- ExprTypeChecked
1190
- } else {
1191
- UncheckedExprNoHint
1192
- } ;
1179
+ let base_hint = ty_hint. erase_hint ( ) ;
1193
1180
if let Ok ( c) = eval_const_expr_partial ( tcx, base, base_hint, fn_args) {
1194
1181
if let Tuple ( tup_id) = c {
1195
1182
if let hir:: ExprTup ( ref fields) = tcx. map . expect_expr ( tup_id) . node {
@@ -1209,12 +1196,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
1209
1196
}
1210
1197
}
1211
1198
hir:: ExprField ( ref base, field_name) => {
1199
+ let base_hint = ty_hint. erase_hint ( ) ;
1212
1200
// Get the base expression if it is a struct and it is constant
1213
- let base_hint = if let ExprTypeChecked = ty_hint {
1214
- ExprTypeChecked
1215
- } else {
1216
- UncheckedExprNoHint
1217
- } ;
1218
1201
if let Ok ( c) = eval_const_expr_partial ( tcx, base, base_hint, fn_args) {
1219
1202
if let Struct ( struct_id) = c {
1220
1203
if let hir:: ExprStruct ( _, ref fields, _) = tcx. map . expect_expr ( struct_id) . node {
0 commit comments