Skip to content

Commit 877bba9

Browse files
committed
Permit C-style enums in vector repeat length expressions (N.B. values only, not type signatures)
1 parent 274e7a4 commit 877bba9

File tree

7 files changed

+127
-30
lines changed

7 files changed

+127
-30
lines changed

src/librustc/middle/const_eval.rs

+53-5
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,58 @@ pub fn classify(e: &expr,
165165
pub fn lookup_const(tcx: ty::ctxt, e: &expr) -> Option<@expr> {
166166
match tcx.def_map.find(&e.id) {
167167
Some(&ast::def_static(def_id, false)) => lookup_const_by_id(tcx, def_id),
168+
Some(&ast::def_variant(enum_def, variant_def)) => lookup_variant_by_id(tcx,
169+
enum_def,
170+
variant_def),
168171
_ => None
169172
}
170173
}
171174

175+
pub fn lookup_variant_by_id(tcx: ty::ctxt,
176+
enum_def: ast::def_id,
177+
variant_def: ast::def_id)
178+
-> Option<@expr> {
179+
fn variant_expr(variants: &[ast::variant], id: ast::node_id) -> Option<@expr> {
180+
for variants.iter().advance |variant| {
181+
if variant.node.id == id {
182+
return variant.node.disr_expr;
183+
}
184+
}
185+
None
186+
}
187+
188+
if ast_util::is_local(enum_def) {
189+
match tcx.items.find(&enum_def.node) {
190+
None => None,
191+
Some(&ast_map::node_item(it, _)) => match it.node {
192+
item_enum(ast::enum_def { variants: ref variants }, _) => {
193+
variant_expr(*variants, variant_def.node)
194+
}
195+
_ => None
196+
},
197+
Some(_) => None
198+
}
199+
} else {
200+
let maps = astencode::Maps {
201+
root_map: @mut HashMap::new(),
202+
method_map: @mut HashMap::new(),
203+
vtable_map: @mut HashMap::new(),
204+
write_guard_map: @mut HashSet::new(),
205+
capture_map: @mut HashMap::new()
206+
};
207+
match csearch::maybe_get_item_ast(tcx, enum_def,
208+
|a, b, c, d| astencode::decode_inlined_item(a, b, maps, /*bar*/ copy c, d)) {
209+
csearch::found(ast::ii_item(item)) => match item.node {
210+
item_enum(ast::enum_def { variants: ref variants }, _) => {
211+
variant_expr(*variants, variant_def.node)
212+
}
213+
_ => None
214+
},
215+
_ => None
216+
}
217+
}
218+
}
219+
172220
pub fn lookup_const_by_id(tcx: ty::ctxt,
173221
def_id: ast::def_id)
174222
-> Option<@expr> {
@@ -237,13 +285,13 @@ pub enum const_val {
237285
}
238286

239287
pub fn eval_const_expr(tcx: middle::ty::ctxt, e: &expr) -> const_val {
240-
match eval_const_expr_partial(tcx, e) {
288+
match eval_const_expr_partial(&tcx, e) {
241289
Ok(r) => r,
242290
Err(s) => tcx.sess.span_fatal(e.span, s)
243291
}
244292
}
245293

246-
pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: &expr)
294+
pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &expr)
247295
-> Result<const_val, ~str> {
248296
use middle::ty;
249297
fn fromb(b: bool) -> Result<const_val, ~str> { Ok(const_int(b as i64)) }
@@ -360,7 +408,7 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: &expr)
360408
}
361409
}
362410
expr_cast(base, _) => {
363-
let ety = ty::expr_ty(tcx, e);
411+
let ety = tcx.expr_ty(e);
364412
let base = eval_const_expr_partial(tcx, base);
365413
match /*bad*/copy base {
366414
Err(_) => base,
@@ -390,8 +438,8 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: &expr)
390438
}
391439
}
392440
expr_path(_) => {
393-
match lookup_const(tcx, e) {
394-
Some(actual_e) => eval_const_expr_partial(tcx, actual_e),
441+
match lookup_const(tcx.ty_ctxt(), e) {
442+
Some(actual_e) => eval_const_expr_partial(&tcx.ty_ctxt(), actual_e),
395443
None => Err(~"Non-constant path in constant expr")
396444
}
397445
}

src/librustc/middle/kind.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
309309
"explicit copy requires a copyable argument");
310310
}
311311
expr_repeat(element, count_expr, _) => {
312-
let count = ty::eval_repeat_count(cx.tcx, count_expr);
312+
let count = ty::eval_repeat_count(&cx.tcx, count_expr);
313313
if count > 1 {
314314
let element_ty = ty::expr_ty(cx.tcx, element);
315315
check_copy(cx, element_ty, element.span,

src/librustc/middle/trans/tvec.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ pub fn write_content(bcx: block,
417417
return expr::trans_into(bcx, element, Ignore);
418418
}
419419
SaveIn(lldest) => {
420-
let count = ty::eval_repeat_count(bcx.tcx(), count_expr);
420+
let count = ty::eval_repeat_count(&bcx.tcx(), count_expr);
421421
if count == 0 {
422422
return bcx;
423423
}
@@ -509,7 +509,7 @@ pub fn elements_required(bcx: block, content_expr: &ast::expr) -> uint {
509509
},
510510
ast::expr_vec(ref es, _) => es.len(),
511511
ast::expr_repeat(_, count_expr, _) => {
512-
ty::eval_repeat_count(bcx.tcx(), count_expr)
512+
ty::eval_repeat_count(&bcx.tcx(), count_expr)
513513
}
514514
_ => bcx.tcx().sess.span_bug(content_expr.span,
515515
"Unexpected evec content")

src/librustc/middle/ty.rs

+31-16
Original file line numberDiff line numberDiff line change
@@ -4230,42 +4230,57 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
42304230
return t_norm;
42314231
}
42324232

4233+
pub trait ExprTyProvider {
4234+
pub fn expr_ty(&self, ex: &ast::expr) -> t;
4235+
pub fn ty_ctxt(&self) -> ctxt;
4236+
}
4237+
4238+
impl ExprTyProvider for ctxt {
4239+
pub fn expr_ty(&self, ex: &ast::expr) -> t {
4240+
expr_ty(*self, ex)
4241+
}
4242+
4243+
pub fn ty_ctxt(&self) -> ctxt {
4244+
*self
4245+
}
4246+
}
4247+
42334248
// Returns the repeat count for a repeating vector expression.
4234-
pub fn eval_repeat_count(tcx: ctxt, count_expr: &ast::expr) -> uint {
4249+
pub fn eval_repeat_count<T: ExprTyProvider>(tcx: &T, count_expr: &ast::expr) -> uint {
42354250
match const_eval::eval_const_expr_partial(tcx, count_expr) {
42364251
Ok(ref const_val) => match *const_val {
42374252
const_eval::const_int(count) => if count < 0 {
4238-
tcx.sess.span_err(count_expr.span,
4239-
"expected positive integer for \
4240-
repeat count but found negative integer");
4253+
tcx.ty_ctxt().sess.span_err(count_expr.span,
4254+
"expected positive integer for \
4255+
repeat count but found negative integer");
42414256
return 0;
42424257
} else {
42434258
return count as uint
42444259
},
42454260
const_eval::const_uint(count) => return count as uint,
42464261
const_eval::const_float(count) => {
4247-
tcx.sess.span_err(count_expr.span,
4248-
"expected positive integer for \
4249-
repeat count but found float");
4262+
tcx.ty_ctxt().sess.span_err(count_expr.span,
4263+
"expected positive integer for \
4264+
repeat count but found float");
42504265
return count as uint;
42514266
}
42524267
const_eval::const_str(_) => {
4253-
tcx.sess.span_err(count_expr.span,
4254-
"expected positive integer for \
4255-
repeat count but found string");
4268+
tcx.ty_ctxt().sess.span_err(count_expr.span,
4269+
"expected positive integer for \
4270+
repeat count but found string");
42564271
return 0;
42574272
}
42584273
const_eval::const_bool(_) => {
4259-
tcx.sess.span_err(count_expr.span,
4260-
"expected positive integer for \
4261-
repeat count but found boolean");
4274+
tcx.ty_ctxt().sess.span_err(count_expr.span,
4275+
"expected positive integer for \
4276+
repeat count but found boolean");
42624277
return 0;
42634278
}
42644279
},
42654280
Err(*) => {
4266-
tcx.sess.span_err(count_expr.span,
4267-
"expected constant integer for repeat count \
4268-
but found variable");
4281+
tcx.ty_ctxt().sess.span_err(count_expr.span,
4282+
"expected constant integer for repeat count \
4283+
but found variable");
42694284
return 0;
42704285
}
42714286
}

src/librustc/middle/typeck/astconv.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
479479
}
480480
}
481481
ast::ty_fixed_length_vec(ref a_mt, e) => {
482-
match const_eval::eval_const_expr_partial(tcx, e) {
482+
match const_eval::eval_const_expr_partial(&tcx, e) {
483483
Ok(ref r) => {
484484
match *r {
485485
const_eval::const_int(i) =>

src/librustc/middle/typeck/check/mod.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ use middle::pat_util;
8383
use middle::lint::unreachable_code;
8484
use middle::ty::{FnSig, VariantInfo_};
8585
use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
86-
use middle::ty::{substs, param_ty};
86+
use middle::ty::{substs, param_ty, ExprTyProvider};
8787
use middle::ty;
8888
use middle::typeck::astconv::AstConv;
8989
use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
@@ -290,6 +290,16 @@ pub fn blank_fn_ctxt(ccx: @mut CrateCtxt,
290290
}
291291
}
292292

293+
impl ExprTyProvider for FnCtxt {
294+
pub fn expr_ty(&self, ex: &ast::expr) -> ty::t {
295+
self.expr_ty(ex)
296+
}
297+
298+
pub fn ty_ctxt(&self) -> ty::ctxt {
299+
self.ccx.tcx
300+
}
301+
}
302+
293303
pub fn check_item_types(ccx: @mut CrateCtxt, crate: &ast::crate) {
294304
let visit = visit::mk_simple_visitor(@visit::SimpleVisitor {
295305
visit_item: |a| check_item(ccx, a),
@@ -797,7 +807,7 @@ impl FnCtxt {
797807
pat.repr(self.tcx())
798808
}
799809

800-
pub fn expr_ty(&self, ex: @ast::expr) -> ty::t {
810+
pub fn expr_ty(&self, ex: &ast::expr) -> ty::t {
801811
match self.inh.node_types.find(&ex.id) {
802812
Some(&t) => t,
803813
None => {
@@ -2250,8 +2260,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
22502260
}
22512261
}
22522262
ast::expr_repeat(element, count_expr, mutbl) => {
2253-
let _ = ty::eval_repeat_count(tcx, count_expr);
22542263
check_expr_with_hint(fcx, count_expr, ty::mk_uint());
2264+
let _ = ty::eval_repeat_count(fcx, count_expr);
22552265
let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
22562266
let mutability = match vst {
22572267
ast::expr_vstore_mut_box | ast::expr_vstore_mut_slice => {
@@ -2730,8 +2740,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
27302740
fcx.write_ty(id, typ);
27312741
}
27322742
ast::expr_repeat(element, count_expr, mutbl) => {
2733-
let count = ty::eval_repeat_count(tcx, count_expr);
27342743
check_expr_with_hint(fcx, count_expr, ty::mk_uint());
2744+
let count = ty::eval_repeat_count(fcx, count_expr);
27352745
let t: ty::t = fcx.infcx().next_ty_var();
27362746
check_expr_has_type(fcx, element, t);
27372747
let element_ty = fcx.expr_ty(element);
@@ -3126,7 +3136,7 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt,
31263136
// that the expression is in an form that eval_const_expr can
31273137
// handle, so we may still get an internal compiler error
31283138

3129-
match const_eval::eval_const_expr_partial(ccx.tcx, e) {
3139+
match const_eval::eval_const_expr_partial(&ccx.tcx, e) {
31303140
Ok(const_eval::const_int(val)) => {
31313141
*disr_val = val as int;
31323142
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2012 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+
enum Flopsy {
12+
Bunny = 2
13+
}
14+
15+
static BAR:uint = Bunny as uint;
16+
static BAR2:uint = BAR;
17+
18+
fn main() {
19+
let v = [0, .. Bunny as uint];
20+
let v = [0, .. BAR];
21+
let v = [0, .. BAR2];
22+
static BAR3:uint = BAR2;
23+
let v = [0, .. BAR3];
24+
}

0 commit comments

Comments
 (0)