Skip to content

Commit 332233b

Browse files
Oliver SchneiderOliver Schneider
Oliver Schneider
authored and
Oliver Schneider
committed
treat statics like consts during const eval + fix const integers
1 parent 81c7382 commit 332233b

File tree

8 files changed

+57
-28
lines changed

8 files changed

+57
-28
lines changed

src/librustc/middle/const_eval.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ pub enum ErrKind {
308308
NotOnArray,
309309
NotOnRepeat,
310310
NotOnRef,
311-
311+
312312
DerefInt,
313313
DerefUInt,
314314
DerefBool,
@@ -344,7 +344,7 @@ pub enum ErrKind {
344344
IndexOutOfBounds,
345345
RepeatCountNotNatural,
346346
RepeatCountNotInt,
347-
MutableRef,
347+
MutableRef,
348348

349349
MiscBinaryOp,
350350
MiscCatchAll,
@@ -377,7 +377,7 @@ impl ConstEvalErr {
377377
NotOnArray => "not on array".into_cow(),
378378
NotOnRepeat => "not on repeat".into_cow(),
379379
NotOnRef => "not on ref".into_cow(),
380-
380+
381381
DerefInt => "deref on int".into_cow(),
382382
DerefUInt => "deref on unsigned int".into_cow(),
383383
DerefBool => "deref on float".into_cow(),
@@ -413,7 +413,7 @@ impl ConstEvalErr {
413413
IndexOutOfBounds => "array index out of bounds".into_cow(),
414414
RepeatCountNotNatural => "repeat count must be a natural number".into_cow(),
415415
RepeatCountNotInt => "repeat count must be integers".into_cow(),
416-
MutableRef => "cannot get a mutable reference to a constant".into_cow(),
416+
MutableRef => "cannot get a mutable reference to a constant".into_cow(),
417417

418418
MiscBinaryOp => "bad operands for binary".into_cow(),
419419
MiscCatchAll => "unsupported constant expr".into_cow(),
@@ -887,13 +887,17 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
887887
ast::ExprPath(..) => {
888888
let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
889889
let (const_expr, const_ty) = match opt_def {
890-
Some(def::DefConst(def_id)) => {
890+
Some(def::DefConst(def_id))
891+
| Some(def::DefStatic(def_id, false)) => {
891892
if ast_util::is_local(def_id) {
892893
match tcx.map.find(def_id.node) {
893894
Some(ast_map::NodeItem(it)) => match it.node {
894895
ast::ItemConst(ref ty, ref expr) => {
895896
(Some(&**expr), Some(&**ty))
896897
}
898+
ast::ItemStatic(ref ty, ast::MutImmutable, ref expr) => {
899+
(Some(&**expr), Some(&**ty))
900+
}
897901
_ => (None, None)
898902
},
899903
_ => (None, None)
@@ -974,12 +978,21 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
974978
} else {
975979
unreachable!()
976980
},
981+
977982
const_val::Repeat(_, n) if idx >= n => signal!(e, IndexOutOfBounds),
978983
const_val::Repeat(elem, _) => try!(eval_const_expr_partial(
979984
tcx,
980985
&*tcx.map.expect_expr(elem),
981986
None,
982-
)),
987+
)),
988+
989+
const_val::const_binary(ref data) if idx as usize >= data.len()
990+
=> signal!(e, IndexOutOfBounds),
991+
const_val::const_binary(data) => const_val::const_uint(data[idx as usize] as u64),
992+
993+
const_val::const_str(ref s) if idx as usize >= s.len()
994+
=> signal!(e, IndexOutOfBounds),
995+
const_val::const_str(_) => unimplemented!(), // there's no const_char type
983996
_ => signal!(e, IndexedNonVec),
984997
}
985998
}

src/librustc_trans/trans/common.rs

-4
Original file line numberDiff line numberDiff line change
@@ -788,10 +788,6 @@ pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
788788
C_integral(Type::i64(ccx), i, false)
789789
}
790790

791-
pub fn C_i64(ccx: &CrateContext, i: i64) -> ValueRef {
792-
C_integral(Type::i64(ccx), i as u64, true)
793-
}
794-
795791
pub fn C_int<I: AsI64>(ccx: &CrateContext, i: I) -> ValueRef {
796792
let v = i.as_i64();
797793

src/librustc_trans/trans/consts.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,34 @@ fn const_val_for_idx<'a, 'tcx>(
4343
cx: &CrateContext<'a, 'tcx>,
4444
val: const_eval::const_val,
4545
param_substs: &'tcx Substs<'tcx>,
46+
ety: Ty<'tcx>,
4647
) -> ValueRef
4748
{
4849
let id2val = |id| {
4950
let expr = cx.tcx().map.expect_expr(id);
5051
const_expr(cx, expr, param_substs).0
5152
};
5253
match val {
53-
const_eval::const_int(i) => C_i64(cx, i), // this might be wrong
54-
const_eval::const_uint(u) => C_u64(cx, u), // this too
54+
const_eval::const_int(i) => if let ty::ty_int(t) = ety.sty {
55+
C_integral(Type::int_from_ty(cx, t), i as u64, true)
56+
} else {
57+
cx.sess().bug(
58+
&format!(
59+
"integer literal has type {}",
60+
ty_to_string(cx.tcx(), ety),
61+
)
62+
)
63+
},
64+
const_eval::const_uint(u) => if let ty::ty_uint(t) = ety.sty {
65+
C_integral(Type::uint_from_ty(cx, t), u as u64, false)
66+
} else {
67+
cx.sess().bug(
68+
&format!(
69+
"unsigned integer literal has type {}",
70+
ty_to_string(cx.tcx(), ety),
71+
)
72+
)
73+
},
5574
const_eval::const_float(f) => C_floating(&f.to_string(), Type::f64(cx)),
5675
const_eval::const_str(s) => C_str_slice(cx, s),
5776
const_eval::const_binary(data) => addr_of(cx, C_bytes(cx, &data[..]), "binary"),
@@ -60,7 +79,7 @@ fn const_val_for_idx<'a, 'tcx>(
6079
const_eval::Tuple(id) => id2val(id),
6180
const_eval::Array(id, _) => id2val(id),
6281
const_eval::Repeat(id, _) => id2val(id),
63-
const_eval::Ref(inner) => const_val_for_idx(cx, *inner, param_substs),
82+
const_eval::Ref(inner) => const_val_for_idx(cx, *inner, param_substs, ety),
6483
}
6584
}
6685

@@ -592,7 +611,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
592611

593612
ast::ExprIndex(..) => {
594613
match const_eval::eval_const_expr_partial(cx.tcx(), &e, None) {
595-
Ok(val) => const_val_for_idx(cx, val, param_substs),
614+
Ok(val) => const_val_for_idx(cx, val, param_substs, ety),
596615
Err(err) => cx.sess().span_fatal(
597616
e.span,
598617
&format!("constant indexing failed: {}", err.description()),

src/test/run-pass/array_const_index-0.rs renamed to src/test/compile-fail/array_const_index-0.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99
// except according to those terms.
1010

1111
static a: &'static [i32] = &[];
12-
static b: i32 = a[1];
12+
static b: i32 = (&a)[1]; //~ ERROR: constant indexing failed: array index out of bounds
1313

14-
fn main() {}
14+
fn main() {}

src/test/compile-fail/const-array-oob.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
const FOO: [u32; 3] = [1, 2, 3];
12-
const BAR: u32 = FOO[5]; //~ ERROR const index-expr is out of bounds
12+
const BAR: u32 = FOO[5]; //~ ERROR constant indexing failed: array index out of bounds
1313

1414
fn main() {
1515
let _ = BAR;

src/test/run-pass/check-static-slice.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ const AD: &'static [isize] = &AA;
1919
const AE: &'static [isize; 3] = &[1, 2, 3];
2020
const AF: &'static [isize] = &[1, 2, 3];
2121

22-
const CA: isize = AA[0];
23-
const CB: isize = AB[1];
24-
const CC: isize = AC[2];
25-
const CD: isize = AD[0];
26-
const CE: isize = AE[1];
27-
const CF: isize = AF[2];
22+
static CA: isize = AA[0];
23+
static CB: isize = AB[1];
24+
static CC: isize = AC[2];
25+
static CD: isize = AD[0];
26+
static CE: isize = AE[1];
27+
static CF: isize = AF[2];
2828

29-
const AG: &'static isize = &AA[2];
29+
static AG: &'static isize = &AA[2];
3030

3131
fn main () {
3232
let b: &[isize] = &[1, 2, 3];

src/test/run-pass/const-enum-vec-index.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ enum E { V1(isize), V0 }
1313
const C: &'static [E] = &[E::V0, E::V1(0xDEADBEE)];
1414
static C0: E = C[0];
1515
static C1: E = C[1];
16-
const D: &'static [E; 2] = &[E::V0, E::V1(0xDEADBEE)];
17-
static D0: E = C[0];
18-
static D1: E = C[1];
16+
const D: &'static [E; 2] = &[E::V0, E::V1(0xDEAFBEE)];
17+
static D0: E = D[0];
18+
static D1: E = D[1];
1919

2020
pub fn main() {
2121
match C0 {
@@ -32,7 +32,7 @@ pub fn main() {
3232
_ => panic!()
3333
}
3434
match D1 {
35-
E::V1(n) => assert!(n == 0xDEADBEE),
35+
E::V1(n) => assert!(n == 0xDEAFBEE),
3636
_ => panic!()
3737
}
3838
}

src/test/run-pass/const-str-ptr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const C: *const u8 = B as *const u8;
1818
pub fn main() {
1919
unsafe {
2020
let foo = &A as *const u8;
21+
assert_eq!(foo, C);
2122
assert_eq!(str::from_utf8_unchecked(&A), "hi");
2223
assert!(*C == A[0]);
2324
assert!(*(&B[0] as *const u8) == A[0]);

0 commit comments

Comments
 (0)