diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index af39dea6d79..2cf99e07dc9 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -165,10 +165,58 @@ pub fn classify(e: &expr, pub fn lookup_const(tcx: ty::ctxt, e: &expr) -> Option<@expr> { match tcx.def_map.find(&e.id) { Some(&ast::def_static(def_id, false)) => lookup_const_by_id(tcx, def_id), + Some(&ast::def_variant(enum_def, variant_def)) => lookup_variant_by_id(tcx, + enum_def, + variant_def), _ => None } } +pub fn lookup_variant_by_id(tcx: ty::ctxt, + enum_def: ast::def_id, + variant_def: ast::def_id) + -> Option<@expr> { + fn variant_expr(variants: &[ast::variant], id: ast::node_id) -> Option<@expr> { + for variants.iter().advance |variant| { + if variant.node.id == id { + return variant.node.disr_expr; + } + } + None + } + + if ast_util::is_local(enum_def) { + match tcx.items.find(&enum_def.node) { + None => None, + Some(&ast_map::node_item(it, _)) => match it.node { + item_enum(ast::enum_def { variants: ref variants }, _) => { + variant_expr(*variants, variant_def.node) + } + _ => None + }, + Some(_) => None + } + } else { + let maps = astencode::Maps { + root_map: @mut HashMap::new(), + method_map: @mut HashMap::new(), + vtable_map: @mut HashMap::new(), + write_guard_map: @mut HashSet::new(), + capture_map: @mut HashMap::new() + }; + match csearch::maybe_get_item_ast(tcx, enum_def, + |a, b, c, d| astencode::decode_inlined_item(a, b, maps, /*bar*/ copy c, d)) { + csearch::found(ast::ii_item(item)) => match item.node { + item_enum(ast::enum_def { variants: ref variants }, _) => { + variant_expr(*variants, variant_def.node) + } + _ => None + }, + _ => None + } + } +} + pub fn lookup_const_by_id(tcx: ty::ctxt, def_id: ast::def_id) -> Option<@expr> { @@ -237,13 +285,13 @@ pub enum const_val { } pub fn eval_const_expr(tcx: middle::ty::ctxt, e: &expr) -> const_val { - match eval_const_expr_partial(tcx, e) { + match eval_const_expr_partial(&tcx, e) { Ok(r) => r, Err(s) => tcx.sess.span_fatal(e.span, s) } } -pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: &expr) +pub fn eval_const_expr_partial(tcx: &T, e: &expr) -> Result { use middle::ty; fn fromb(b: bool) -> Result { Ok(const_int(b as i64)) } @@ -360,7 +408,7 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: &expr) } } expr_cast(base, _) => { - let ety = ty::expr_ty(tcx, e); + let ety = tcx.expr_ty(e); let base = eval_const_expr_partial(tcx, base); match /*bad*/copy base { Err(_) => base, @@ -390,8 +438,8 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: &expr) } } expr_path(_) => { - match lookup_const(tcx, e) { - Some(actual_e) => eval_const_expr_partial(tcx, actual_e), + match lookup_const(tcx.ty_ctxt(), e) { + Some(actual_e) => eval_const_expr_partial(&tcx.ty_ctxt(), actual_e), None => Err(~"Non-constant path in constant expr") } } diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index a9454d1b230..ae2a27ed6ed 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -309,7 +309,7 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt)) { "explicit copy requires a copyable argument"); } expr_repeat(element, count_expr, _) => { - let count = ty::eval_repeat_count(cx.tcx, count_expr); + let count = ty::eval_repeat_count(&cx.tcx, count_expr); if count > 1 { let element_ty = ty::expr_ty(cx.tcx, element); check_copy(cx, element_ty, element.span, diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index 8fff23c6498..561c9a3399a 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -417,7 +417,7 @@ pub fn write_content(bcx: block, return expr::trans_into(bcx, element, Ignore); } SaveIn(lldest) => { - let count = ty::eval_repeat_count(bcx.tcx(), count_expr); + let count = ty::eval_repeat_count(&bcx.tcx(), count_expr); if count == 0 { return bcx; } @@ -509,7 +509,7 @@ pub fn elements_required(bcx: block, content_expr: &ast::expr) -> uint { }, ast::expr_vec(ref es, _) => es.len(), ast::expr_repeat(_, count_expr, _) => { - ty::eval_repeat_count(bcx.tcx(), count_expr) + ty::eval_repeat_count(&bcx.tcx(), count_expr) } _ => bcx.tcx().sess.span_bug(content_expr.span, "Unexpected evec content") diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8e23f5431bc..eb69798d0cc 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4230,42 +4230,57 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t { return t_norm; } +pub trait ExprTyProvider { + pub fn expr_ty(&self, ex: &ast::expr) -> t; + pub fn ty_ctxt(&self) -> ctxt; +} + +impl ExprTyProvider for ctxt { + pub fn expr_ty(&self, ex: &ast::expr) -> t { + expr_ty(*self, ex) + } + + pub fn ty_ctxt(&self) -> ctxt { + *self + } +} + // Returns the repeat count for a repeating vector expression. -pub fn eval_repeat_count(tcx: ctxt, count_expr: &ast::expr) -> uint { +pub fn eval_repeat_count(tcx: &T, count_expr: &ast::expr) -> uint { match const_eval::eval_const_expr_partial(tcx, count_expr) { Ok(ref const_val) => match *const_val { const_eval::const_int(count) => if count < 0 { - tcx.sess.span_err(count_expr.span, - "expected positive integer for \ - repeat count but found negative integer"); + tcx.ty_ctxt().sess.span_err(count_expr.span, + "expected positive integer for \ + repeat count but found negative integer"); return 0; } else { return count as uint }, const_eval::const_uint(count) => return count as uint, const_eval::const_float(count) => { - tcx.sess.span_err(count_expr.span, - "expected positive integer for \ - repeat count but found float"); + tcx.ty_ctxt().sess.span_err(count_expr.span, + "expected positive integer for \ + repeat count but found float"); return count as uint; } const_eval::const_str(_) => { - tcx.sess.span_err(count_expr.span, - "expected positive integer for \ - repeat count but found string"); + tcx.ty_ctxt().sess.span_err(count_expr.span, + "expected positive integer for \ + repeat count but found string"); return 0; } const_eval::const_bool(_) => { - tcx.sess.span_err(count_expr.span, - "expected positive integer for \ - repeat count but found boolean"); + tcx.ty_ctxt().sess.span_err(count_expr.span, + "expected positive integer for \ + repeat count but found boolean"); return 0; } }, Err(*) => { - tcx.sess.span_err(count_expr.span, - "expected constant integer for repeat count \ - but found variable"); + tcx.ty_ctxt().sess.span_err(count_expr.span, + "expected constant integer for repeat count \ + but found variable"); return 0; } } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index d8185022e41..1186f8cecab 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -479,7 +479,7 @@ pub fn ast_ty_to_ty( } } ast::ty_fixed_length_vec(ref a_mt, e) => { - match const_eval::eval_const_expr_partial(tcx, e) { + match const_eval::eval_const_expr_partial(&tcx, e) { Ok(ref r) => { match *r { const_eval::const_int(i) => diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 4caf0b62a54..396fae68f73 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -83,7 +83,7 @@ use middle::pat_util; use middle::lint::unreachable_code; use middle::ty::{FnSig, VariantInfo_}; use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty}; -use middle::ty::{substs, param_ty}; +use middle::ty::{substs, param_ty, ExprTyProvider}; use middle::ty; use middle::typeck::astconv::AstConv; use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty}; @@ -290,6 +290,16 @@ pub fn blank_fn_ctxt(ccx: @mut CrateCtxt, } } +impl ExprTyProvider for FnCtxt { + pub fn expr_ty(&self, ex: &ast::expr) -> ty::t { + self.expr_ty(ex) + } + + pub fn ty_ctxt(&self) -> ty::ctxt { + self.ccx.tcx + } +} + pub fn check_item_types(ccx: @mut CrateCtxt, crate: &ast::crate) { let visit = visit::mk_simple_visitor(@visit::SimpleVisitor { visit_item: |a| check_item(ccx, a), @@ -797,7 +807,7 @@ impl FnCtxt { pat.repr(self.tcx()) } - pub fn expr_ty(&self, ex: @ast::expr) -> ty::t { + pub fn expr_ty(&self, ex: &ast::expr) -> ty::t { match self.inh.node_types.find(&ex.id) { Some(&t) => t, None => { @@ -2250,8 +2260,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } ast::expr_repeat(element, count_expr, mutbl) => { - let _ = ty::eval_repeat_count(tcx, count_expr); check_expr_with_hint(fcx, count_expr, ty::mk_uint()); + let _ = ty::eval_repeat_count(fcx, count_expr); let tt = ast_expr_vstore_to_vstore(fcx, ev, vst); let mutability = match vst { ast::expr_vstore_mut_box | ast::expr_vstore_mut_slice => { @@ -2730,8 +2740,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_ty(id, typ); } ast::expr_repeat(element, count_expr, mutbl) => { - let count = ty::eval_repeat_count(tcx, count_expr); check_expr_with_hint(fcx, count_expr, ty::mk_uint()); + let count = ty::eval_repeat_count(fcx, count_expr); let t: ty::t = fcx.infcx().next_ty_var(); check_expr_has_type(fcx, element, t); let element_ty = fcx.expr_ty(element); @@ -3126,7 +3136,7 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt, // that the expression is in an form that eval_const_expr can // handle, so we may still get an internal compiler error - match const_eval::eval_const_expr_partial(ccx.tcx, e) { + match const_eval::eval_const_expr_partial(&ccx.tcx, e) { Ok(const_eval::const_int(val)) => { *disr_val = val as int; } diff --git a/src/test/run-pass/enum-vec-initializer.rs b/src/test/run-pass/enum-vec-initializer.rs new file mode 100644 index 00000000000..ae590ad7d1f --- /dev/null +++ b/src/test/run-pass/enum-vec-initializer.rs @@ -0,0 +1,24 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Flopsy { + Bunny = 2 +} + +static BAR:uint = Bunny as uint; +static BAR2:uint = BAR; + +fn main() { + let v = [0, .. Bunny as uint]; + let v = [0, .. BAR]; + let v = [0, .. BAR2]; + static BAR3:uint = BAR2; + let v = [0, .. BAR3]; +} \ No newline at end of file