auto merge of #7557 : michaelwoerister/rust/enum_structs, r=pcwalton

After getting an ICE trying to use the `Repr` enum from middle::trans::adt (see issue #7527), I tried to implement the missing case for struct-like enum variants in `middle::ty::enum_variants()`. It seems to work now (and passes make check) but there are still some uncertainties that bother me:
+ I'm not sure I did everything, right. Especially getting the variant constructor function from the variant node id is just copied from the tuple-variant case. Someone with more experience in the code base should be able to see rather quickly whether this OK so.
+ It is kind of strange that I could not reproduce the ICE with a smaller test case. The unimplemented code path never seems to be hit in most cases, even when using the exact same `Repr` enum, just with `ty::t` replaced by an opaque pointer. Also, within the `adt` module, `Repr` and matching on it is used multiple times, again without running into problems. Can anyone explain why this is the case? That would be much appreciated. 

Apart from that, I hope this PR is useful.
This commit is contained in:
bors 2013-07-06 23:59:05 -07:00
commit 88487d8274

View File

@ -3828,41 +3828,62 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
}, _) => {
let mut disr_val = -1;
@enum_definition.variants.iter().transform(|variant| {
let ctor_ty = node_id_to_type(cx, variant.node.id);
match variant.node.kind {
ast::tuple_variant_kind(ref args) => {
let ctor_ty = node_id_to_type(cx, variant.node.id);
let arg_tys = {
if args.len() > 0u {
ty_fn_args(ctor_ty).map(|a| *a)
} else {
let arg_tys = if args.len() > 0u {
ty_fn_args(ctor_ty).map(|a| *a) }
else {
~[]
}
};
};
match variant.node.disr_expr {
Some (ex) => {
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")
_ => cx.sess.bug("enum_variants: bad disr expr")
}
}
_ => disr_val += 1
}
@VariantInfo_{args: arg_tys,
ctor_ty: ctor_ty,
name: variant.node.name,
id: ast_util::local_def(variant.node.id),
disr_val: disr_val,
vis: variant.node.vis
@VariantInfo_{
args: arg_tys,
ctor_ty: ctor_ty,
name: variant.node.name,
id: ast_util::local_def(variant.node.id),
disr_val: disr_val,
vis: variant.node.vis
}
}
ast::struct_variant_kind(_) => {
fail!("struct variant kinds unimpl in enum_variants")
},
ast::struct_variant_kind(struct_def) => {
let arg_tys =
// Is this check needed for structs too, or are they always guaranteed
// to have a valid constructor function?
if struct_def.fields.len() > 0 {
ty_fn_args(ctor_ty).map(|a| *a)
} else {
~[]
};
assert!(variant.node.disr_expr.is_none());
disr_val += 1;
@VariantInfo_{
args: arg_tys,
ctor_ty: ctor_ty,
name: variant.node.name,
id: ast_util::local_def(variant.node.id),
disr_val: disr_val,
vis: variant.node.vis
}
}
}
}).collect()
}
_ => cx.sess.bug("tag_variants: id not bound to an enum")
_ => cx.sess.bug("enum_variants: id not bound to an enum")
}
};
cx.enum_var_cache.insert(id, result);