diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 577ef1464cf6..87fe7fe67a97 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -632,7 +632,13 @@ type foreign_mod = type variant_arg = {ty: @ty, id: node_id}; #[auto_serialize] -type variant_ = {name: ident, attrs: ~[attribute], args: ~[variant_arg], +enum variant_kind { + tuple_variant_kind(~[variant_arg]), + struct_variant_kind +} + +#[auto_serialize] +type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind, id: node_id, disr_expr: option<@expr>, vis: visibility}; #[auto_serialize] diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index deb8bb5963df..7d7867d05160 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -187,12 +187,13 @@ fn is_exported(i: ident, m: _mod) -> bool { for m.items.each |it| { if it.ident == i { local = true; } match it.node { - item_enum(variants, _) => for variants.each |v| { - if v.node.name == i { - local = true; - parent_enum = some(/* FIXME (#2543) */ copy it.ident); + item_enum(variants, _) => + for variants.each |v| { + if v.node.name == i { + local = true; + parent_enum = some(/* FIXME (#2543) */ copy it.ident); + } } - }, _ => () } if local { break; } diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs index 053c972d1ea5..4ce017eeae9a 100644 --- a/src/libsyntax/ext/auto_serialize.rs +++ b/src/libsyntax/ext/auto_serialize.rs @@ -830,43 +830,51 @@ fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: ast::ident, let variant = variants[vidx]; let v_span = variant.span; let v_name = variant.node.name; - let variant_tys = vec::map(variant.node.args, |a| a.ty); - ser_variant( - cx, tps, variant_tys, v_span, cx.clone(s), + match variant.node.kind { + ast::tuple_variant_kind(args) => { + let variant_tys = vec::map(args, |a| a.ty); - // Generate pattern var(v1, v2, v3) - |pats| { - if vec::is_empty(pats) { - ast::pat_ident(ast::bind_by_implicit_ref, - cx.path(v_span, ~[v_name]), - none) - } else { - ast::pat_enum(cx.path(v_span, ~[v_name]), some(pats)) - } - }, + ser_variant( + cx, tps, variant_tys, v_span, cx.clone(s), - // Generate body s.emit_enum_variant("foo", 0u, - // 3u, {|| blk }) - |-s, blk| { - let v_name = cx.lit_str(v_span, v_name); - let v_id = cx.lit_uint(v_span, vidx); - let sz = cx.lit_uint(v_span, vec::len(variant_tys)); - let body = cx.lambda(blk); - #ast[expr]{ - $(s).emit_enum_variant($(v_name), $(v_id), - $(sz), $(body)) - } - }, + // Generate pattern var(v1, v2, v3) + |pats| { + if vec::is_empty(pats) { + ast::pat_ident(ast::bind_by_implicit_ref, + cx.path(v_span, ~[v_name]), + none) + } else { + ast::pat_enum(cx.path(v_span, ~[v_name]), + some(pats)) + } + }, - // Generate s.emit_enum_variant_arg(i, {|| blk }) - |-s, i, blk| { - let idx = cx.lit_uint(v_span, i); - let body = cx.lambda(blk); - #ast[expr]{ - $(s).emit_enum_variant_arg($(idx), $(body)) - } - }) + // Generate body s.emit_enum_variant("foo", 0u, + // 3u, {|| blk }) + |-s, blk| { + let v_name = cx.lit_str(v_span, v_name); + let v_id = cx.lit_uint(v_span, vidx); + let sz = cx.lit_uint(v_span, vec::len(variant_tys)); + let body = cx.lambda(blk); + #ast[expr]{ + $(s).emit_enum_variant($(v_name), $(v_id), + $(sz), $(body)) + } + }, + + // Generate s.emit_enum_variant_arg(i, {|| blk }) + |-s, i, blk| { + let idx = cx.lit_uint(v_span, i); + let body = cx.lambda(blk); + #ast[expr]{ + $(s).emit_enum_variant_arg($(idx), $(body)) + } + }) + } + _ => + fail ~"struct variants unimplemented for auto serialize" + } }; let lam = cx.lambda(cx.blk(e_span, ~[cx.alt_stmt(arms, e_span, v)])); let e_name = cx.lit_str(e_span, e_name); @@ -881,24 +889,32 @@ fn deser_enum(cx: ext_ctxt, tps: deser_tps_map, e_name: ast::ident, let variant = variants[vidx]; let v_span = variant.span; let v_name = variant.node.name; - let tys = vec::map(variant.node.args, |a| a.ty); - let arg_exprs = do vec::from_fn(vec::len(tys)) |i| { - let idx = cx.lit_uint(v_span, i); - let body = deser_lambda(cx, tps, tys[i], cx.clone(d)); - #ast{ $(d).read_enum_variant_arg($(idx), $(body)) } - }; + let body; + match variant.node.kind { + ast::tuple_variant_kind(args) => { + let tys = vec::map(args, |a| a.ty); - let body = { - if vec::is_empty(tys) { - // for a nullary variant v, do "v" - cx.var_ref(v_span, v_name) - } else { - // for an n-ary variant v, do "v(a_1, ..., a_n)" - cx.expr(v_span, ast::expr_call( - cx.var_ref(v_span, v_name), arg_exprs, false)) + let arg_exprs = do vec::from_fn(vec::len(tys)) |i| { + let idx = cx.lit_uint(v_span, i); + let body = deser_lambda(cx, tps, tys[i], cx.clone(d)); + #ast{ $(d).read_enum_variant_arg($(idx), $(body)) } + }; + + body = { + if vec::is_empty(tys) { + // for a nullary variant v, do "v" + cx.var_ref(v_span, v_name) + } else { + // for an n-ary variant v, do "v(a_1, ..., a_n)" + cx.expr(v_span, ast::expr_call( + cx.var_ref(v_span, v_name), arg_exprs, false)) + } + }; } - }; + ast::struct_variant_kind => + fail ~"struct variants unimplemented" + } {pats: ~[@{id: cx.next_id(), node: ast::pat_lit(cx.lit_uint(v_span, vidx)), diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index b8c37f844525..06a22b63fe0b 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -254,7 +254,7 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt { {node: {name: name, attrs: ~[], - args: args, + kind: ast::tuple_variant_kind(args), id: self.next_id(), disr_expr: none, vis: ast::public}, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index ab39bf53f6a5..0ceee7f7d97a 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -541,7 +541,15 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ { return {ty: fld.fold_ty(va.ty), id: fld.new_id(va.id)}; } let fold_variant_arg = |x| fold_variant_arg_(x, fld); - let args = vec::map(v.args, fold_variant_arg); + + let kind; + match v.kind { + tuple_variant_kind(variant_args) => + kind = tuple_variant_kind(vec::map(variant_args, + fold_variant_arg)), + struct_variant_kind => + kind = struct_variant_kind + } let fold_attribute = |x| fold_attribute_(x, fld); let attrs = vec::map(v.attrs, fold_attribute); @@ -552,7 +560,8 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ { }; return {name: /* FIXME (#2543) */ copy v.name, attrs: attrs, - args: args, id: fld.new_id(v.id), + kind: kind, + id: fld.new_id(v.id), disr_expr: de, vis: v.vis}; } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 993419bd9c4e..5feb753657de 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -49,14 +49,14 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr, stmt_semi, subtract, sty_box, sty_by_ref, sty_region, sty_uniq, sty_value, token_tree, trait_method, trait_ref, tt_delim, tt_seq, - tt_tok, tt_nonterminal, ty, ty_, ty_bot, ty_box, ty_field, ty_fn, - ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound, - ty_path, ty_ptr, ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, - ty_vec, ty_fixed_length, unchecked_blk, uniq, unsafe_blk, - unsafe_fn, variant, view_item, view_item_, view_item_export, - view_item_import, view_item_use, view_path, view_path_glob, - view_path_list, view_path_simple, visibility, vstore, vstore_box, - vstore_fixed, vstore_slice, vstore_uniq}; + tt_tok, tt_nonterminal, tuple_variant_kind, ty, ty_, ty_bot, + ty_box, ty_field, ty_fn, ty_infer, ty_mac, ty_method, ty_nil, + ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr, + ty_tup, ty_u32, ty_uniq, ty_vec, ty_fixed_length, unchecked_blk, + uniq, unsafe_blk, unsafe_fn, variant, view_item, view_item_, + view_item_export, view_item_import, view_item_use, view_path, + view_path_glob, view_path_list, view_path_simple, visibility, + vstore, vstore_box, vstore_fixed, vstore_slice, vstore_uniq}; export file_type; export parser; @@ -2830,7 +2830,8 @@ class parser { spanned(ty.span.lo, ty.span.hi, {name: id, attrs: ~[], - args: ~[{ty: ty, id: self.get_id()}], + kind: tuple_variant_kind + (~[{ty: ty, id: self.get_id()}]), id: self.get_id(), disr_expr: none, vis: public}); @@ -2861,7 +2862,7 @@ class parser { } let vr = {name: ident, attrs: variant_attrs, - args: args, id: self.get_id(), + kind: tuple_variant_kind(args), id: self.get_id(), disr_expr: disr_expr, vis: vis}; vec::push(variants, spanned(vlo, self.last_span.hi, vr)); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 41b61f57f928..d3eef85f0625 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -488,21 +488,31 @@ fn print_item(s: ps, &&item: @ast::item) { end(s); // end the outer ibox } ast::item_enum(variants, params) => { - let newtype = + let mut newtype = vec::len(variants) == 1u && - str::eq(item.ident, variants[0].node.name) && - vec::len(variants[0].node.args) == 1u; + str::eq(item.ident, variants[0].node.name); + if newtype { + match variants[0].node.kind { + ast::tuple_variant_kind(args) if args.len() == 1 => {} + _ => newtype = false + } + } if newtype { ibox(s, indent_unit); word_space(s, ~"enum"); - } else { head(s, ~"enum"); } + } else { + head(s, ~"enum"); + } word(s.s, *item.ident); print_type_params(s, params); space(s.s); if newtype { word_space(s, ~"="); - print_type(s, variants[0].node.args[0].ty); + match variants[0].node.kind { + ast::tuple_variant_kind(args) => print_type(s, args[0].ty), + _ => fail ~"newtype syntax with struct?" + } word(s.s, ~";"); end(s); } else { @@ -680,13 +690,18 @@ fn print_tt(s: ps, tt: ast::token_tree) { fn print_variant(s: ps, v: ast::variant) { word(s.s, *v.node.name); - if vec::len(v.node.args) > 0u { - popen(s); - fn print_variant_arg(s: ps, arg: ast::variant_arg) { - print_type(s, arg.ty); + match v.node.kind { + ast::tuple_variant_kind(args) => { + if vec::len(args) > 0u { + popen(s); + fn print_variant_arg(s: ps, arg: ast::variant_arg) { + print_type(s, arg.ty); + } + commasep(s, consistent, args, print_variant_arg); + pclose(s); + } } - commasep(s, consistent, v.node.args, print_variant_arg); - pclose(s); + ast::struct_variant_kind => {} } match v.node.disr_expr { some(d) => { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 830114b47ad7..3bf820dd5cf6 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -135,7 +135,11 @@ fn visit_item(i: @item, e: E, v: vt) { item_enum(variants, tps) => { v.visit_ty_params(tps, e, v); for variants.each |vr| { - for vr.node.args.each |va| { v.visit_ty(va.ty, e, v); } + match vr.node.kind { + tuple_variant_kind(variant_args) => + for variant_args.each |va| { v.visit_ty(va.ty, e, v); }, + struct_variant_kind => {} + } } } item_impl(tps, traits, ty, methods) => { diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 49299ac850c5..267bb55e09eb 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -362,8 +362,12 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer, encode_parent_item(ebml_w, local_def(id)); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, variant.node.id)); - if vec::len(variant.node.args) > 0u && ty_params.len() == 0u { - encode_symbol(ecx, ebml_w, variant.node.id); + match variant.node.kind { + ast::tuple_variant_kind(args) + if args.len() > 0 && ty_params.len() == 0 => { + encode_symbol(ecx, ebml_w, variant.node.id); + } + ast::tuple_variant_kind(_) | ast::struct_variant_kind => {} } encode_discriminant(ecx, ebml_w, variant.node.id); if vi[i].disr_val != disr_val { diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 81ea48f95014..eb23008f1856 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -2173,8 +2173,14 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, tv.id.node == fn_id.node})); let d = mk_lldecl(); set_inline_hint(d); - trans_enum_variant(ccx, enum_item.id, v, this_tv.disr_val, - (*tvs).len() == 1u, psubsts, d); + match v.node.kind { + ast::tuple_variant_kind(args) => { + trans_enum_variant(ccx, enum_item.id, v, args, + this_tv.disr_val, (*tvs).len() == 1u, + psubsts, d); + } + ast::struct_variant_kind => {} + } d } ast_map::node_method(mth, impl_def_id, _) => { @@ -4671,13 +4677,16 @@ fn trans_fn(ccx: @crate_ctxt, } } -fn trans_enum_variant(ccx: @crate_ctxt, enum_id: ast::node_id, - variant: ast::variant, disr: int, is_degen: bool, +fn trans_enum_variant(ccx: @crate_ctxt, + enum_id: ast::node_id, + variant: ast::variant, + args: ~[ast::variant_arg], + disr: int, is_degen: bool, param_substs: option, llfndecl: ValueRef) { let _icx = ccx.insn_ctxt(~"trans_enum_variant"); // Translate variant arguments to function arguments. - let fn_args = vec::map(variant.node.args, |varg| + let fn_args = vec::map(args, |varg| {mode: ast::expl(ast::by_copy), ty: varg.ty, ident: @~"arg", @@ -4705,7 +4714,7 @@ fn trans_enum_variant(ccx: @crate_ctxt, enum_id: ast::node_id, }; let t_id = local_def(enum_id); let v_id = local_def(variant.node.id); - for vec::eachi(variant.node.args) |i, va| { + for vec::eachi(args) |i, va| { let lldestptr = GEP_enum(bcx, llblobptr, t_id, v_id, ty_param_substs, i); // If this argument to this function is a enum, it'll have come in to @@ -4867,11 +4876,16 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) { let vi = ty::enum_variants(ccx.tcx, local_def(item.id)); let mut i = 0; for vec::each(variants) |variant| { - if variant.node.args.len() > 0u { - let llfn = get_item_val(ccx, variant.node.id); - trans_enum_variant(ccx, item.id, variant, - vi[i].disr_val, degen, - none, llfn); + 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(_) | ast::struct_variant_kind => { + // Nothing to do. + } } i += 1; } @@ -5166,15 +5180,23 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { } ast_map::node_variant(v, enm, pth) => { - assert v.node.args.len() != 0u; - let pth = vec::append(*pth, - ~[path_name(enm.ident), - path_name(v.node.name)]); - let llfn = match check enm.node { - ast::item_enum(_, _) => { - register_fn(ccx, v.span, pth, id) - } - }; + let llfn; + match v.node.kind { + ast::tuple_variant_kind(args) => { + assert args.len() != 0u; + let pth = vec::append(*pth, + ~[path_name(enm.ident), + path_name(v.node.name)]); + llfn = match check enm.node { + ast::item_enum(_, _) => { + register_fn(ccx, v.span, pth, id) + } + }; + } + ast::struct_variant_kind => { + fail ~"struct unexpected in get_item_val" + } + } set_inline_hint(llfn); llfn } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 1f79774256d9..db8d2b3ae3e6 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -2837,28 +2837,37 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[variant_info] { ast_map::node_item(@{node: ast::item_enum(variants, _), _}, _) => { let mut disr_val = -1; @vec::map(variants, |variant| { - let ctor_ty = node_id_to_type(cx, variant.node.id); - let arg_tys = { - if vec::len(variant.node.args) > 0u { - ty_fn_args(ctor_ty).map(|a| a.ty) - } else { ~[] } - }; - match variant.node.disr_expr { - some (ex) => { - // FIXME: issue #1417 - disr_val = match const_eval::eval_const_expr(cx, ex) { - const_eval::const_int(val) =>val as int, - _ => cx.sess.bug(~"tag_variants: bad disr expr") + match variant.node.kind { + ast::tuple_variant_kind(args) => { + let ctor_ty = node_id_to_type(cx, variant.node.id); + let arg_tys = { + if vec::len(args) > 0u { + ty_fn_args(ctor_ty).map(|a| a.ty) + } else { + ~[] + } + }; + match variant.node.disr_expr { + some (ex) => { + // FIXME: issue #1417 + disr_val = match const_eval::eval_const_expr(cx, + ex) { + const_eval::const_int(val) => val as int, + _ => cx.sess.bug(~"tag_variants: bad disr expr") + } + } + _ => disr_val += 1 + } + @{args: arg_tys, + ctor_ty: ctor_ty, + name: variant.node.name, + id: ast_util::local_def(variant.node.id), + disr_val: disr_val + } } - } - _ => disr_val += 1 + ast::struct_variant_kind => + fail ~"struct variant kinds unimpl in enum_variants" } - @{args: arg_tys, - ctor_ty: ctor_ty, - name: variant.node.name, - id: ast_util::local_def(variant.node.id), - disr_val: disr_val - } }) } _ => cx.sess.bug(~"tag_variants: id not bound to an enum") diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index c9f9e45bb78c..c62861e211df 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -2073,9 +2073,13 @@ fn check_enum_variants(ccx: @crate_ctxt, } vec::push(disr_vals, disr_val); let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id); - let arg_tys = if v.node.args.len() > 0u { - ty::ty_fn_args(ctor_ty).map(|a| a.ty) - } else { ~[] }; + 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}); diff --git a/src/rustc/middle/typeck/coherence.rs b/src/rustc/middle/typeck/coherence.rs index c6633efe43f9..037a93fdf3d4 100644 --- a/src/rustc/middle/typeck/coherence.rs +++ b/src/rustc/middle/typeck/coherence.rs @@ -111,7 +111,6 @@ fn get_base_type_def_id(inference_context: infer_ctxt, class CoherenceInfo { // Contains implementations of methods that are inherent to a type. // Methods in these implementations don't need to be exported. - let inherent_methods: hashmap>; // Contains implementations of methods associated with a trait. For these, diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index ce41330d25d7..3f68cc40f1da 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -115,20 +115,23 @@ fn get_enum_variant_types(ccx: @crate_ctxt, for variants.each |variant| { // Nullary enum constructors get turned into constants; n-ary enum // constructors get turned into functions. - let result_ty = if vec::len(variant.node.args) == 0u { - enum_ty - } else { - let rs = type_rscope(rp); - let args = variant.node.args.map(|va| { - let arg_ty = ccx.to_ty(rs, va.ty); - {mode: ast::expl(ast::by_copy), ty: arg_ty} - }); - ty::mk_fn(tcx, {purity: ast::pure_fn, - proto: ast::proto_box, - bounds: @~[], - inputs: args, - output: enum_ty, - ret_style: ast::return_val}) + let result_ty; + match variant.node.kind { + ast::tuple_variant_kind(args) if args.len() > 0 => { + let rs = type_rscope(rp); + let args = args.map(|va| { + 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, + proto: ast::proto_box, + bounds: @~[], + inputs: args, + output: enum_ty, + ret_style: ast::return_val}); + } + ast::tuple_variant_kind(_) | ast::struct_variant_kind => + result_ty = enum_ty }; let tpt = {bounds: ty_param_bounds(ccx, ty_params), rp: rp,