@@ -609,14 +609,56 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
609
609
} )
610
610
}
611
611
612
- ast:: ExprIndex ( ..) => {
613
- match const_eval:: eval_const_expr_partial ( cx. tcx ( ) , & e, None ) {
614
- Ok ( val) => const_val_for_idx ( cx, val, param_substs, ety) ,
615
- Err ( err) => cx. sess ( ) . span_fatal (
616
- e. span ,
617
- & format ! ( "constant indexing failed: {}" , err. description( ) ) ,
618
- ) ,
619
- }
612
+ ast:: ExprIndex ( ref base, ref index) => {
613
+ if let Ok ( val) = const_eval:: eval_const_expr_partial ( cx. tcx ( ) , & e, None ) {
614
+ const_val_for_idx ( cx, val, param_substs, ety)
615
+ } else {
616
+ let ( bv, bt) = const_expr ( cx, & * * base, param_substs) ;
617
+ let iv = try!( eval_const_index ( tcx, idx) ) ;
618
+ let ( arr, len) = match bt. sty {
619
+ ty:: ty_vec( _, Some ( u) ) => ( bv, C_uint ( cx, u) ) ,
620
+ ty:: ty_vec( _, None ) | ty:: ty_str => {
621
+ let e1 = const_get_elt ( cx, bv, & [ 0 ] ) ;
622
+ ( const_deref_ptr ( cx, e1) , const_get_elt ( cx, bv, & [ 1 ] ) )
623
+ }
624
+ ty:: ty_rptr( _, mt) => match mt. ty . sty {
625
+ ty:: ty_vec( _, Some ( u) ) => {
626
+ ( const_deref_ptr ( cx, bv) , C_uint ( cx, u) )
627
+ } ,
628
+ _ => cx. sess ( ) . span_bug ( base. span ,
629
+ & format ! ( "index-expr base must be a vector \
630
+ or string type, found {}",
631
+ ty_to_string( cx. tcx( ) , bt) ) )
632
+ } ,
633
+ _ => cx. sess ( ) . span_bug ( base. span ,
634
+ & format ! ( "index-expr base must be a vector \
635
+ or string type, found {}",
636
+ ty_to_string( cx. tcx( ) , bt) ) )
637
+ } ;
638
+
639
+ let len = llvm:: LLVMConstIntGetZExtValue ( len) as u64 ;
640
+ let len = match bt. sty {
641
+ ty:: ty_uniq( ty) | ty:: ty_rptr( _, ty:: mt { ty, ..} ) => match ty. sty {
642
+ ty:: ty_str => {
643
+ assert ! ( len > 0 ) ;
644
+ len - 1
645
+ }
646
+ _ => len
647
+ } ,
648
+ _ => len
649
+ } ;
650
+ if iv >= len {
651
+ // FIXME #3170: report this earlier on in the const-eval
652
+ // pass. Reporting here is a bit late.
653
+ // Since some static-eval expressions aren't const-evaluable
654
+ // this has to stay
655
+ cx. sess ( ) . span_err ( e. span ,
656
+ "const index-expr is out of bounds" ) ;
657
+ C_undef ( type_of:: type_of ( cx, bt) . element_type ( ) )
658
+ } else {
659
+ const_get_elt ( cx, arr, & [ iv as c_uint ] )
660
+ }
661
+ }
620
662
} ,
621
663
622
664
ast:: ExprCast ( ref base, _) => {
@@ -693,40 +735,14 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
693
735
_ => break ,
694
736
}
695
737
}
696
- if let ast:: ExprIndex ( ref base, ref index) = cur. node {
697
- let ( bv, bt) = const_expr ( cx, & * * base, param_substs) ;
698
- let iv = match const_eval:: eval_const_expr_partial ( cx. tcx ( ) , & * * index, None ) {
699
- Ok ( const_eval:: const_int( i) ) => i as u64 ,
700
- Ok ( const_eval:: const_uint( u) ) => u,
701
- _ => unreachable ! ( ) ,
702
- } ;
703
- let arr = match bt. sty {
704
- ty:: ty_vec( _, Some ( _) ) => bv,
705
- ty:: ty_vec( _, None ) | ty:: ty_str => {
706
- let e1 = const_get_elt ( cx, bv, & [ 0 ] ) ;
707
- const_deref_ptr ( cx, e1)
708
- } ,
709
- ty:: ty_rptr( _, mt) => if let ty:: ty_vec( _, Some ( _) ) = mt. ty . sty {
710
- const_deref_ptr ( cx, bv)
711
- } else {
712
- unreachable ! ( )
713
- } ,
714
- _ => unreachable ! ( ) ,
715
- } ;
716
- // UB if const_eval wasn't called on this
717
- // since no len check happening here
718
- let v = const_get_elt ( cx, arr, & [ iv as c_uint ] ) ;
719
- addr_of ( cx, v, "ref" )
738
+ let opt_def = cx. tcx ( ) . def_map . borrow ( ) . get ( & cur. id ) . map ( |d| d. full_def ( ) ) ;
739
+ if let Some ( def:: DefStatic ( def_id, _) ) = opt_def {
740
+ get_static_val ( cx, def_id, ety)
720
741
} else {
721
- let opt_def = cx. tcx ( ) . def_map . borrow ( ) . get ( & cur. id ) . map ( |d| d. full_def ( ) ) ;
722
- if let Some ( def:: DefStatic ( def_id, _) ) = opt_def {
723
- get_static_val ( cx, def_id, ety)
724
- } else {
725
- // If this isn't the address of a static, then keep going through
726
- // normal constant evaluation.
727
- let ( v, _) = const_expr ( cx, & * * sub, param_substs) ;
728
- addr_of ( cx, v, "ref" )
729
- }
742
+ // If this isn't the address of a static, then keep going through
743
+ // normal constant evaluation.
744
+ let ( v, _) = const_expr ( cx, & * * sub, param_substs) ;
745
+ addr_of ( cx, v, "ref" )
730
746
}
731
747
}
732
748
ast:: ExprAddrOf ( ast:: MutMutable , ref sub) => {
0 commit comments