@@ -207,7 +207,9 @@ pub enum const_val {
207207 const_binary( Rc < Vec < u8 > > ) ,
208208 const_bool( bool ) ,
209209 Struct ( ast:: NodeId ) ,
210- Tuple ( ast:: NodeId )
210+ Tuple ( ast:: NodeId ) ,
211+ Array ( Vec < P < Expr > > ) ,
212+ Repeat ( P < Expr > , u64 ) ,
211213}
212214
213215pub fn const_expr_to_pat ( tcx : & ty:: ctxt , expr : & Expr , span : Span ) -> P < ast:: Pat > {
@@ -294,11 +296,15 @@ pub enum ErrKind {
294296 NegateOnBinary ,
295297 NegateOnStruct ,
296298 NegateOnTuple ,
299+ NegateOnArray ,
300+ NegateOnRepeat ,
297301 NotOnFloat ,
298302 NotOnString ,
299303 NotOnBinary ,
300304 NotOnStruct ,
301305 NotOnTuple ,
306+ NotOnArray ,
307+ NotOnRepeat ,
302308
303309 NegateWithOverflow ( i64 ) ,
304310 AddiWithOverflow ( i64 , i64 ) ,
@@ -318,6 +324,12 @@ pub enum ErrKind {
318324 ExpectedConstTuple ,
319325 ExpectedConstStruct ,
320326 TupleIndexOutOfBounds ,
327+ IndexedNonVec ,
328+ IndexNotNatural ,
329+ IndexNotInt ,
330+ IndexOutOfBounds ,
331+ RepeatCountNotNatural ,
332+ RepeatCountNotInt ,
321333
322334 MiscBinaryOp ,
323335 MiscCatchAll ,
@@ -339,11 +351,15 @@ impl ConstEvalErr {
339351 NegateOnBinary => "negate on binary literal" . into_cow ( ) ,
340352 NegateOnStruct => "negate on struct" . into_cow ( ) ,
341353 NegateOnTuple => "negate on tuple" . into_cow ( ) ,
354+ NegateOnArray => "negate on array" . into_cow ( ) ,
355+ NegateOnRepeat => "negate on repeat" . into_cow ( ) ,
342356 NotOnFloat => "not on float or string" . into_cow ( ) ,
343357 NotOnString => "not on float or string" . into_cow ( ) ,
344358 NotOnBinary => "not on binary literal" . into_cow ( ) ,
345359 NotOnStruct => "not on struct" . into_cow ( ) ,
346360 NotOnTuple => "not on tuple" . into_cow ( ) ,
361+ NotOnArray => "not on array" . into_cow ( ) ,
362+ NotOnRepeat => "not on repeat" . into_cow ( ) ,
347363
348364 NegateWithOverflow ( ..) => "attempted to negate with overflow" . into_cow ( ) ,
349365 AddiWithOverflow ( ..) => "attempted to add with overflow" . into_cow ( ) ,
@@ -363,6 +379,12 @@ impl ConstEvalErr {
363379 ExpectedConstTuple => "expected constant tuple" . into_cow ( ) ,
364380 ExpectedConstStruct => "expected constant struct" . into_cow ( ) ,
365381 TupleIndexOutOfBounds => "tuple index out of bounds" . into_cow ( ) ,
382+ IndexedNonVec => "indexing is only supported for arrays" . into_cow ( ) ,
383+ IndexNotNatural => "indices must be a natural number" . into_cow ( ) ,
384+ IndexNotInt => "indices must be integers" . into_cow ( ) ,
385+ IndexOutOfBounds => "array index out of bounds" . into_cow ( ) ,
386+ RepeatCountNotNatural => "repeat count must be a natural number" . into_cow ( ) ,
387+ RepeatCountNotInt => "repeat count must be integers" . into_cow ( ) ,
366388
367389 MiscBinaryOp => "bad operands for binary" . into_cow ( ) ,
368390 MiscCatchAll => "unsupported constant expr" . into_cow ( ) ,
@@ -672,6 +694,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
672694 const_binary( _) => signal ! ( e, NegateOnBinary ) ,
673695 const_val:: Tuple ( _) => signal ! ( e, NegateOnTuple ) ,
674696 const_val:: Struct ( ..) => signal ! ( e, NegateOnStruct ) ,
697+ const_val:: Array ( _) => signal ! ( e, NegateOnArray ) ,
698+ const_val:: Repeat ( ..) => signal ! ( e, NegateOnRepeat ) ,
675699 }
676700 }
677701 ast:: ExprUnary ( ast:: UnNot , ref inner) => {
@@ -684,6 +708,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
684708 const_binary( _) => signal ! ( e, NotOnBinary ) ,
685709 const_val:: Tuple ( _) => signal ! ( e, NotOnTuple ) ,
686710 const_val:: Struct ( ..) => signal ! ( e, NotOnStruct ) ,
711+ const_val:: Array ( _) => signal ! ( e, NotOnArray ) ,
712+ const_val:: Repeat ( ..) => signal ! ( e, NotOnRepeat ) ,
687713 }
688714 }
689715 ast:: ExprBinary ( op, ref a, ref b) => {
@@ -873,6 +899,33 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
873899 ast:: ExprTup ( _) => {
874900 const_val:: Tuple ( e. id )
875901 }
902+ ast:: ExprIndex ( ref arr, ref idx) => {
903+ let arr = try!( eval_const_expr_partial ( tcx, arr, None ) ) ;
904+ let idx = try!( eval_const_expr_partial ( tcx, idx, None ) ) ;
905+ let idx = match idx {
906+ const_int( i) if i >= 0 => i as u64 ,
907+ const_int( _) => signal ! ( e, IndexNotNatural ) ,
908+ const_uint( i) => i,
909+ _ => signal ! ( e, IndexNotInt ) ,
910+ } ;
911+ match arr {
912+ const_val:: Array ( ref v) if idx as usize >= v. len ( ) => signal ! ( e, IndexOutOfBounds ) ,
913+ const_val:: Array ( v) => try!( eval_const_expr_partial ( tcx, & * v[ idx as usize ] , None ) ) ,
914+ const_val:: Repeat ( _, n) if idx >= n => signal ! ( e, IndexOutOfBounds ) ,
915+ const_val:: Repeat ( elem, _) => try!( eval_const_expr_partial ( tcx, & * elem, None ) ) ,
916+ _ => signal ! ( e, IndexedNonVec ) ,
917+ }
918+ }
919+ ast:: ExprVec ( ref arr) => const_val:: Array ( arr. clone ( ) ) , // FIXME: eval elements?
920+ ast:: ExprRepeat ( ref elem, ref n) => const_val:: Repeat (
921+ elem. clone ( ) ,
922+ match try!( eval_const_expr_partial ( tcx, & * * n, None ) ) {
923+ const_int( i) if i >= 0 => i as u64 ,
924+ const_int( _) => signal ! ( e, RepeatCountNotNatural ) ,
925+ const_uint( i) => i,
926+ _ => signal ! ( e, RepeatCountNotInt ) ,
927+ } ,
928+ ) ,
876929 ast:: ExprStruct ( ..) => {
877930 const_val:: Struct ( e. id )
878931 }
0 commit comments