@@ -256,6 +256,8 @@ pub enum ConstVal {
256256 Struct ( ast:: NodeId ) ,
257257 Tuple ( ast:: NodeId ) ,
258258 Function ( DefId ) ,
259+ Array ( ast:: NodeId , u64 ) ,
260+ Repeat ( ast:: NodeId , u64 ) ,
259261}
260262
261263impl hash:: Hash for ConstVal {
@@ -270,6 +272,8 @@ impl hash::Hash for ConstVal {
270272 Struct ( a) => a. hash ( state) ,
271273 Tuple ( a) => a. hash ( state) ,
272274 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) } ,
273277 }
274278 }
275279}
@@ -290,6 +294,8 @@ impl PartialEq for ConstVal {
290294 ( & Struct ( a) , & Struct ( b) ) => a == b,
291295 ( & Tuple ( a) , & Tuple ( b) ) => a == b,
292296 ( & 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) ,
293299 _ => false ,
294300 }
295301 }
@@ -310,6 +316,8 @@ impl ConstVal {
310316 Struct ( _) => "struct" ,
311317 Tuple ( _) => "tuple" ,
312318 Function ( _) => "function definition" ,
319+ Array ( ..) => "array" ,
320+ Repeat ( ..) => "repeat" ,
313321 }
314322 }
315323}
@@ -416,6 +424,12 @@ pub enum ErrKind {
416424 ExpectedConstTuple ,
417425 ExpectedConstStruct ,
418426 TupleIndexOutOfBounds ,
427+ IndexedNonVec ,
428+ IndexNegative ,
429+ IndexNotInt ,
430+ IndexOutOfBounds ,
431+ RepeatCountNotNatural ,
432+ RepeatCountNotInt ,
419433
420434 MiscBinaryOp ,
421435 MiscCatchAll ,
@@ -454,6 +468,12 @@ impl ConstEvalErr {
454468 ExpectedConstTuple => "expected constant tuple" . into_cow ( ) ,
455469 ExpectedConstStruct => "expected constant struct" . into_cow ( ) ,
456470 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 ( ) ,
457477
458478 MiscBinaryOp => "bad operands for binary" . into_cow ( ) ,
459479 MiscCatchAll => "unsupported constant expr" . into_cow ( ) ,
@@ -1111,11 +1131,72 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
11111131 hir:: ExprBlock ( ref block) => {
11121132 match block. expr {
11131133 Some ( ref expr) => try!( eval_const_expr_partial ( tcx, & * * expr, ty_hint, fn_args) ) ,
1114- None => Int ( 0 )
1134+ None => unreachable ! ( ) ,
11151135 }
11161136 }
11171137 hir:: ExprTup ( _) => Tuple ( e. id ) ,
11181138 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+ } ,
11191200 hir:: ExprTupField ( ref base, index) => {
11201201 let base_hint = if let ExprTypeChecked = ty_hint {
11211202 ExprTypeChecked
0 commit comments