@@ -266,7 +266,10 @@ pub enum const_val {
266
266
const_binary( Rc < Vec < u8 > > ) ,
267
267
const_bool( bool ) ,
268
268
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 > ) ,
270
273
}
271
274
272
275
pub fn const_expr_to_pat ( tcx : & ty:: ctxt , expr : & Expr , span : Span ) -> P < ast:: Pat > {
@@ -353,11 +356,28 @@ pub enum ErrKind {
353
356
NegateOnBinary ,
354
357
NegateOnStruct ,
355
358
NegateOnTuple ,
359
+ NegateOnArray ,
360
+ NegateOnRepeat ,
361
+ NegateOnRef ,
356
362
NotOnFloat ,
357
363
NotOnString ,
358
364
NotOnBinary ,
359
365
NotOnStruct ,
360
366
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 ,
361
381
362
382
NegateWithOverflow ( i64 ) ,
363
383
AddiWithOverflow ( i64 , i64 ) ,
@@ -377,6 +397,13 @@ pub enum ErrKind {
377
397
ExpectedConstTuple ,
378
398
ExpectedConstStruct ,
379
399
TupleIndexOutOfBounds ,
400
+ IndexedNonVec ,
401
+ IndexNotNatural ,
402
+ IndexNotInt ,
403
+ IndexOutOfBounds ,
404
+ RepeatCountNotNatural ,
405
+ RepeatCountNotInt ,
406
+ MutableRef ,
380
407
381
408
MiscBinaryOp ,
382
409
MiscCatchAll ,
@@ -398,11 +425,28 @@ impl ConstEvalErr {
398
425
NegateOnBinary => "negate on binary literal" . into_cow ( ) ,
399
426
NegateOnStruct => "negate on struct" . into_cow ( ) ,
400
427
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 ( ) ,
401
431
NotOnFloat => "not on float or string" . into_cow ( ) ,
402
432
NotOnString => "not on float or string" . into_cow ( ) ,
403
433
NotOnBinary => "not on binary literal" . into_cow ( ) ,
404
434
NotOnStruct => "not on struct" . into_cow ( ) ,
405
435
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 ( ) ,
406
450
407
451
NegateWithOverflow ( ..) => "attempted to negate with overflow" . into_cow ( ) ,
408
452
AddiWithOverflow ( ..) => "attempted to add with overflow" . into_cow ( ) ,
@@ -422,6 +466,13 @@ impl ConstEvalErr {
422
466
ExpectedConstTuple => "expected constant tuple" . into_cow ( ) ,
423
467
ExpectedConstStruct => "expected constant struct" . into_cow ( ) ,
424
468
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 ( ) ,
425
476
426
477
MiscBinaryOp => "bad operands for binary" . into_cow ( ) ,
427
478
MiscCatchAll => "unsupported constant expr" . into_cow ( ) ,
@@ -530,6 +581,15 @@ fn const_uint_not(a: u64, opt_ety: Option<UintTy>) -> const_val {
530
581
const_uint ( !a & mask)
531
582
}
532
583
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
+
533
593
macro_rules! overflow_checking_body {
534
594
( $a: ident, $b: ident, $ety: ident, $overflowing_op: ident,
535
595
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>,
741
801
const_binary( _) => signal ! ( e, NegateOnBinary ) ,
742
802
const_val:: Tuple ( _) => signal ! ( e, NegateOnTuple ) ,
743
803
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 ) ,
744
807
}
745
808
}
746
809
ast:: ExprUnary ( ast:: UnNot , ref inner) => {
@@ -753,6 +816,24 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
753
816
const_binary( _) => signal ! ( e, NotOnBinary ) ,
754
817
const_val:: Tuple ( _) => signal ! ( e, NotOnTuple ) ,
755
818
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,
756
837
}
757
838
}
758
839
ast:: ExprBinary ( op, ref a, ref b) => {
@@ -936,12 +1017,57 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
936
1017
ast:: ExprBlock ( ref block) => {
937
1018
match block. expr {
938
1019
Some ( ref expr) => try!( eval_const_expr_partial ( tcx, & * * expr, ety) ) ,
939
- None => const_int ( 0 )
1020
+ None => unreachable ! ( ) ,
940
1021
}
941
1022
}
942
1023
ast:: ExprTup ( _) => {
943
1024
const_val:: Tuple ( e. id )
944
1025
}
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
+ ) ,
945
1071
ast:: ExprStruct ( ..) => {
946
1072
const_val:: Struct ( e. id )
947
1073
}
0 commit comments