Skip to content

Commit cdfc4b1

Browse files
author
Elliott Slaughter
committed
rustc: Fix for type_of on recursive enum creating two types instead of one.
1 parent 6144629 commit cdfc4b1

File tree

1 file changed

+15
-16
lines changed

1 file changed

+15
-16
lines changed

src/rustc/middle/trans/type_of.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,14 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
9292
ty::ty_estr(ty::vstore_uniq) => {
9393
T_unique_ptr(T_unique(cx, T_vec(cx, T_i8())))
9494
}
95-
ty::ty_enum(did, _) => type_of_enum(cx, did, t),
95+
ty::ty_enum(did, _) => {
96+
// Only create the named struct, but don't fill it in. We
97+
// fill it in *after* placing it into the type cache. This
98+
// avoids creating more than one copy of the enum when one
99+
// of the enum's variants refers to the enum itself.
100+
101+
common::T_named_struct(llvm_type_name(cx, t))
102+
}
96103
ty::ty_estr(ty::vstore_box) => {
97104
T_box_ptr(T_box(cx, T_vec(cx, T_i8())))
98105
}
@@ -165,8 +172,11 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
165172

166173
cx.lltypes.insert(t, llty);
167174

168-
// If this was a class, fill in the type now.
175+
// If this was an enum or class, fill in the type now.
169176
match ty::get(t).struct {
177+
ty::ty_enum(did, _) => {
178+
fill_type_of_enum(cx, did, t, llty);
179+
}
170180
ty::ty_class(did, ts) => {
171181
// Only instance vars are record fields at runtime.
172182
let fields = ty::lookup_class_fields(cx.tcx, did);
@@ -191,21 +201,11 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
191201
return llty;
192202
}
193203

194-
// This should only be called from type_of, above, because it
195-
// creates new llvm named struct types lazily that are then
196-
// cached by type_of
197-
fn type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t)
198-
-> TypeRef {
204+
fn fill_type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t,
205+
llty: TypeRef) {
199206

200207
debug!{"type_of_enum %?: %?", t, ty::get(t)};
201208

202-
// Every enum type has a unique name. When we find our roots
203-
// for GC and unwinding we will use this name to rediscover
204-
// the Rust type
205-
let name = llvm_type_name(cx, t);
206-
207-
let named_llty = common::T_named_struct(name);
208-
209209
let lltys = {
210210
let degen = (*ty::enum_variants(cx.tcx, did)).len() == 1u;
211211
let size = shape::static_size_of_enum(cx, t);
@@ -220,8 +220,7 @@ fn type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t)
220220
}
221221
};
222222

223-
common::set_struct_body(named_llty, lltys);
224-
return named_llty;
223+
common::set_struct_body(llty, lltys);
225224
}
226225

227226
fn llvm_type_name(cx: @crate_ctxt, t: ty::t) -> ~str {

0 commit comments

Comments
 (0)