@@ -253,6 +253,8 @@ pub enum ConstVal {
253253 Struct ( ast:: NodeId ) ,
254254 Tuple ( ast:: NodeId ) ,
255255 Function ( DefId ) ,
256+ Array ( ast:: NodeId , u64 ) ,
257+ Repeat ( ast:: NodeId , u64 ) ,
256258}
257259
258260impl hash:: Hash for ConstVal {
@@ -267,6 +269,8 @@ impl hash::Hash for ConstVal {
267269 Struct ( a) => a. hash ( state) ,
268270 Tuple ( a) => a. hash ( state) ,
269271 Function ( a) => a. hash ( state) ,
272+ Array ( a, n) => { a. hash ( state) ; n. hash ( state) } ,
273+ Repeat ( a, n) => { a. hash ( state) ; n. hash ( state) } ,
270274 }
271275 }
272276}
@@ -287,6 +291,8 @@ impl PartialEq for ConstVal {
287291 ( & Struct ( a) , & Struct ( b) ) => a == b,
288292 ( & Tuple ( a) , & Tuple ( b) ) => a == b,
289293 ( & Function ( a) , & Function ( b) ) => a == b,
294+ ( & Array ( a, an) , & Array ( b, bn) ) => ( a == b) && ( an == bn) ,
295+ ( & Repeat ( a, an) , & Repeat ( b, bn) ) => ( a == b) && ( an == bn) ,
290296 _ => false ,
291297 }
292298 }
@@ -307,6 +313,8 @@ impl ConstVal {
307313 Struct ( _) => "struct" ,
308314 Tuple ( _) => "tuple" ,
309315 Function ( _) => "function definition" ,
316+ Array ( ..) => "array" ,
317+ Repeat ( ..) => "repeat" ,
310318 }
311319 }
312320}
@@ -415,6 +423,12 @@ pub enum ErrKind {
415423 ExpectedConstTuple ,
416424 ExpectedConstStruct ,
417425 TupleIndexOutOfBounds ,
426+ IndexedNonVec ,
427+ IndexNegative ,
428+ IndexNotInt ,
429+ IndexOutOfBounds ,
430+ RepeatCountNotNatural ,
431+ RepeatCountNotInt ,
418432
419433 MiscBinaryOp ,
420434 MiscCatchAll ,
@@ -455,6 +469,12 @@ impl ConstEvalErr {
455469 ExpectedConstTuple => "expected constant tuple" . into_cow ( ) ,
456470 ExpectedConstStruct => "expected constant struct" . into_cow ( ) ,
457471 TupleIndexOutOfBounds => "tuple index out of bounds" . into_cow ( ) ,
472+ IndexedNonVec => "indexing is only supported for arrays" . into_cow ( ) ,
473+ IndexNegative => "indices must be non-negative integers" . into_cow ( ) ,
474+ IndexNotInt => "indices must be integers" . into_cow ( ) ,
475+ IndexOutOfBounds => "array index out of bounds" . into_cow ( ) ,
476+ RepeatCountNotNatural => "repeat count must be a natural number" . into_cow ( ) ,
477+ RepeatCountNotInt => "repeat count must be integers" . into_cow ( ) ,
458478
459479 MiscBinaryOp => "bad operands for binary" . into_cow ( ) ,
460480 MiscCatchAll => "unsupported constant expr" . into_cow ( ) ,
@@ -1111,11 +1131,83 @@ 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+ if !tcx. sess . features . borrow ( ) . const_indexing {
1141+ tcx. sess . span_err (
1142+ e. span ,
1143+ "const indexing is an unstable feature" ) ;
1144+ fileline_help ! (
1145+ tcx. sess,
1146+ e. span,
1147+ "in Nightly builds, add `#![feature(const_indexing)]` to the crate \
1148+ attributes to enable") ;
1149+ signal ! ( e, NonConstPath )
1150+ }
1151+ let arr_hint = if let ExprTypeChecked = ty_hint {
1152+ ExprTypeChecked
1153+ } else {
1154+ UncheckedExprNoHint
1155+ } ;
1156+ let arr = try!( eval_const_expr_partial ( tcx, arr, arr_hint, fn_args) ) ;
1157+ let idx_hint = if let ExprTypeChecked = ty_hint {
1158+ ExprTypeChecked
1159+ } else {
1160+ UncheckedExprHint ( tcx. types . usize )
1161+ } ;
1162+ let idx = match try!( eval_const_expr_partial ( tcx, idx, idx_hint, fn_args) ) {
1163+ Int ( i) if i >= 0 => i as u64 ,
1164+ Int ( _) => signal ! ( idx, IndexNegative ) ,
1165+ Uint ( i) => i,
1166+ _ => signal ! ( idx, IndexNotInt ) ,
1167+ } ;
1168+ match arr {
1169+ Array ( _, n) if idx >= n => signal ! ( e, IndexOutOfBounds ) ,
1170+ Array ( v, _) => if let hir:: ExprVec ( ref v) = tcx. map . expect_expr ( v) . node {
1171+ try!( eval_const_expr_partial ( tcx, & * v[ idx as usize ] , ty_hint, fn_args) )
1172+ } else {
1173+ unreachable ! ( )
1174+ } ,
1175+
1176+ Repeat ( _, n) if idx >= n => signal ! ( e, IndexOutOfBounds ) ,
1177+ Repeat ( elem, _) => try!( eval_const_expr_partial (
1178+ tcx,
1179+ & * tcx. map . expect_expr ( elem) ,
1180+ ty_hint,
1181+ fn_args,
1182+ ) ) ,
1183+
1184+ ByteStr ( ref data) if idx as usize >= data. len ( )
1185+ => signal ! ( e, IndexOutOfBounds ) ,
1186+ ByteStr ( data) => Uint ( data[ idx as usize ] as u64 ) ,
1187+
1188+ Str ( ref s) if idx as usize >= s. len ( )
1189+ => signal ! ( e, IndexOutOfBounds ) ,
1190+ Str ( _) => unimplemented ! ( ) , // there's no const_char type
1191+ _ => signal ! ( e, IndexedNonVec ) ,
1192+ }
1193+ }
1194+ hir:: ExprVec ( ref v) => Array ( e. id , v. len ( ) as u64 ) ,
1195+ hir:: ExprRepeat ( _, ref n) => {
1196+ let len_hint = if let ExprTypeChecked = ty_hint {
1197+ ExprTypeChecked
1198+ } else {
1199+ UncheckedExprHint ( tcx. types . usize )
1200+ } ;
1201+ Repeat (
1202+ e. id ,
1203+ match try!( eval_const_expr_partial ( tcx, & * * n, len_hint, fn_args) ) {
1204+ Int ( i) if i >= 0 => i as u64 ,
1205+ Int ( _) => signal ! ( e, RepeatCountNotNatural ) ,
1206+ Uint ( i) => i,
1207+ _ => signal ! ( e, RepeatCountNotInt ) ,
1208+ } ,
1209+ )
1210+ } ,
11191211 hir:: ExprTupField ( ref base, index) => {
11201212 let base_hint = if let ExprTypeChecked = ty_hint {
11211213 ExprTypeChecked
0 commit comments