about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-08-08 14:17:52 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-08-08 14:19:21 -0700
commitf110e8f21c707cb4bbb5e54b45f4458987920322 (patch)
treed4999199d287f0e3e53569ba8bdc82a593654a6c /src/rustc
parent166cb1b28bc23303d15e8c1c4a71d0cdff0556a2 (diff)
downloadrust-f110e8f21c707cb4bbb5e54b45f4458987920322.tar.gz
rust-f110e8f21c707cb4bbb5e54b45f4458987920322.zip
rustc: Do some plumbing work on nested enums
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/metadata/encoder.rs3
-rw-r--r--src/rustc/middle/resolve3.rs36
-rw-r--r--src/rustc/middle/trans/base.rs57
-rw-r--r--src/rustc/middle/ty.rs6
-rw-r--r--src/rustc/middle/typeck/check.rs107
-rw-r--r--src/rustc/middle/typeck/collect.rs30
6 files changed, 152 insertions, 87 deletions
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 07d12a12866..de0dca66f9c 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -398,7 +398,8 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer,
                     if args.len() > 0 && ty_params.len() == 0 => {
                 encode_symbol(ecx, ebml_w, variant.node.id);
             }
-            ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) => {}
+            ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) |
+            ast::enum_variant_kind(_) => {}
         }
         encode_discriminant(ecx, ebml_w, variant.node.id);
         if vi[i].disr_val != disr_val {
diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs
index 3bd47b8d5f2..d17542b797a 100644
--- a/src/rustc/middle/resolve3.rs
+++ b/src/rustc/middle/resolve3.rs
@@ -21,19 +21,19 @@ import syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op};
 import syntax::ast::{expr_binary, expr_cast, expr_field, expr_fn};
 import syntax::ast::{expr_fn_block, expr_index, expr_path};
 import syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
-import syntax::ast::{def_upvar, def_use, def_variant, div, eq, expr};
-import syntax::ast::{expr_assign_op, expr_binary, expr_cast, expr_field};
-import syntax::ast::{expr_fn, expr_fn_block, expr_index, expr_path};
-import syntax::ast::{expr_struct, expr_unary, fn_decl, foreign_item};
-import syntax::ast::{foreign_item_fn, ge, gt, ident, trait_ref, impure_fn};
-import syntax::ast::{instance_var, item, item_class, item_const, item_enum};
-import syntax::ast::{item_fn, item_mac, item_foreign_mod, item_impl};
-import syntax::ast::{item_mod, item_trait, item_ty, le, local, local_crate};
-import syntax::ast::{lt, method, mul, ne, neg, node_id, pat, pat_enum};
-import syntax::ast::{pat_ident, path, prim_ty, pat_box, pat_uniq, pat_lit};
-import syntax::ast::{pat_range, pat_rec, pat_struct, pat_tup, pat_wild};
-import syntax::ast::{provided, required, rem, self_ty_, shl, stmt_decl};
-import syntax::ast::{struct_variant_kind, sty_static, subtract};
+import syntax::ast::{def_upvar, def_use, def_variant, div, eq};
+import syntax::ast::{enum_variant_kind, expr, expr_assign_op, expr_binary};
+import syntax::ast::{expr_cast, expr_field, expr_fn, expr_fn_block};
+import syntax::ast::{expr_index, expr_path, expr_struct, expr_unary, fn_decl};
+import syntax::ast::{foreign_item, foreign_item_fn, ge, gt, ident, trait_ref};
+import syntax::ast::{impure_fn, instance_var, item, item_class, item_const};
+import syntax::ast::{item_enum, item_fn, item_mac, item_foreign_mod};
+import syntax::ast::{item_impl, item_mod, item_trait, item_ty, le, local};
+import syntax::ast::{local_crate, lt, method, mul, ne, neg, node_id, pat};
+import syntax::ast::{pat_enum, pat_ident, path, prim_ty, pat_box, pat_uniq};
+import syntax::ast::{pat_lit, pat_range, pat_rec, pat_struct, pat_tup};
+import syntax::ast::{pat_wild, provided, required, rem, self_ty_, shl};
+import syntax::ast::{stmt_decl, struct_variant_kind, sty_static, subtract};
 import syntax::ast::{tuple_variant_kind, ty};
 import syntax::ast::{ty_bool, ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i};
 import syntax::ast::{ty_i16, ty_i32, ty_i64, ty_i8, ty_int, ty_param};
@@ -1128,7 +1128,7 @@ class Resolver {
     fn build_reduced_graph_for_variant(variant: variant,
                                        item_id: def_id,
                                        parent: ReducedGraphParent,
-                                       &&_visitor: vt<ReducedGraphParent>) {
+                                       &&visitor: vt<ReducedGraphParent>) {
 
         let atom = (*self.atom_table).intern(variant.node.name);
         let (child, _) = self.add_child(atom, parent, ~[ValueNS],
@@ -1146,6 +1146,14 @@ class Resolver {
                                      variant.span);
                 self.structs.insert(local_def(variant.node.id), false);
             }
+            enum_variant_kind(variants) => {
+                (*child).define_type(def_ty(local_def(variant.node.id)),
+                                     variant.span);
+                for variants.each |variant| {
+                    self.build_reduced_graph_for_variant(variant, item_id,
+                                                         parent, visitor);
+                }
+            }
         }
     }
 
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index ce6669f9799..15f7de84c5f 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -2235,7 +2235,9 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id,
                                    psubsts, d);
             }
             ast::struct_variant_kind(_) =>
-                ccx.tcx.sess.bug(~"can't monomorphize struct variants")
+                ccx.tcx.sess.bug(~"can't monomorphize struct variants"),
+            ast::enum_variant_kind(_) =>
+                ccx.tcx.sess.bug(~"can't monomorphize enum variants")
         }
         d
       }
@@ -4893,6 +4895,34 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path,
   lldecl
 }
 
+fn trans_variants(ccx: @crate_ctxt, variants: ~[ast::variant],
+                  id: ast::node_id, tps: ~[ast::ty_param], degen: bool,
+                  path: @ast_map::path, vi: @~[ty::variant_info],
+                  i: &mut uint) {
+    for vec::each(variants) |variant| {
+        let disr_val = vi[*i].disr_val;
+        *i += 1;
+
+        match variant.node.kind {
+            ast::tuple_variant_kind(args) if args.len() > 0 => {
+                let llfn = get_item_val(ccx, variant.node.id);
+                trans_enum_variant(ccx, id, variant, args, disr_val,
+                                   degen, none, llfn);
+            }
+            ast::tuple_variant_kind(_) => {
+                // Nothing to do.
+            }
+            ast::struct_variant_kind(struct_def) => {
+                trans_struct_def(ccx, struct_def, tps, path,
+                                 variant.node.name, variant.node.id);
+            }
+            ast::enum_variant_kind(variants) => {
+                trans_variants(ccx, variants, id, tps, degen, path, vi, i);
+            }
+        }
+    }
+}
+
 fn trans_item(ccx: @crate_ctxt, item: ast::item) {
     let _icx = ccx.insn_ctxt(~"trans_item");
     let path = match check ccx.tcx.items.get(item.id) {
@@ -4934,24 +4964,8 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
             let degen = variants.len() == 1u;
             let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
             let mut i = 0;
-            for vec::each(variants) |variant| {
-                match variant.node.kind {
-                    ast::tuple_variant_kind(args) if args.len() > 0 => {
-                        let llfn = get_item_val(ccx, variant.node.id);
-                        trans_enum_variant(ccx, item.id, variant, args,
-                                           vi[i].disr_val, degen,
-                                           none, llfn);
-                    }
-                    ast::tuple_variant_kind(_) => {
-                        // Nothing to do.
-                    }
-                    ast::struct_variant_kind(struct_def) => {
-                        trans_struct_def(ccx, struct_def, tps, path,
-                                         variant.node.name, variant.node.id);
-                    }
-                }
-                i += 1;
-            }
+            trans_variants(ccx, variants, item.id, tps, degen, path, vi,
+                           &mut i);
         }
       }
       ast::item_const(_, expr) => consts::trans_const(ccx, expr, item.id),
@@ -5263,7 +5277,10 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
                     };
                 }
                 ast::struct_variant_kind(_) => {
-                    fail ~"struct unexpected in get_item_val"
+                    fail ~"struct variant kind unexpected in get_item_val"
+                }
+                ast::enum_variant_kind(_) => {
+                    fail ~"enum variant kind unexpected in get_item_val"
                 }
             }
             set_inline_hint(llfn);
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index ad7824fabe5..ff807cbcab2 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -2868,8 +2868,12 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[variant_info] {
                           disr_val: disr_val
                          }
                     }
-                    ast::struct_variant_kind(_) =>
+                    ast::struct_variant_kind(_) => {
                         fail ~"struct variant kinds unimpl in enum_variants"
+                    }
+                    ast::enum_variant_kind(_) => {
+                        fail ~"enum variant kinds unimpl in enum_variants"
+                    }
                 }
             })
           }
diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs
index ec7e642c09d..16d93137ac7 100644
--- a/src/rustc/middle/typeck/check.rs
+++ b/src/rustc/middle/typeck/check.rs
@@ -2043,53 +2043,76 @@ fn check_enum_variants(ccx: @crate_ctxt,
                        sp: span,
                        vs: ~[ast::variant],
                        id: ast::node_id) {
-    let rty = ty::node_id_to_type(ccx.tcx, id);
-    let mut disr_vals: ~[int] = ~[];
-    let mut disr_val = 0;
-    let mut variants = ~[];
-    for vs.each |v| {
-        match v.node.disr_expr {
-          some(e) => {
-            let fcx = blank_fn_ctxt(ccx, rty, e.id);
-            check_expr(fcx, e, none);
-            let cty = fcx.expr_ty(e);
-            let declty = ty::mk_int(ccx.tcx);
-            demand::suptype(fcx, e.span, declty, cty);
-            // FIXME: issue #1417
-            // Also, check_expr (from check_const pass) doesn't guarantee that
-            // the expression in an form that eval_const_expr can handle, so
-            // we may still get an internal compiler error
-            match const_eval::eval_const_expr(ccx.tcx, e) {
-              const_eval::const_int(val) => {
-                disr_val = val as int;
-              }
-              _ => {
-                ccx.tcx.sess.span_err(e.span,
-                                      ~"expected signed integer constant");
+    fn do_check(ccx: @crate_ctxt, sp: span, vs: ~[ast::variant],
+                id: ast::node_id, disr_vals: &mut ~[int], disr_val: &mut int,
+                variants: &mut ~[ty::variant_info]) {
+        let rty = ty::node_id_to_type(ccx.tcx, id);
+        for vs.each |v| {
+            match v.node.disr_expr {
+              some(e) => {
+                let fcx = blank_fn_ctxt(ccx, rty, e.id);
+                check_expr(fcx, e, none);
+                let cty = fcx.expr_ty(e);
+                let declty = ty::mk_int(ccx.tcx);
+                demand::suptype(fcx, e.span, declty, cty);
+                // FIXME: issue #1417
+                // Also, check_expr (from check_const pass) doesn't guarantee
+                // 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(ccx.tcx, e) {
+                  const_eval::const_int(val) => {
+                    *disr_val = val as int;
+                  }
+                  _ => {
+                    ccx.tcx.sess.span_err(e.span, ~"expected signed integer \
+                                                    constant");
+                  }
+                }
               }
+              _ => ()
+            }
+            if vec::contains(*disr_vals, *disr_val) {
+                ccx.tcx.sess.span_err(v.span,
+                                      ~"discriminator value already exists");
+            }
+            vec::push(*disr_vals, *disr_val);
+            let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
+            let arg_tys;
+
+            let this_disr_val = *disr_val;
+            *disr_val += 1;
+
+            match v.node.kind {
+                ast::tuple_variant_kind(args) if args.len() > 0u => {
+                    arg_tys = some(ty::ty_fn_args(ctor_ty).map(|a| a.ty));
+                }
+                ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) => {
+                    arg_tys = some(~[]);
+                }
+                ast::enum_variant_kind(subvariants) => {
+                    arg_tys = none;
+                    do_check(ccx, sp, vs, id, disr_vals, disr_val, variants);
+                }
+            }
+
+            match arg_tys {
+                none => {}
+                some(arg_tys) => {
+                    vec::push(*variants, @{args: arg_tys, ctor_ty: ctor_ty,
+                          name: v.node.name, id: local_def(v.node.id),
+                          disr_val: this_disr_val});
+                }
             }
-          }
-          _ => ()
-        }
-        if vec::contains(disr_vals, disr_val) {
-            ccx.tcx.sess.span_err(v.span,
-                                  ~"discriminator value already exists");
         }
-        vec::push(disr_vals, disr_val);
-        let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
-        let arg_tys;
-        match v.node.kind {
-            ast::tuple_variant_kind(args) if args.len() > 0u =>
-                arg_tys = ty::ty_fn_args(ctor_ty).map(|a| a.ty),
-            ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) =>
-                arg_tys = ~[]
-        };
-        vec::push(variants, @{args: arg_tys, ctor_ty: ctor_ty,
-              name: v.node.name, id: local_def(v.node.id),
-              disr_val: disr_val});
-        disr_val += 1;
     }
 
+    let rty = ty::node_id_to_type(ccx.tcx, id);
+    let mut disr_vals: ~[int] = ~[];
+    let mut disr_val = 0;
+    let mut variants = ~[];
+
+    do_check(ccx, sp, vs, id, &mut disr_vals, &mut disr_val, &mut variants);
+
     // cache so that ty::enum_variants won't repeat this work
     ccx.tcx.enum_var_cache.insert(local_def(id), @variants);
 
diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs
index 64021f216c3..08eaad73e65 100644
--- a/src/rustc/middle/typeck/collect.rs
+++ b/src/rustc/middle/typeck/collect.rs
@@ -124,21 +124,33 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
                     let arg_ty = ccx.to_ty(rs, va.ty);
                     {mode: ast::expl(ast::by_copy), ty: arg_ty}
                 });
-                result_ty = ty::mk_fn(tcx, {purity: ast::pure_fn,
+                result_ty = some(ty::mk_fn(tcx,
+                                           {purity: ast::pure_fn,
                                             proto: ast::proto_box,
                                             bounds: @~[],
                                             inputs: args,
                                             output: enum_ty,
-                                            ret_style: ast::return_val});
+                                            ret_style: ast::return_val}));
+            }
+            ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) => {
+                result_ty = some(enum_ty);
+            }
+            ast::enum_variant_kind(variants) => {
+                get_enum_variant_types(ccx, enum_ty, variants, ty_params, rp);
+                result_ty = none;
             }
-            ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) =>
-                result_ty = enum_ty
         };
-        let tpt = {bounds: ty_param_bounds(ccx, ty_params),
-                   rp: rp,
-                   ty: result_ty};
-        tcx.tcache.insert(local_def(variant.node.id), tpt);
-        write_ty_to_tcx(tcx, variant.node.id, result_ty);
+
+        match result_ty {
+            none => {}
+            some(result_ty) => {
+                let tpt = {bounds: ty_param_bounds(ccx, ty_params),
+                           rp: rp,
+                           ty: result_ty};
+                tcx.tcache.insert(local_def(variant.node.id), tpt);
+                write_ty_to_tcx(tcx, variant.node.id, result_ty);
+            }
+        }
     }
 }