about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-07-16 16:19:37 -0700
committerbors <bors@rust-lang.org>2013-07-16 16:19:37 -0700
commit8a1002fbd93989bbf5c8989ed8002827920b375b (patch)
tree88eacb64219d603f19e34264e486618f07831ab5 /src
parent53e934c2ab773eaf61da331893d176aa3e62230b (diff)
parent877bba91d54457c104ff0bf67fd46a499a451cf6 (diff)
downloadrust-8a1002fbd93989bbf5c8989ed8002827920b375b.tar.gz
rust-8a1002fbd93989bbf5c8989ed8002827920b375b.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/const_eval.rs58
-rw-r--r--src/librustc/middle/kind.rs2
-rw-r--r--src/librustc/middle/trans/tvec.rs4
-rw-r--r--src/librustc/middle/ty.rs47
-rw-r--r--src/librustc/middle/typeck/astconv.rs2
-rw-r--r--src/librustc/middle/typeck/check/mod.rs20
-rw-r--r--src/test/run-pass/enum-vec-initializer.rs24
7 files changed, 127 insertions, 30 deletions
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<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")
           }
       }
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<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,
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<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;
       }
     }
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<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) =>
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 <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];
+}
\ No newline at end of file