@@ -266,7 +266,10 @@ pub enum const_val {
266266 const_binary( Rc < Vec < u8 > > ) ,
267267 const_bool( bool ) ,
268268 Struct ( ast:: NodeId ) ,
269- Tuple ( ast:: NodeId )
269+ Tuple ( ast:: NodeId ) ,
270+ Array ( ast:: NodeId , u64 ) ,
271+ Repeat ( ast:: NodeId , u64 ) ,
272+ Ref ( Box < const_val > ) ,
270273}
271274
272275pub fn const_expr_to_pat ( tcx : & ty:: ctxt , expr : & Expr , span : Span ) -> P < ast:: Pat > {
@@ -353,11 +356,28 @@ pub enum ErrKind {
353356 NegateOnBinary ,
354357 NegateOnStruct ,
355358 NegateOnTuple ,
359+ NegateOnArray ,
360+ NegateOnRepeat ,
361+ NegateOnRef ,
356362 NotOnFloat ,
357363 NotOnString ,
358364 NotOnBinary ,
359365 NotOnStruct ,
360366 NotOnTuple ,
367+ NotOnArray ,
368+ NotOnRepeat ,
369+ NotOnRef ,
370+
371+ DerefInt ,
372+ DerefUInt ,
373+ DerefBool ,
374+ DerefString ,
375+ DerefFloat ,
376+ DerefBinary ,
377+ DerefTuple ,
378+ DerefStruct ,
379+ DerefArray ,
380+ DerefRepeat ,
361381
362382 NegateWithOverflow ( i64 ) ,
363383 AddiWithOverflow ( i64 , i64 ) ,
@@ -377,6 +397,13 @@ pub enum ErrKind {
377397 ExpectedConstTuple ,
378398 ExpectedConstStruct ,
379399 TupleIndexOutOfBounds ,
400+ IndexedNonVec ,
401+ IndexNotNatural ,
402+ IndexNotInt ,
403+ IndexOutOfBounds ,
404+ RepeatCountNotNatural ,
405+ RepeatCountNotInt ,
406+ MutableRef ,
380407
381408 MiscBinaryOp ,
382409 MiscCatchAll ,
@@ -398,11 +425,28 @@ impl ConstEvalErr {
398425 NegateOnBinary => "negate on binary literal" . into_cow ( ) ,
399426 NegateOnStruct => "negate on struct" . into_cow ( ) ,
400427 NegateOnTuple => "negate on tuple" . into_cow ( ) ,
428+ NegateOnArray => "negate on array" . into_cow ( ) ,
429+ NegateOnRepeat => "negate on repeat" . into_cow ( ) ,
430+ NegateOnRef => "negate on ref" . into_cow ( ) ,
401431 NotOnFloat => "not on float or string" . into_cow ( ) ,
402432 NotOnString => "not on float or string" . into_cow ( ) ,
403433 NotOnBinary => "not on binary literal" . into_cow ( ) ,
404434 NotOnStruct => "not on struct" . into_cow ( ) ,
405435 NotOnTuple => "not on tuple" . into_cow ( ) ,
436+ NotOnArray => "not on array" . into_cow ( ) ,
437+ NotOnRepeat => "not on repeat" . into_cow ( ) ,
438+ NotOnRef => "not on ref" . into_cow ( ) ,
439+
440+ DerefInt => "deref on int" . into_cow ( ) ,
441+ DerefUInt => "deref on unsigned int" . into_cow ( ) ,
442+ DerefBool => "deref on float" . into_cow ( ) ,
443+ DerefFloat => "deref on float" . into_cow ( ) ,
444+ DerefString => "deref on string" . into_cow ( ) ,
445+ DerefBinary => "deref on binary literal" . into_cow ( ) ,
446+ DerefStruct => "deref on struct" . into_cow ( ) ,
447+ DerefTuple => "deref on tuple" . into_cow ( ) ,
448+ DerefArray => "deref on array" . into_cow ( ) ,
449+ DerefRepeat => "deref on repeat" . into_cow ( ) ,
406450
407451 NegateWithOverflow ( ..) => "attempted to negate with overflow" . into_cow ( ) ,
408452 AddiWithOverflow ( ..) => "attempted to add with overflow" . into_cow ( ) ,
@@ -422,6 +466,13 @@ impl ConstEvalErr {
422466 ExpectedConstTuple => "expected constant tuple" . into_cow ( ) ,
423467 ExpectedConstStruct => "expected constant struct" . into_cow ( ) ,
424468 TupleIndexOutOfBounds => "tuple index out of bounds" . into_cow ( ) ,
469+ IndexedNonVec => "indexing is only supported for arrays" . into_cow ( ) ,
470+ IndexNotNatural => "indices must be a natural number" . into_cow ( ) ,
471+ IndexNotInt => "indices must be integers" . into_cow ( ) ,
472+ IndexOutOfBounds => "array index out of bounds" . into_cow ( ) ,
473+ RepeatCountNotNatural => "repeat count must be a natural number" . into_cow ( ) ,
474+ RepeatCountNotInt => "repeat count must be integers" . into_cow ( ) ,
475+ MutableRef => "cannot get a mutable reference to a constant" . into_cow ( ) ,
425476
426477 MiscBinaryOp => "bad operands for binary" . into_cow ( ) ,
427478 MiscCatchAll => "unsupported constant expr" . into_cow ( ) ,
@@ -530,6 +581,15 @@ fn const_uint_not(a: u64, opt_ety: Option<UintTy>) -> const_val {
530581 const_uint ( !a & mask)
531582}
532583
584+ pub fn eval_const_index ( tcx : & ty:: ctxt , idx : & Expr ) -> Result < u64 , ConstEvalErr > {
585+ match try!( eval_const_expr_partial ( tcx, idx, None ) ) {
586+ const_int( i) if i >= 0 => Ok ( i as u64 ) ,
587+ const_int( _) => signal ! ( idx, IndexNotNatural ) ,
588+ const_uint( i) => Ok ( i) ,
589+ _ => signal ! ( idx, IndexNotInt ) ,
590+ }
591+ }
592+
533593macro_rules! overflow_checking_body {
534594 ( $a: ident, $b: ident, $ety: ident, $overflowing_op: ident,
535595 lhs: $to_8_lhs: ident $to_16_lhs: ident $to_32_lhs: ident,
@@ -741,6 +801,9 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
741801 const_binary( _) => signal ! ( e, NegateOnBinary ) ,
742802 const_val:: Tuple ( _) => signal ! ( e, NegateOnTuple ) ,
743803 const_val:: Struct ( ..) => signal ! ( e, NegateOnStruct ) ,
804+ const_val:: Array ( ..) => signal ! ( e, NegateOnArray ) ,
805+ const_val:: Repeat ( ..) => signal ! ( e, NegateOnRepeat ) ,
806+ const_val:: Ref ( _) => signal ! ( e, NegateOnRef ) ,
744807 }
745808 }
746809 ast:: ExprUnary ( ast:: UnNot , ref inner) => {
@@ -753,6 +816,24 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
753816 const_binary( _) => signal ! ( e, NotOnBinary ) ,
754817 const_val:: Tuple ( _) => signal ! ( e, NotOnTuple ) ,
755818 const_val:: Struct ( ..) => signal ! ( e, NotOnStruct ) ,
819+ const_val:: Array ( ..) => signal ! ( e, NotOnArray ) ,
820+ const_val:: Repeat ( ..) => signal ! ( e, NotOnRepeat ) ,
821+ const_val:: Ref ( _) => signal ! ( e, NotOnRef ) ,
822+ }
823+ }
824+ ast:: ExprUnary ( ast:: UnDeref , ref inner) => {
825+ match try!( eval_const_expr_partial ( tcx, & * * inner, ety) ) {
826+ const_int( _) => signal ! ( e, DerefInt ) ,
827+ const_uint( _) => signal ! ( e, DerefUInt ) ,
828+ const_bool( _) => signal ! ( e, DerefBool ) ,
829+ const_str( _) => signal ! ( e, DerefString ) ,
830+ const_float( _) => signal ! ( e, DerefFloat ) ,
831+ const_binary( _) => signal ! ( e, DerefBinary ) ,
832+ const_val:: Tuple ( _) => signal ! ( e, DerefTuple ) ,
833+ const_val:: Struct ( ..) => signal ! ( e, DerefStruct ) ,
834+ const_val:: Array ( ..) => signal ! ( e, DerefArray ) ,
835+ const_val:: Repeat ( ..) => signal ! ( e, DerefRepeat ) ,
836+ const_val:: Ref ( inner) => * inner,
756837 }
757838 }
758839 ast:: ExprBinary ( op, ref a, ref b) => {
@@ -936,12 +1017,57 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
9361017 ast:: ExprBlock ( ref block) => {
9371018 match block. expr {
9381019 Some ( ref expr) => try!( eval_const_expr_partial ( tcx, & * * expr, ety) ) ,
939- None => const_int ( 0 )
1020+ None => unreachable ! ( ) ,
9401021 }
9411022 }
9421023 ast:: ExprTup ( _) => {
9431024 const_val:: Tuple ( e. id )
9441025 }
1026+ ast:: ExprIndex ( ref arr, ref idx) => {
1027+ let mut arr = try!( eval_const_expr_partial ( tcx, arr, None ) ) ;
1028+ while let const_val:: Ref ( inner) = arr {
1029+ arr = * inner;
1030+ }
1031+ let idx = try!( eval_const_index ( tcx, idx) ) ;
1032+ match arr {
1033+ const_val:: Array ( _, n) if idx >= n => signal ! ( e, IndexOutOfBounds ) ,
1034+ const_val:: Array ( v, _) => if let ast:: ExprVec ( ref v) = tcx. map . expect_expr ( v) . node {
1035+ try!( eval_const_expr_partial ( tcx, & * v[ idx as usize ] , None ) )
1036+ } else {
1037+ unreachable ! ( )
1038+ } ,
1039+
1040+ const_val:: Repeat ( _, n) if idx >= n => signal ! ( e, IndexOutOfBounds ) ,
1041+ const_val:: Repeat ( elem, _) => try!( eval_const_expr_partial (
1042+ tcx,
1043+ & * tcx. map . expect_expr ( elem) ,
1044+ None ,
1045+ ) ) ,
1046+
1047+ const_val:: const_binary( ref data) if idx as usize >= data. len ( )
1048+ => signal ! ( e, IndexOutOfBounds ) ,
1049+ const_val:: const_binary( data) => const_val:: const_uint ( data[ idx as usize ] as u64 ) ,
1050+
1051+ const_val:: const_str( ref s) if idx as usize >= s. len ( )
1052+ => signal ! ( e, IndexOutOfBounds ) ,
1053+ const_val:: const_str( _) => unimplemented ! ( ) , // there's no const_char type
1054+ _ => signal ! ( e, IndexedNonVec ) ,
1055+ }
1056+ }
1057+ ast:: ExprAddrOf ( ast:: Mutability :: MutMutable , _) => signal ! ( e, MutableRef ) ,
1058+ ast:: ExprAddrOf ( ast:: Mutability :: MutImmutable , ref expr) => {
1059+ const_val:: Ref ( Box :: new ( try!( eval_const_expr_partial ( tcx, & * * expr, None ) ) ) )
1060+ } ,
1061+ ast:: ExprVec ( ref v) => const_val:: Array ( e. id , v. len ( ) as u64 ) ,
1062+ ast:: ExprRepeat ( _, ref n) => const_val:: Repeat (
1063+ e. id ,
1064+ match try!( eval_const_expr_partial ( tcx, & * * n, None ) ) {
1065+ const_int( i) if i >= 0 => i as u64 ,
1066+ const_int( _) => signal ! ( e, RepeatCountNotNatural ) ,
1067+ const_uint( i) => i,
1068+ _ => signal ! ( e, RepeatCountNotInt ) ,
1069+ } ,
1070+ ) ,
9451071 ast:: ExprStruct ( ..) => {
9461072 const_val:: Struct ( e. id )
9471073 }
0 commit comments