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:
commit
8a1002fbd9
|
@ -165,10 +165,58 @@ pub fn classify(e: &expr,
|
||||||
pub fn lookup_const(tcx: ty::ctxt, e: &expr) -> Option<@expr> {
|
pub fn lookup_const(tcx: ty::ctxt, e: &expr) -> Option<@expr> {
|
||||||
match tcx.def_map.find(&e.id) {
|
match tcx.def_map.find(&e.id) {
|
||||||
Some(&ast::def_static(def_id, false)) => lookup_const_by_id(tcx, def_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
|
_ => 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,
|
pub fn lookup_const_by_id(tcx: ty::ctxt,
|
||||||
def_id: ast::def_id)
|
def_id: ast::def_id)
|
||||||
-> Option<@expr> {
|
-> Option<@expr> {
|
||||||
|
@ -237,13 +285,13 @@ pub enum const_val {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval_const_expr(tcx: middle::ty::ctxt, e: &expr) -> 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,
|
Ok(r) => r,
|
||||||
Err(s) => tcx.sess.span_fatal(e.span, s)
|
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> {
|
-> Result<const_val, ~str> {
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
fn fromb(b: bool) -> Result<const_val, ~str> { Ok(const_int(b as i64)) }
|
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, _) => {
|
expr_cast(base, _) => {
|
||||||
let ety = ty::expr_ty(tcx, e);
|
let ety = tcx.expr_ty(e);
|
||||||
let base = eval_const_expr_partial(tcx, base);
|
let base = eval_const_expr_partial(tcx, base);
|
||||||
match /*bad*/copy base {
|
match /*bad*/copy base {
|
||||||
Err(_) => base,
|
Err(_) => base,
|
||||||
|
@ -390,8 +438,8 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: &expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr_path(_) => {
|
expr_path(_) => {
|
||||||
match lookup_const(tcx, e) {
|
match lookup_const(tcx.ty_ctxt(), e) {
|
||||||
Some(actual_e) => eval_const_expr_partial(tcx, actual_e),
|
Some(actual_e) => eval_const_expr_partial(&tcx.ty_ctxt(), actual_e),
|
||||||
None => Err(~"Non-constant path in constant expr")
|
None => Err(~"Non-constant path in constant expr")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,7 +309,7 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
|
||||||
"explicit copy requires a copyable argument");
|
"explicit copy requires a copyable argument");
|
||||||
}
|
}
|
||||||
expr_repeat(element, count_expr, _) => {
|
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 {
|
if count > 1 {
|
||||||
let element_ty = ty::expr_ty(cx.tcx, element);
|
let element_ty = ty::expr_ty(cx.tcx, element);
|
||||||
check_copy(cx, element_ty, element.span,
|
check_copy(cx, element_ty, element.span,
|
||||||
|
|
|
@ -417,7 +417,7 @@ pub fn write_content(bcx: block,
|
||||||
return expr::trans_into(bcx, element, Ignore);
|
return expr::trans_into(bcx, element, Ignore);
|
||||||
}
|
}
|
||||||
SaveIn(lldest) => {
|
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 {
|
if count == 0 {
|
||||||
return bcx;
|
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_vec(ref es, _) => es.len(),
|
||||||
ast::expr_repeat(_, count_expr, _) => {
|
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,
|
_ => bcx.tcx().sess.span_bug(content_expr.span,
|
||||||
"Unexpected evec content")
|
"Unexpected evec content")
|
||||||
|
|
|
@ -4230,42 +4230,57 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
|
||||||
return t_norm;
|
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.
|
// 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) {
|
match const_eval::eval_const_expr_partial(tcx, count_expr) {
|
||||||
Ok(ref const_val) => match *const_val {
|
Ok(ref const_val) => match *const_val {
|
||||||
const_eval::const_int(count) => if count < 0 {
|
const_eval::const_int(count) => if count < 0 {
|
||||||
tcx.sess.span_err(count_expr.span,
|
tcx.ty_ctxt().sess.span_err(count_expr.span,
|
||||||
"expected positive integer for \
|
"expected positive integer for \
|
||||||
repeat count but found negative integer");
|
repeat count but found negative integer");
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return count as uint
|
return count as uint
|
||||||
},
|
},
|
||||||
const_eval::const_uint(count) => return count as uint,
|
const_eval::const_uint(count) => return count as uint,
|
||||||
const_eval::const_float(count) => {
|
const_eval::const_float(count) => {
|
||||||
tcx.sess.span_err(count_expr.span,
|
tcx.ty_ctxt().sess.span_err(count_expr.span,
|
||||||
"expected positive integer for \
|
"expected positive integer for \
|
||||||
repeat count but found float");
|
repeat count but found float");
|
||||||
return count as uint;
|
return count as uint;
|
||||||
}
|
}
|
||||||
const_eval::const_str(_) => {
|
const_eval::const_str(_) => {
|
||||||
tcx.sess.span_err(count_expr.span,
|
tcx.ty_ctxt().sess.span_err(count_expr.span,
|
||||||
"expected positive integer for \
|
"expected positive integer for \
|
||||||
repeat count but found string");
|
repeat count but found string");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const_eval::const_bool(_) => {
|
const_eval::const_bool(_) => {
|
||||||
tcx.sess.span_err(count_expr.span,
|
tcx.ty_ctxt().sess.span_err(count_expr.span,
|
||||||
"expected positive integer for \
|
"expected positive integer for \
|
||||||
repeat count but found boolean");
|
repeat count but found boolean");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(*) => {
|
Err(*) => {
|
||||||
tcx.sess.span_err(count_expr.span,
|
tcx.ty_ctxt().sess.span_err(count_expr.span,
|
||||||
"expected constant integer for repeat count \
|
"expected constant integer for repeat count \
|
||||||
but found variable");
|
but found variable");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) => {
|
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) => {
|
Ok(ref r) => {
|
||||||
match *r {
|
match *r {
|
||||||
const_eval::const_int(i) =>
|
const_eval::const_int(i) =>
|
||||||
|
|
|
@ -83,7 +83,7 @@ use middle::pat_util;
|
||||||
use middle::lint::unreachable_code;
|
use middle::lint::unreachable_code;
|
||||||
use middle::ty::{FnSig, VariantInfo_};
|
use middle::ty::{FnSig, VariantInfo_};
|
||||||
use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
|
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::ty;
|
||||||
use middle::typeck::astconv::AstConv;
|
use middle::typeck::astconv::AstConv;
|
||||||
use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
|
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) {
|
pub fn check_item_types(ccx: @mut CrateCtxt, crate: &ast::crate) {
|
||||||
let visit = visit::mk_simple_visitor(@visit::SimpleVisitor {
|
let visit = visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||||
visit_item: |a| check_item(ccx, a),
|
visit_item: |a| check_item(ccx, a),
|
||||||
|
@ -797,7 +807,7 @@ impl FnCtxt {
|
||||||
pat.repr(self.tcx())
|
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) {
|
match self.inh.node_types.find(&ex.id) {
|
||||||
Some(&t) => t,
|
Some(&t) => t,
|
||||||
None => {
|
None => {
|
||||||
|
@ -2250,8 +2260,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::expr_repeat(element, count_expr, mutbl) => {
|
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());
|
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 tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
|
||||||
let mutability = match vst {
|
let mutability = match vst {
|
||||||
ast::expr_vstore_mut_box | ast::expr_vstore_mut_slice => {
|
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);
|
fcx.write_ty(id, typ);
|
||||||
}
|
}
|
||||||
ast::expr_repeat(element, count_expr, mutbl) => {
|
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());
|
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();
|
let t: ty::t = fcx.infcx().next_ty_var();
|
||||||
check_expr_has_type(fcx, element, t);
|
check_expr_has_type(fcx, element, t);
|
||||||
let element_ty = fcx.expr_ty(element);
|
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
|
// that the expression is in an form that eval_const_expr can
|
||||||
// handle, so we may still get an internal compiler error
|
// 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)) => {
|
Ok(const_eval::const_int(val)) => {
|
||||||
*disr_val = val as int;
|
*disr_val = val as int;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
}
|
Loading…
Reference in New Issue