about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorElliott Slaughter <eslaughter@mozilla.com>2012-08-07 14:20:31 -0700
committerElliott Slaughter <eslaughter@mozilla.com>2012-08-07 16:58:15 -0700
commitcdfc4b1c7a968635ae7a0fec40e26e93b5a77538 (patch)
treef9e0a2f6ed9ef30a3929ec848962daab8eadebce /src/rustc
parent61446293f91cd7a4dff7ca5e17ca5eced22577ad (diff)
downloadrust-cdfc4b1c7a968635ae7a0fec40e26e93b5a77538.tar.gz
rust-cdfc4b1c7a968635ae7a0fec40e26e93b5a77538.zip
rustc: Fix for type_of on recursive enum creating two types instead of one.
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/trans/type_of.rs31
1 files changed, 15 insertions, 16 deletions
diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs
index 73daa654d28..71d73d874ea 100644
--- a/src/rustc/middle/trans/type_of.rs
+++ b/src/rustc/middle/trans/type_of.rs
@@ -92,7 +92,14 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
           ty::ty_estr(ty::vstore_uniq) => {
             T_unique_ptr(T_unique(cx, T_vec(cx, T_i8())))
           }
-          ty::ty_enum(did, _) => type_of_enum(cx, did, t),
+          ty::ty_enum(did, _) => {
+            // Only create the named struct, but don't fill it in. We
+            // fill it in *after* placing it into the type cache. This
+            // avoids creating more than one copy of the enum when one
+            // of the enum's variants refers to the enum itself.
+
+            common::T_named_struct(llvm_type_name(cx, t))
+          }
           ty::ty_estr(ty::vstore_box) => {
             T_box_ptr(T_box(cx, T_vec(cx, T_i8())))
           }
@@ -165,8 +172,11 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
 
         cx.lltypes.insert(t, llty);
 
-        // If this was a class, fill in the type now.
+        // If this was an enum or class, fill in the type now.
         match ty::get(t).struct {
+          ty::ty_enum(did, _) => {
+              fill_type_of_enum(cx, did, t, llty);
+          }
           ty::ty_class(did, ts) => {
             // Only instance vars are record fields at runtime.
             let fields = ty::lookup_class_fields(cx.tcx, did);
@@ -191,21 +201,11 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
     return llty;
 }
 
-// This should only be called from type_of, above, because it
-// creates new llvm named struct types lazily that are then
-// cached by type_of
-fn type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t)
-    -> TypeRef {
+fn fill_type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t,
+                     llty: TypeRef) {
 
     debug!{"type_of_enum %?: %?", t, ty::get(t)};
 
-    // Every enum type has a unique name. When we find our roots
-    // for GC and unwinding we will use this name to rediscover
-    // the Rust type
-    let name = llvm_type_name(cx, t);
-
-    let named_llty = common::T_named_struct(name);
-
     let lltys = {
         let degen = (*ty::enum_variants(cx.tcx, did)).len() == 1u;
         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)
         }
     };
 
-    common::set_struct_body(named_llty, lltys);
-    return named_llty;
+    common::set_struct_body(llty, lltys);
 }
 
 fn llvm_type_name(cx: @crate_ctxt, t: ty::t) -> ~str {