auto merge of #7827 : jdm/rust/enumlength, r=graydon

Allowing them in type signatures is a significant amount of extra work, unfortunately. This also doesn't apply to static values, which takes a different code path.
This commit is contained in:
bors 2013-07-16 16:19:37 -07:00
commit 8a1002fbd9
7 changed files with 127 additions and 30 deletions

View File

@ -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<T: ty::ExprTyProvider>(tcx: &T, e: &expr)
-> Result<const_val, ~str> {
use middle::ty;
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)
}
}
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")
}
}

View File

@ -309,7 +309,7 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
"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,

View File

@ -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")

View File

@ -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<T: ExprTyProvider>(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;
}
}

View File

@ -479,7 +479,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
}
}
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) =>

View File

@ -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;
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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];
}