diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2012-08-08 14:17:52 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2012-08-08 14:19:21 -0700 |
| commit | f110e8f21c707cb4bbb5e54b45f4458987920322 (patch) | |
| tree | d4999199d287f0e3e53569ba8bdc82a593654a6c | |
| parent | 166cb1b28bc23303d15e8c1c4a71d0cdff0556a2 (diff) | |
| download | rust-f110e8f21c707cb4bbb5e54b45f4458987920322.tar.gz rust-f110e8f21c707cb4bbb5e54b45f4458987920322.zip | |
rustc: Do some plumbing work on nested enums
| -rw-r--r-- | src/libsyntax/ast.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/ext/auto_serialize.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 95 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 31 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 30 | ||||
| -rw-r--r-- | src/rustc/metadata/encoder.rs | 3 | ||||
| -rw-r--r-- | src/rustc/middle/resolve3.rs | 36 | ||||
| -rw-r--r-- | src/rustc/middle/trans/base.rs | 57 | ||||
| -rw-r--r-- | src/rustc/middle/ty.rs | 6 | ||||
| -rw-r--r-- | src/rustc/middle/typeck/check.rs | 107 | ||||
| -rw-r--r-- | src/rustc/middle/typeck/collect.rs | 30 |
12 files changed, 250 insertions, 157 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f1c5f63bd1d..d2a6aa1f7b0 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -636,7 +636,8 @@ type variant_arg = {ty: @ty, id: node_id}; #[auto_serialize] enum variant_kind { tuple_variant_kind(~[variant_arg]), - struct_variant_kind(@struct_def) + struct_variant_kind(@struct_def), + enum_variant_kind(~[variant]) } #[auto_serialize] diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs index 20cc04b2c79..d0a55b6d95c 100644 --- a/src/libsyntax/ext/auto_serialize.rs +++ b/src/libsyntax/ext/auto_serialize.rs @@ -913,7 +913,9 @@ fn deser_enum(cx: ext_ctxt, tps: deser_tps_map, e_name: ast::ident, }; } ast::struct_variant_kind(*) => - fail ~"struct variants unimplemented" + fail ~"struct variants unimplemented", + ast::enum_variant_kind(*) => + fail ~"enum variants unimplemented" } {pats: ~[@{id: cx.next_id(), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 22713618222..d84c981504f 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -564,6 +564,11 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ { dtor: dtor }) } + + enum_variant_kind(variants) => { + let variants = vec::map(variants, |x| fld.fold_variant(x)); + kind = enum_variant_kind(variants); + } } let fold_attribute = |x| fold_attribute_(x, fld); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6f8128b9b76..1cc3f197721 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -17,28 +17,27 @@ import dvec::{dvec, extensions}; import vec::{push}; import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, bind_by_ref, bind_by_implicit_ref, bind_by_value, - bitand, bitor, bitxor, blk, - blk_check_mode, bound_const, bound_copy, bound_send, bound_trait, - bound_owned, box, by_copy, by_move, by_mutbl_ref, by_ref, by_val, - capture_clause, capture_item, cdir_dir_mod, cdir_src_mod, - cdir_view_item, class_immutable, class_member, class_method, - class_mutable, crate, crate_cfg, crate_directive, decl, - decl_item, decl_local, default_blk, deref, div, expl, expr, - expr_, expr_addr_of, expr_match, expr_again, expr_assert, - expr_assign, expr_assign_op, expr_binary, expr_block, expr_break, - expr_call, expr_cast, expr_copy, expr_do_body, - expr_fail, expr_field, expr_fn, expr_fn_block, expr_if, - expr_index, expr_lit, expr_log, expr_loop, - expr_loop_body, expr_mac, expr_move, expr_path, expr_rec, - expr_repeat, expr_ret, expr_swap, expr_struct, expr_tup, - expr_unary, expr_unary_move, expr_vec, expr_vstore, expr_while, - extern_fn, field, fn_decl, foreign_item, foreign_item_fn, - foreign_mod, ident, impure_fn, infer, inherited, init_assign, - init_move, initializer, instance_var, item, item_, item_class, - item_const, item_enum, item_fn, item_foreign_mod, item_impl, - item_mac, item_mod, item_trait, item_ty, lit, lit_, lit_bool, - lit_float, lit_int, lit_int_unsuffixed, lit_nil, lit_str, - lit_uint, local, m_const, m_imm, m_mutbl, mac_, mac_aq, + bitand, bitor, bitxor, blk, blk_check_mode, bound_const, + bound_copy, bound_send, bound_trait, bound_owned, box, by_copy, + by_move, by_mutbl_ref, by_ref, by_val, capture_clause, + capture_item, cdir_dir_mod, cdir_src_mod, cdir_view_item, + class_immutable, class_member, class_method, class_mutable, + crate, crate_cfg, crate_directive, decl, decl_item, decl_local, + default_blk, deref, div, enum_variant_kind, expl, expr, expr_, + expr_addr_of, expr_match, expr_again, expr_assert, expr_assign, + expr_assign_op, expr_binary, expr_block, expr_break, expr_call, + expr_cast, expr_copy, expr_do_body, expr_fail, expr_field, + expr_fn, expr_fn_block, expr_if, expr_index, expr_lit, expr_log, + expr_loop, expr_loop_body, expr_mac, expr_move, expr_path, + expr_rec, expr_repeat, expr_ret, expr_swap, expr_struct, + expr_tup, expr_unary, expr_unary_move, expr_vec, expr_vstore, + expr_while, extern_fn, field, fn_decl, foreign_item, + foreign_item_fn, foreign_mod, ident, impure_fn, infer, inherited, + init_assign, init_move, initializer, instance_var, item, item_, + item_class, item_const, item_enum, item_fn, item_foreign_mod, + item_impl, item_mac, item_mod, item_trait, item_ty, lit, lit_, + lit_bool, lit_float, lit_int, lit_int_unsuffixed, lit_nil, + lit_str, lit_uint, local, m_const, m_imm, m_mutbl, mac_, mac_aq, mac_ellipsis, mac_invoc, mac_invoc_tt, mac_var, matcher, match_nonterminal, match_seq, match_tok, method, mode, mt, mul, mutability, neg, noreturn, not, pat, pat_box, pat_enum, @@ -2842,30 +2841,8 @@ class parser { } } - fn parse_item_enum() -> item_info { - let id = self.parse_ident(); - self.parse_region_param(); - let ty_params = self.parse_ty_params(); + fn parse_enum_body(ty_params: ~[ast::ty_param]) -> ~[ast::variant] { let mut variants: ~[variant] = ~[]; - // Newtype syntax - if self.token == token::EQ { - self.check_restricted_keywords_(*id); - self.bump(); - let ty = self.parse_ty(false); - self.expect(token::SEMI); - let variant = - spanned(ty.span.lo, ty.span.hi, - {name: id, - attrs: ~[], - kind: tuple_variant_kind - (~[{ty: ty, id: self.get_id()}]), - id: self.get_id(), - disr_expr: none, - vis: public}); - return (id, item_enum(~[variant], ty_params), none); - } - self.expect(token::LBRACE); - let mut all_nullary = true, have_disr = false; while self.token != token::RBRACE { @@ -2954,6 +2931,34 @@ class parser { self.fatal(~"discriminator values can only be used with a c-like \ enum"); } + + return variants; + } + + fn parse_item_enum() -> item_info { + let id = self.parse_ident(); + self.parse_region_param(); + let ty_params = self.parse_ty_params(); + // Newtype syntax + if self.token == token::EQ { + self.check_restricted_keywords_(*id); + self.bump(); + let ty = self.parse_ty(false); + self.expect(token::SEMI); + let variant = + spanned(ty.span.lo, ty.span.hi, + {name: id, + attrs: ~[], + kind: tuple_variant_kind + (~[{ty: ty, id: self.get_id()}]), + id: self.get_id(), + disr_expr: none, + vis: public}); + return (id, item_enum(~[variant], ty_params), none); + } + self.expect(token::LBRACE); + + let variants = self.parse_enum_body(ty_params); (id, item_enum(variants, ty_params), none) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 4b23fbf74a9..56b3197c336 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -516,18 +516,7 @@ fn print_item(s: ps, &&item: @ast::item) { word(s.s, ~";"); end(s); } else { - bopen(s); - for variants.each |v| { - space_if_not_bol(s); - maybe_print_comment(s, v.span.lo); - print_outer_attributes(s, v.node.attrs); - ibox(s, indent_unit); - print_variant(s, v); - word(s.s, ~","); - end(s); - maybe_print_trailing_comment(s, v.span, none::<uint>); - } - bclose(s, item.span); + print_variants(s, variants, item.span); } } ast::item_class(struct_def, tps) => { @@ -582,6 +571,21 @@ fn print_item(s: ps, &&item: @ast::item) { s.ann.post(ann_node); } +fn print_variants(s: ps, variants: ~[ast::variant], span: ast::span) { + bopen(s); + for variants.each |v| { + space_if_not_bol(s); + maybe_print_comment(s, v.span.lo); + print_outer_attributes(s, v.node.attrs); + ibox(s, indent_unit); + print_variant(s, v); + word(s.s, ~","); + end(s); + maybe_print_trailing_comment(s, v.span, none::<uint>); + } + bclose(s, span); +} + fn print_struct(s: ps, struct_def: @ast::struct_def, tps: ~[ast::ty_param], ident: ast::ident, span: ast::span) { word_nbsp(s, *ident); @@ -710,6 +714,9 @@ fn print_variant(s: ps, v: ast::variant) { head(s, ~""); print_struct(s, struct_def, ~[], v.node.name, v.span); } + ast::enum_variant_kind(variants) => { + print_variants(s, variants, v.span); + } } match v.node.disr_expr { some(d) => { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index a47685dd42c..f526f8c73e1 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -138,17 +138,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) { } item_enum(variants, tps) => { v.visit_ty_params(tps, e, v); - for variants.each |vr| { - match vr.node.kind { - tuple_variant_kind(variant_args) => { - for variant_args.each |va| { v.visit_ty(va.ty, e, v); } - } - struct_variant_kind(struct_def) => { - v.visit_struct_def(struct_def, vr.node.name, tps, - vr.node.id, e, v); - } - } - } + visit_variants(variants, tps, e, v); } item_impl(tps, traits, ty, methods) => { v.visit_ty_params(tps, e, v); @@ -175,6 +165,24 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) { } } +fn visit_variants<E>(variants: ~[ast::variant], tps: ~[ast::ty_param], e: E, + v: vt<E>) { + for variants.each |vr| { + match vr.node.kind { + tuple_variant_kind(variant_args) => { + for variant_args.each |va| { v.visit_ty(va.ty, e, v); } + } + struct_variant_kind(struct_def) => { + v.visit_struct_def(struct_def, vr.node.name, tps, + vr.node.id, e, v); + } + enum_variant_kind(variants) => { + visit_variants(variants, tps, e, v); + } + } + } +} + fn visit_class_item<E>(cm: @class_member, e:E, v:vt<E>) { match cm.node { instance_var(_, t, _, _, _) => v.visit_ty(t, e, v), 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); + } + } } } |
