@@ -256,6 +256,8 @@ pub enum ConstVal {
256
256
Struct ( ast:: NodeId ) ,
257
257
Tuple ( ast:: NodeId ) ,
258
258
Function ( DefId ) ,
259
+ Array ( ast:: NodeId , u64 ) ,
260
+ Repeat ( ast:: NodeId , u64 ) ,
259
261
}
260
262
261
263
impl hash:: Hash for ConstVal {
@@ -270,6 +272,8 @@ impl hash::Hash for ConstVal {
270
272
Struct ( a) => a. hash ( state) ,
271
273
Tuple ( a) => a. hash ( state) ,
272
274
Function ( a) => a. hash ( state) ,
275
+ Array ( a, n) => { a. hash ( state) ; n. hash ( state) } ,
276
+ Repeat ( a, n) => { a. hash ( state) ; n. hash ( state) } ,
273
277
}
274
278
}
275
279
}
@@ -290,6 +294,8 @@ impl PartialEq for ConstVal {
290
294
( & Struct ( a) , & Struct ( b) ) => a == b,
291
295
( & Tuple ( a) , & Tuple ( b) ) => a == b,
292
296
( & Function ( a) , & Function ( b) ) => a == b,
297
+ ( & Array ( a, an) , & Array ( b, bn) ) => ( a == b) && ( an == bn) ,
298
+ ( & Repeat ( a, an) , & Repeat ( b, bn) ) => ( a == b) && ( an == bn) ,
293
299
_ => false ,
294
300
}
295
301
}
@@ -310,6 +316,8 @@ impl ConstVal {
310
316
Struct ( _) => "struct" ,
311
317
Tuple ( _) => "tuple" ,
312
318
Function ( _) => "function definition" ,
319
+ Array ( ..) => "array" ,
320
+ Repeat ( ..) => "repeat" ,
313
321
}
314
322
}
315
323
}
@@ -416,6 +424,12 @@ pub enum ErrKind {
416
424
ExpectedConstTuple ,
417
425
ExpectedConstStruct ,
418
426
TupleIndexOutOfBounds ,
427
+ IndexedNonVec ,
428
+ IndexNegative ,
429
+ IndexNotInt ,
430
+ IndexOutOfBounds ,
431
+ RepeatCountNotNatural ,
432
+ RepeatCountNotInt ,
419
433
420
434
MiscBinaryOp ,
421
435
MiscCatchAll ,
@@ -454,6 +468,12 @@ impl ConstEvalErr {
454
468
ExpectedConstTuple => "expected constant tuple" . into_cow ( ) ,
455
469
ExpectedConstStruct => "expected constant struct" . into_cow ( ) ,
456
470
TupleIndexOutOfBounds => "tuple index out of bounds" . into_cow ( ) ,
471
+ IndexedNonVec => "indexing is only supported for arrays" . into_cow ( ) ,
472
+ IndexNegative => "indices must be non-negative integers" . into_cow ( ) ,
473
+ IndexNotInt => "indices must be integers" . into_cow ( ) ,
474
+ IndexOutOfBounds => "array index out of bounds" . into_cow ( ) ,
475
+ RepeatCountNotNatural => "repeat count must be a natural number" . into_cow ( ) ,
476
+ RepeatCountNotInt => "repeat count must be integers" . into_cow ( ) ,
457
477
458
478
MiscBinaryOp => "bad operands for binary" . into_cow ( ) ,
459
479
MiscCatchAll => "unsupported constant expr" . into_cow ( ) ,
@@ -1111,11 +1131,72 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
1111
1131
hir:: ExprBlock ( ref block) => {
1112
1132
match block. expr {
1113
1133
Some ( ref expr) => try!( eval_const_expr_partial ( tcx, & * * expr, ty_hint, fn_args) ) ,
1114
- None => Int ( 0 )
1134
+ None => unreachable ! ( ) ,
1115
1135
}
1116
1136
}
1117
1137
hir:: ExprTup ( _) => Tuple ( e. id ) ,
1118
1138
hir:: ExprStruct ( ..) => Struct ( e. id ) ,
1139
+ hir:: ExprIndex ( ref arr, ref idx) => {
1140
+ let arr_hint = if let ExprTypeChecked = ty_hint {
1141
+ ExprTypeChecked
1142
+ } else {
1143
+ UncheckedExprNoHint
1144
+ } ;
1145
+ let arr = try!( eval_const_expr_partial ( tcx, arr, arr_hint, fn_args) ) ;
1146
+ let idx_hint = if let ExprTypeChecked = ty_hint {
1147
+ ExprTypeChecked
1148
+ } else {
1149
+ UncheckedExprHint ( tcx. types . usize )
1150
+ } ;
1151
+ let idx = match try!( eval_const_expr_partial ( tcx, idx, idx_hint, fn_args) ) {
1152
+ Int ( i) if i >= 0 => i as u64 ,
1153
+ Int ( _) => signal ! ( idx, IndexNegative ) ,
1154
+ Uint ( i) => i,
1155
+ _ => signal ! ( idx, IndexNotInt ) ,
1156
+ } ;
1157
+ match arr {
1158
+ Array ( _, n) if idx >= n => signal ! ( e, IndexOutOfBounds ) ,
1159
+ Array ( v, _) => if let hir:: ExprVec ( ref v) = tcx. map . expect_expr ( v) . node {
1160
+ try!( eval_const_expr_partial ( tcx, & * v[ idx as usize ] , ty_hint, fn_args) )
1161
+ } else {
1162
+ unreachable ! ( )
1163
+ } ,
1164
+
1165
+ Repeat ( _, n) if idx >= n => signal ! ( e, IndexOutOfBounds ) ,
1166
+ Repeat ( elem, _) => try!( eval_const_expr_partial (
1167
+ tcx,
1168
+ & * tcx. map . expect_expr ( elem) ,
1169
+ ty_hint,
1170
+ fn_args,
1171
+ ) ) ,
1172
+
1173
+ ByteStr ( ref data) if idx as usize >= data. len ( )
1174
+ => signal ! ( e, IndexOutOfBounds ) ,
1175
+ ByteStr ( data) => Uint ( data[ idx as usize ] as u64 ) ,
1176
+
1177
+ Str ( ref s) if idx as usize >= s. len ( )
1178
+ => signal ! ( e, IndexOutOfBounds ) ,
1179
+ Str ( _) => unimplemented ! ( ) , // there's no const_char type
1180
+ _ => signal ! ( e, IndexedNonVec ) ,
1181
+ }
1182
+ }
1183
+ hir:: ExprVec ( ref v) => Array ( e. id , v. len ( ) as u64 ) ,
1184
+ hir:: ExprRepeat ( _, ref n) => {
1185
+ let len_hint = if let ExprTypeChecked = ty_hint {
1186
+ ExprTypeChecked
1187
+ } else {
1188
+ UncheckedExprHint ( tcx. types . usize )
1189
+ } ;
1190
+ Repeat (
1191
+ e. id ,
1192
+ match try!( eval_const_expr_partial ( tcx, & * * n, len_hint, fn_args) ) {
1193
+ Int ( i) if i >= 0 => i as u64 ,
1194
+ Int ( _) => signal ! ( e, RepeatCountNotNatural ) ,
1195
+ Uint ( i) => i,
1196
+ _ => signal ! ( e, RepeatCountNotInt ) ,
1197
+ } ,
1198
+ )
1199
+ } ,
1119
1200
hir:: ExprTupField ( ref base, index) => {
1120
1201
let base_hint = if let ExprTypeChecked = ty_hint {
1121
1202
ExprTypeChecked
0 commit comments