From 499a58708f7576f2c9d5b6eb266a7fe855eff419 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 20 Dec 2012 00:02:46 -0700 Subject: [PATCH] Assign correct types to struct-like enum variant constructors Before, the type was just the enum type itself, which caused an assertion failure in iter_variant in trans::base. r=brson Closes #4229 --- src/librustc/middle/trans/base.rs | 5 ++++- src/librustc/middle/typeck/collect.rs | 15 ++++++++++++++- src/test/run-pass/enum-variants.rs | 11 +++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/enum-variants.rs diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index a65f6668cd3..a48032fa1ca 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -545,7 +545,10 @@ fn iter_variant(cx: block, a_tup: ValueRef, j += 1u; } } - _ => cx.tcx().sess.bug(~"iter_variant: not a function type") + _ => cx.tcx().sess.bug(fmt!("iter_variant: not a function type: \ + %s (variant name = %s)", + cx.ty_to_str(fn_ty), + cx.sess().str_of(variant.name))) } return cx; } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index b4ba9c3d654..45f1ad7470c 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -158,13 +158,26 @@ fn get_enum_variant_types(ccx: @crate_ctxt, result_ty = Some(enum_ty); } ast::struct_variant_kind(struct_def) => { - result_ty = Some(enum_ty); // XXX: Merge with computation of the the same value below? let tpt = {bounds: ty_param_bounds(ccx, ty_params), region_param: rp, ty: enum_ty}; convert_struct( ccx, rp, struct_def, ty_params, tpt, variant.node.id); + // Compute the ctor arg types from the struct fields + let struct_fields = do struct_def.fields.map |struct_field| { + {mode: ast::expl(ast::by_val), + ty: ty::node_id_to_type(ccx.tcx, (*struct_field).node.id) + } + }; + result_ty = Some(ty::mk_fn(tcx, FnTyBase { + meta: FnMeta {purity: ast::pure_fn, + proto: ast::ProtoBare, + onceness: ast::Many, + bounds: @~[], + region: ty::re_static, + ret_style: ast::return_val}, + sig: FnSig {inputs: struct_fields, output: enum_ty }})); } ast::enum_variant_kind(ref enum_definition) => { get_enum_variant_types(ccx, diff --git a/src/test/run-pass/enum-variants.rs b/src/test/run-pass/enum-variants.rs new file mode 100644 index 00000000000..26fae68e158 --- /dev/null +++ b/src/test/run-pass/enum-variants.rs @@ -0,0 +1,11 @@ +enum Animal { + Dog (~str, float), + Cat { name: ~str, weight: float } +} + +fn main() { + let mut a: Animal = Dog(~"Cocoa", 37.2); + a = Cat{ name: ~"Spotty", weight: 2.7 }; + // permuting the fields should work too + let c = Cat { weight: 3.1, name: ~"Spreckles" }; +}