about summary refs log tree commit diff
path: root/src/comp/middle
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-06-24 14:31:52 -0400
committerPatrick Walton <pcwalton@mimiga.net>2011-06-24 14:32:50 -0400
commitb4c0893a39d1675110bb0865aabfbaec1cd0e6e7 (patch)
treee5538361913fae3b3f42d8e0bb2d87b729856288 /src/comp/middle
parent1e7f06b17ae11b35e55a6f8655f13be8d590e91a (diff)
downloadrust-b4c0893a39d1675110bb0865aabfbaec1cd0e6e7.tar.gz
rust-b4c0893a39d1675110bb0865aabfbaec1cd0e6e7.zip
rustc: If needed, duplicate types' heap parts recursively through structural types
Diffstat (limited to 'src/comp/middle')
-rw-r--r--src/comp/middle/trans.rs19
-rw-r--r--src/comp/middle/ty.rs78
2 files changed, 65 insertions, 32 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 3f3bf9f665a..2bcc19b6c69 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -3024,13 +3024,20 @@ fn memmove_ty(&@block_ctxt cx, ValueRef dst, ValueRef src, &ty::t t) ->
 // Duplicates the heap-owned memory owned by a value of the given type.
 fn duplicate_heap_parts(&@block_ctxt cx, ValueRef vptr, ty::t typ) -> result {
     alt (ty::struct(cx.fcx.lcx.ccx.tcx, typ)) {
-        case (ty::ty_ivec(?tm)) {
-            ret ivec::duplicate_heap_part(cx, vptr, tm.ty);
-        }
-        case (ty::ty_str) {
-            ret ivec::duplicate_heap_part(cx, vptr,
-                ty::mk_mach(cx.fcx.lcx.ccx.tcx, common::ty_u8));
+      case (ty::ty_ivec(?tm)) {
+        ret ivec::duplicate_heap_part(cx, vptr, tm.ty);
+      }
+      case (ty::ty_istr) {
+        ret ivec::duplicate_heap_part(cx, vptr,
+            ty::mk_mach(cx.fcx.lcx.ccx.tcx, common::ty_u8));
+      }
+      case (_) {    // TODO: guard
+        if (ty::type_is_structural(cx.fcx.lcx.ccx.tcx, typ)) {
+            ret iter_structural_ty(cx, vptr, typ, duplicate_heap_parts);
         }
+
+        ret res(cx, C_nil());
+      }
     }
 }
 
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index fe2cba1180c..e392c8aa0f3 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -1151,36 +1151,62 @@ fn type_is_signed(&ctxt cx, &t ty) -> bool {
 }
 
 fn type_owns_heap_mem(&ctxt cx, &t ty) -> bool {
+    auto result = false;
     alt (struct(cx, ty)) {
-        case (ty_ivec(_)) { ret true; }
-        case (ty_istr) { ret true; }
+        case (ty_ivec(_)) { result = true; }
+        case (ty_istr) { result = true; }
 
-        case (ty_nil) { ret false; }
-        case (ty_bot) { ret false; }
-        case (ty_bool) { ret false; }
-        case (ty_int) { ret false; }
-        case (ty_float) { ret false; }
-        case (ty_uint) { ret false; }
-        case (ty_machine(_)) { ret false; }
-        case (ty_char) { ret false; }
-        case (ty_str) { ret false; }
-        case (ty_tag(_,_)) { ret false; }
-        case (ty_box(_)) { ret false; }
-        case (ty_vec(_)) { ret false; }
-        case (ty_ptr(_)) { ret false; }
-        case (ty_port(_)) { ret false; }
-        case (ty_chan(_)) { ret false; }
-        case (ty_task) { ret false; }
-        case (ty_tup(_)) { ret false; }
-        case (ty_rec(_)) { ret false; }
-        case (ty_fn(_,_,_,_,_)) { ret false; }
-        case (ty_native_fn(_,_,_)) { ret false; }
-        case (ty_obj(_)) { ret false; }
+        // scalar types
+        case (ty_nil) { result = false; }
+        case (ty_bot) { result = false; }
+        case (ty_bool) { result = false; }
+        case (ty_int) { result = false; }
+        case (ty_float) { result = false; }
+        case (ty_uint) { result = false; }
+        case (ty_machine(_)) { result = false; }
+        case (ty_char) { result = false; }
+        case (ty_type) { result = false; }
+        case (ty_native) { result = false; }
+
+        // boxed types
+        case (ty_str) { result = false; }
+        case (ty_box(_)) { result = false; }
+        case (ty_vec(_)) { result = false; }
+        case (ty_fn(_,_,_,_,_)) { result = false; }
+        case (ty_native_fn(_,_,_)) { result = false; }
+        case (ty_obj(_)) { result = false; }
+
+        // structural types
+        case (ty_tag(?did, ?tps)) {
+            auto variants = tag_variants(cx, did);
+            for (variant_info variant in variants) {
+                auto tup_ty = mk_imm_tup(cx, variant.args);
+                // Perform any type parameter substitutions.
+                tup_ty = substitute_type_params(cx, tps, tup_ty);
+                if (type_owns_heap_mem(cx, tup_ty)) { result = true; }
+            }
+        }
+        case (ty_tup(?elts)) {
+            for (mt m in elts) {
+                if (type_owns_heap_mem(cx, m.ty)) { result = true; }
+            }
+        }
+        case (ty_rec(?flds)) {
+            for (field f in flds) {
+                if (type_owns_heap_mem(cx, f.mt.ty)) { result = true; }
+            }
+        }
+
+        case (ty_ptr(_)) { result = false; }
+        case (ty_port(_)) { result = false; }
+        case (ty_chan(_)) { result = false; }
+        case (ty_task) { result = false; }
+        case (ty_tup(_)) { result = false; }
+        case (ty_rec(_)) { result = false; }
         case (ty_var(_)) { fail "ty_var in type_owns_heap_mem"; }
-        case (ty_param(_)) { ret false; }
-        case (ty_type) { ret false; }
-        case (ty_native) { ret false; }
+        case (ty_param(_)) { result = false; }
     }
+    ret result;
 }
 
 fn type_param(&ctxt cx, &t ty) -> option::t[uint] {