Skip to content

Commit d05c099

Browse files
author
Oliver Schneider
committed
don't go through llvm for const indexing
1 parent 30a42fa commit d05c099

File tree

4 files changed

+76
-53
lines changed

4 files changed

+76
-53
lines changed

src/librustc/middle/const_eval.rs

+54-1
Original file line numberDiff line numberDiff line change
@@ -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

213215
pub 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
}

src/librustc/middle/ty.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -6198,7 +6198,9 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> usize {
61986198
const_eval::const_bool(_) => "boolean",
61996199
const_eval::const_binary(_) => "binary array",
62006200
const_eval::Struct(..) => "struct",
6201-
const_eval::Tuple(_) => "tuple"
6201+
const_eval::Tuple(_) => "tuple",
6202+
const_eval::Array(_) => "array",
6203+
const_eval::Repeat(..) => "repeat",
62026204
};
62036205
span_err!(tcx.sess, count_expr.span, E0306,
62046206
"expected positive integer for repeat count, found {}",

src/librustc_trans/trans/consts.rs

-51
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ use middle::ty::{self, Ty};
3434
use util::ppaux::{Repr, ty_to_string};
3535

3636
use std::iter::repeat;
37-
use libc::c_uint;
3837
use syntax::{ast, ast_util};
3938
use syntax::parse::token;
4039
use syntax::ptr::P;
@@ -565,56 +564,6 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
565564
})
566565
}
567566

568-
ast::ExprIndex(ref base, ref index) => {
569-
let (bv, bt) = const_expr(cx, &**base, param_substs);
570-
let iv = match const_eval::eval_const_expr_partial(cx.tcx(), &**index, None) {
571-
Ok(const_eval::const_int(i)) => i as u64,
572-
Ok(const_eval::const_uint(u)) => u,
573-
_ => cx.sess().span_bug(index.span,
574-
"index is not an integer-constant expression")
575-
};
576-
let (arr, len) = match bt.sty {
577-
ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)),
578-
ty::ty_vec(_, None) | ty::ty_str => {
579-
let e1 = const_get_elt(cx, bv, &[0]);
580-
(const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
581-
}
582-
ty::ty_rptr(_, mt) => match mt.ty.sty {
583-
ty::ty_vec(_, Some(u)) => {
584-
(const_deref_ptr(cx, bv), C_uint(cx, u))
585-
},
586-
_ => cx.sess().span_bug(base.span,
587-
&format!("index-expr base must be a vector \
588-
or string type, found {}",
589-
ty_to_string(cx.tcx(), bt)))
590-
},
591-
_ => cx.sess().span_bug(base.span,
592-
&format!("index-expr base must be a vector \
593-
or string type, found {}",
594-
ty_to_string(cx.tcx(), bt)))
595-
};
596-
597-
let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
598-
let len = match bt.sty {
599-
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty.sty {
600-
ty::ty_str => {
601-
assert!(len > 0);
602-
len - 1
603-
}
604-
_ => len
605-
},
606-
_ => len
607-
};
608-
if iv >= len {
609-
// FIXME #3170: report this earlier on in the const-eval
610-
// pass. Reporting here is a bit late.
611-
cx.sess().span_err(e.span,
612-
"const index-expr is out of bounds");
613-
C_undef(type_of::type_of(cx, bt).element_type())
614-
} else {
615-
const_get_elt(cx, arr, &[iv as c_uint])
616-
}
617-
}
618567
ast::ExprCast(ref base, _) => {
619568
let llty = type_of::type_of(cx, ety);
620569
let (v, basety) = const_expr(cx, &**base, param_substs);
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
12+
fn main() {
13+
//const range: Range<_> = 2..5;
14+
//const start: i32 = range.start;
15+
//const end: i32 = range.end;
16+
const arr: [i32; 6] = [42, 43, 44, 45, 46, 47];
17+
const idx: usize = 3;
18+
const val: i32 = arr[idx];
19+
}

0 commit comments

Comments
 (0)