@@ -609,14 +609,56 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
609609 } )
610610 }
611611
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+ }
620662 } ,
621663
622664 ast:: ExprCast ( ref base, _) => {
@@ -693,40 +735,14 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
693735 _ => break ,
694736 }
695737 }
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)
720741 } 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" )
730746 }
731747 }
732748 ast:: ExprAddrOf ( ast:: MutMutable , ref sub) => {
0 commit comments