rustc: Do some plumbing work on nested enums
This commit is contained in:
parent
166cb1b28b
commit
f110e8f21c
12 changed files with 250 additions and 157 deletions
|
@ -636,7 +636,8 @@ type variant_arg = {ty: @ty, id: node_id};
|
||||||
#[auto_serialize]
|
#[auto_serialize]
|
||||||
enum variant_kind {
|
enum variant_kind {
|
||||||
tuple_variant_kind(~[variant_arg]),
|
tuple_variant_kind(~[variant_arg]),
|
||||||
struct_variant_kind(@struct_def)
|
struct_variant_kind(@struct_def),
|
||||||
|
enum_variant_kind(~[variant])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[auto_serialize]
|
#[auto_serialize]
|
||||||
|
|
|
@ -913,7 +913,9 @@ fn deser_enum(cx: ext_ctxt, tps: deser_tps_map, e_name: ast::ident,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
ast::struct_variant_kind(*) =>
|
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(),
|
{pats: ~[@{id: cx.next_id(),
|
||||||
|
|
|
@ -564,6 +564,11 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ {
|
||||||
dtor: dtor
|
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);
|
let fold_attribute = |x| fold_attribute_(x, fld);
|
||||||
|
|
|
@ -17,28 +17,27 @@ import dvec::{dvec, extensions};
|
||||||
import vec::{push};
|
import vec::{push};
|
||||||
import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
|
import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
|
||||||
bind_by_ref, bind_by_implicit_ref, bind_by_value,
|
bind_by_ref, bind_by_implicit_ref, bind_by_value,
|
||||||
bitand, bitor, bitxor, blk,
|
bitand, bitor, bitxor, blk, blk_check_mode, bound_const,
|
||||||
blk_check_mode, bound_const, bound_copy, bound_send, bound_trait,
|
bound_copy, bound_send, bound_trait, bound_owned, box, by_copy,
|
||||||
bound_owned, box, by_copy, by_move, by_mutbl_ref, by_ref, by_val,
|
by_move, by_mutbl_ref, by_ref, by_val, capture_clause,
|
||||||
capture_clause, capture_item, cdir_dir_mod, cdir_src_mod,
|
capture_item, cdir_dir_mod, cdir_src_mod, cdir_view_item,
|
||||||
cdir_view_item, class_immutable, class_member, class_method,
|
class_immutable, class_member, class_method, class_mutable,
|
||||||
class_mutable, crate, crate_cfg, crate_directive, decl,
|
crate, crate_cfg, crate_directive, decl, decl_item, decl_local,
|
||||||
decl_item, decl_local, default_blk, deref, div, expl, expr,
|
default_blk, deref, div, enum_variant_kind, expl, expr, expr_,
|
||||||
expr_, expr_addr_of, expr_match, expr_again, expr_assert,
|
expr_addr_of, expr_match, expr_again, expr_assert, expr_assign,
|
||||||
expr_assign, expr_assign_op, expr_binary, expr_block, expr_break,
|
expr_assign_op, expr_binary, expr_block, expr_break, expr_call,
|
||||||
expr_call, expr_cast, expr_copy, expr_do_body,
|
expr_cast, expr_copy, expr_do_body, expr_fail, expr_field,
|
||||||
expr_fail, expr_field, expr_fn, expr_fn_block, expr_if,
|
expr_fn, expr_fn_block, expr_if, expr_index, expr_lit, expr_log,
|
||||||
expr_index, expr_lit, expr_log, expr_loop,
|
expr_loop, expr_loop_body, expr_mac, expr_move, expr_path,
|
||||||
expr_loop_body, expr_mac, expr_move, expr_path, expr_rec,
|
expr_rec, expr_repeat, expr_ret, expr_swap, expr_struct,
|
||||||
expr_repeat, expr_ret, expr_swap, expr_struct, expr_tup,
|
expr_tup, expr_unary, expr_unary_move, expr_vec, expr_vstore,
|
||||||
expr_unary, expr_unary_move, expr_vec, expr_vstore, expr_while,
|
expr_while, extern_fn, field, fn_decl, foreign_item,
|
||||||
extern_fn, field, fn_decl, foreign_item, foreign_item_fn,
|
foreign_item_fn, foreign_mod, ident, impure_fn, infer, inherited,
|
||||||
foreign_mod, ident, impure_fn, infer, inherited, init_assign,
|
init_assign, init_move, initializer, instance_var, item, item_,
|
||||||
init_move, initializer, instance_var, item, item_, item_class,
|
item_class, item_const, item_enum, item_fn, item_foreign_mod,
|
||||||
item_const, item_enum, item_fn, item_foreign_mod, item_impl,
|
item_impl, item_mac, item_mod, item_trait, item_ty, lit, lit_,
|
||||||
item_mac, item_mod, item_trait, item_ty, lit, lit_, lit_bool,
|
lit_bool, lit_float, lit_int, lit_int_unsuffixed, lit_nil,
|
||||||
lit_float, lit_int, lit_int_unsuffixed, lit_nil, lit_str,
|
lit_str, lit_uint, local, m_const, m_imm, m_mutbl, mac_, mac_aq,
|
||||||
lit_uint, local, m_const, m_imm, m_mutbl, mac_, mac_aq,
|
|
||||||
mac_ellipsis, mac_invoc, mac_invoc_tt, mac_var, matcher,
|
mac_ellipsis, mac_invoc, mac_invoc_tt, mac_var, matcher,
|
||||||
match_nonterminal, match_seq, match_tok, method, mode, mt, mul,
|
match_nonterminal, match_seq, match_tok, method, mode, mt, mul,
|
||||||
mutability, neg, noreturn, not, pat, pat_box, pat_enum,
|
mutability, neg, noreturn, not, pat, pat_box, pat_enum,
|
||||||
|
@ -2842,30 +2841,8 @@ class parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_item_enum() -> item_info {
|
fn parse_enum_body(ty_params: ~[ast::ty_param]) -> ~[ast::variant] {
|
||||||
let id = self.parse_ident();
|
|
||||||
self.parse_region_param();
|
|
||||||
let ty_params = self.parse_ty_params();
|
|
||||||
let mut variants: ~[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;
|
let mut all_nullary = true, have_disr = false;
|
||||||
|
|
||||||
while self.token != token::RBRACE {
|
while self.token != token::RBRACE {
|
||||||
|
@ -2954,6 +2931,34 @@ class parser {
|
||||||
self.fatal(~"discriminator values can only be used with a c-like \
|
self.fatal(~"discriminator values can only be used with a c-like \
|
||||||
enum");
|
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)
|
(id, item_enum(variants, ty_params), none)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -516,18 +516,7 @@ fn print_item(s: ps, &&item: @ast::item) {
|
||||||
word(s.s, ~";");
|
word(s.s, ~";");
|
||||||
end(s);
|
end(s);
|
||||||
} else {
|
} else {
|
||||||
bopen(s);
|
print_variants(s, variants, item.span);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::item_class(struct_def, tps) => {
|
ast::item_class(struct_def, tps) => {
|
||||||
|
@ -582,6 +571,21 @@ fn print_item(s: ps, &&item: @ast::item) {
|
||||||
s.ann.post(ann_node);
|
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],
|
fn print_struct(s: ps, struct_def: @ast::struct_def, tps: ~[ast::ty_param],
|
||||||
ident: ast::ident, span: ast::span) {
|
ident: ast::ident, span: ast::span) {
|
||||||
word_nbsp(s, *ident);
|
word_nbsp(s, *ident);
|
||||||
|
@ -710,6 +714,9 @@ fn print_variant(s: ps, v: ast::variant) {
|
||||||
head(s, ~"");
|
head(s, ~"");
|
||||||
print_struct(s, struct_def, ~[], v.node.name, v.span);
|
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 {
|
match v.node.disr_expr {
|
||||||
some(d) => {
|
some(d) => {
|
||||||
|
|
|
@ -138,17 +138,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
|
||||||
}
|
}
|
||||||
item_enum(variants, tps) => {
|
item_enum(variants, tps) => {
|
||||||
v.visit_ty_params(tps, e, v);
|
v.visit_ty_params(tps, e, v);
|
||||||
for variants.each |vr| {
|
visit_variants(variants, tps, 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(struct_def) => {
|
|
||||||
v.visit_struct_def(struct_def, vr.node.name, tps,
|
|
||||||
vr.node.id, e, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
item_impl(tps, traits, ty, methods) => {
|
item_impl(tps, traits, ty, methods) => {
|
||||||
v.visit_ty_params(tps, e, v);
|
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>) {
|
fn visit_class_item<E>(cm: @class_member, e:E, v:vt<E>) {
|
||||||
match cm.node {
|
match cm.node {
|
||||||
instance_var(_, t, _, _, _) => v.visit_ty(t, e, v),
|
instance_var(_, t, _, _, _) => v.visit_ty(t, e, v),
|
||||||
|
|
|
@ -398,7 +398,8 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
||||||
if args.len() > 0 && ty_params.len() == 0 => {
|
if args.len() > 0 && ty_params.len() == 0 => {
|
||||||
encode_symbol(ecx, ebml_w, variant.node.id);
|
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);
|
encode_discriminant(ecx, ebml_w, variant.node.id);
|
||||||
if vi[i].disr_val != disr_val {
|
if vi[i].disr_val != disr_val {
|
||||||
|
|
|
@ -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_binary, expr_cast, expr_field, expr_fn};
|
||||||
import syntax::ast::{expr_fn_block, expr_index, expr_path};
|
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_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::{def_upvar, def_use, def_variant, div, eq};
|
||||||
import syntax::ast::{expr_assign_op, expr_binary, expr_cast, expr_field};
|
import syntax::ast::{enum_variant_kind, expr, expr_assign_op, expr_binary};
|
||||||
import syntax::ast::{expr_fn, expr_fn_block, expr_index, expr_path};
|
import syntax::ast::{expr_cast, expr_field, expr_fn, expr_fn_block};
|
||||||
import syntax::ast::{expr_struct, expr_unary, fn_decl, foreign_item};
|
import syntax::ast::{expr_index, expr_path, expr_struct, expr_unary, fn_decl};
|
||||||
import syntax::ast::{foreign_item_fn, ge, gt, ident, trait_ref, impure_fn};
|
import syntax::ast::{foreign_item, foreign_item_fn, ge, gt, ident, trait_ref};
|
||||||
import syntax::ast::{instance_var, item, item_class, item_const, item_enum};
|
import syntax::ast::{impure_fn, instance_var, item, item_class, item_const};
|
||||||
import syntax::ast::{item_fn, item_mac, item_foreign_mod, item_impl};
|
import syntax::ast::{item_enum, item_fn, item_mac, item_foreign_mod};
|
||||||
import syntax::ast::{item_mod, item_trait, item_ty, le, local, local_crate};
|
import syntax::ast::{item_impl, item_mod, item_trait, item_ty, le, local};
|
||||||
import syntax::ast::{lt, method, mul, ne, neg, node_id, pat, pat_enum};
|
import syntax::ast::{local_crate, lt, method, mul, ne, neg, node_id, pat};
|
||||||
import syntax::ast::{pat_ident, path, prim_ty, pat_box, pat_uniq, pat_lit};
|
import syntax::ast::{pat_enum, pat_ident, path, prim_ty, pat_box, pat_uniq};
|
||||||
import syntax::ast::{pat_range, pat_rec, pat_struct, pat_tup, pat_wild};
|
import syntax::ast::{pat_lit, pat_range, pat_rec, pat_struct, pat_tup};
|
||||||
import syntax::ast::{provided, required, rem, self_ty_, shl, stmt_decl};
|
import syntax::ast::{pat_wild, provided, required, rem, self_ty_, shl};
|
||||||
import syntax::ast::{struct_variant_kind, sty_static, subtract};
|
import syntax::ast::{stmt_decl, struct_variant_kind, sty_static, subtract};
|
||||||
import syntax::ast::{tuple_variant_kind, ty};
|
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_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};
|
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,
|
fn build_reduced_graph_for_variant(variant: variant,
|
||||||
item_id: def_id,
|
item_id: def_id,
|
||||||
parent: ReducedGraphParent,
|
parent: ReducedGraphParent,
|
||||||
&&_visitor: vt<ReducedGraphParent>) {
|
&&visitor: vt<ReducedGraphParent>) {
|
||||||
|
|
||||||
let atom = (*self.atom_table).intern(variant.node.name);
|
let atom = (*self.atom_table).intern(variant.node.name);
|
||||||
let (child, _) = self.add_child(atom, parent, ~[ValueNS],
|
let (child, _) = self.add_child(atom, parent, ~[ValueNS],
|
||||||
|
@ -1146,6 +1146,14 @@ class Resolver {
|
||||||
variant.span);
|
variant.span);
|
||||||
self.structs.insert(local_def(variant.node.id), false);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2235,7 +2235,9 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id,
|
||||||
psubsts, d);
|
psubsts, d);
|
||||||
}
|
}
|
||||||
ast::struct_variant_kind(_) =>
|
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
|
d
|
||||||
}
|
}
|
||||||
|
@ -4893,6 +4895,34 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path,
|
||||||
lldecl
|
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) {
|
fn trans_item(ccx: @crate_ctxt, item: ast::item) {
|
||||||
let _icx = ccx.insn_ctxt(~"trans_item");
|
let _icx = ccx.insn_ctxt(~"trans_item");
|
||||||
let path = match check ccx.tcx.items.get(item.id) {
|
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 degen = variants.len() == 1u;
|
||||||
let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
|
let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for vec::each(variants) |variant| {
|
trans_variants(ccx, variants, item.id, tps, degen, path, vi,
|
||||||
match variant.node.kind {
|
&mut i);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::item_const(_, expr) => consts::trans_const(ccx, expr, item.id),
|
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(_) => {
|
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);
|
set_inline_hint(llfn);
|
||||||
|
|
|
@ -2868,8 +2868,12 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[variant_info] {
|
||||||
disr_val: disr_val
|
disr_val: disr_val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::struct_variant_kind(_) =>
|
ast::struct_variant_kind(_) => {
|
||||||
fail ~"struct variant kinds unimpl in enum_variants"
|
fail ~"struct variant kinds unimpl in enum_variants"
|
||||||
|
}
|
||||||
|
ast::enum_variant_kind(_) => {
|
||||||
|
fail ~"enum variant kinds unimpl in enum_variants"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -2043,52 +2043,75 @@ fn check_enum_variants(ccx: @crate_ctxt,
|
||||||
sp: span,
|
sp: span,
|
||||||
vs: ~[ast::variant],
|
vs: ~[ast::variant],
|
||||||
id: ast::node_id) {
|
id: ast::node_id) {
|
||||||
|
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});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let rty = ty::node_id_to_type(ccx.tcx, id);
|
let rty = ty::node_id_to_type(ccx.tcx, id);
|
||||||
let mut disr_vals: ~[int] = ~[];
|
let mut disr_vals: ~[int] = ~[];
|
||||||
let mut disr_val = 0;
|
let mut disr_val = 0;
|
||||||
let mut variants = ~[];
|
let mut variants = ~[];
|
||||||
for vs.each |v| {
|
|
||||||
match v.node.disr_expr {
|
do_check(ccx, sp, vs, id, &mut disr_vals, &mut disr_val, &mut variants);
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cache so that ty::enum_variants won't repeat this work
|
// cache so that ty::enum_variants won't repeat this work
|
||||||
ccx.tcx.enum_var_cache.insert(local_def(id), @variants);
|
ccx.tcx.enum_var_cache.insert(local_def(id), @variants);
|
||||||
|
|
|
@ -124,21 +124,33 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
|
||||||
let arg_ty = ccx.to_ty(rs, va.ty);
|
let arg_ty = ccx.to_ty(rs, va.ty);
|
||||||
{mode: ast::expl(ast::by_copy), ty: arg_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,
|
proto: ast::proto_box,
|
||||||
bounds: @~[],
|
bounds: @~[],
|
||||||
inputs: args,
|
inputs: args,
|
||||||
output: enum_ty,
|
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,
|
match result_ty {
|
||||||
ty: result_ty};
|
none => {}
|
||||||
tcx.tcache.insert(local_def(variant.node.id), tpt);
|
some(result_ty) => {
|
||||||
write_ty_to_tcx(tcx, variant.node.id, 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue