about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2012-06-12 16:25:09 -0700
committerTim Chevalier <chevalier@alum.wellesley.edu>2012-06-12 17:37:04 -0700
commitaa9d2d88d33266437ca770a7345cce0d23ad1011 (patch)
tree66225e5bd762c78643cb298e90d1f626355cb569 /src
parente9fc19c3c22174dd4308337805e686bbd4960635 (diff)
downloadrust-aa9d2d88d33266437ca770a7345cce0d23ad1011.tar.gz
rust-aa9d2d88d33266437ca770a7345cce0d23ad1011.zip
Handle class destructors correctly in metadata
This allows destructors to be inlined, which is necessary since
classes can have both ty params and destructors.
Diffstat (limited to 'src')
-rw-r--r--src/libsyntax/ast.rs3
-rw-r--r--src/libsyntax/ast_map.rs2
-rw-r--r--src/libsyntax/ast_util.rs5
-rw-r--r--src/rustc/metadata/decoder.rs17
-rw-r--r--src/rustc/metadata/encoder.rs38
-rw-r--r--src/rustc/middle/astencode.rs16
-rw-r--r--src/rustc/middle/trans/base.rs16
-rw-r--r--src/rustc/middle/trans/reachable.rs20
8 files changed, 91 insertions, 26 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 536ce3c294e..ad1501dd8b0 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -730,7 +730,8 @@ enum inlined_item {
     ii_item(@item),
     ii_method(def_id /* impl id */, @method),
     ii_native(@native_item),
-    ii_ctor(class_ctor, ident, [ty_param], def_id /* parent id */)
+    ii_ctor(class_ctor, ident, [ty_param], def_id /* parent id */),
+    ii_dtor(class_dtor, ident, [ty_param], def_id /* parent id */)
 }
 
 //
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index b2e6446d7ee..10397e795ab 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -106,7 +106,7 @@ fn map_decoded_item(diag: span_handler,
     // don't decode and instantiate the impl, but just the method, we have to
     // add it to the table now:
     alt ii {
-      ii_item(_) | ii_ctor(_,_,_,_) { /* fallthrough */ }
+      ii_item(*) | ii_ctor(*) | ii_dtor(*) { /* fallthrough */ }
       ii_native(i) {
         cx.map.insert(i.id, node_native_item(i, native_abi_rust_intrinsic,
                                              @path));
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index c81f6d9590f..9eee9a33af8 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -320,6 +320,7 @@ impl inlined_item_methods for inlined_item {
           ii_native(i) { /* FIXME: bad */ copy i.ident }
           ii_method(_, m) { /* FIXME: bad */ copy m.ident }
           ii_ctor(_, nm, _, _) { /* FIXME: bad */ copy nm }
+          ii_dtor(_, nm, _, _) { /* FIXME: bad */ copy nm }
         }
     }
 
@@ -329,6 +330,7 @@ impl inlined_item_methods for inlined_item {
           ii_native(i) { i.id }
           ii_method(_, m) { m.id }
           ii_ctor(ctor, _, _, _) { ctor.node.id }
+          ii_dtor(dtor, _, _, _) { dtor.node.id }
         }
     }
 
@@ -340,6 +342,9 @@ impl inlined_item_methods for inlined_item {
           ii_ctor(ctor, nm, tps, parent_id) {
               visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v);
           }
+          ii_dtor(dtor, nm, tps, parent_id) {
+              visit::visit_class_dtor_helper(dtor, tps, parent_id, e, v);
+          }
         }
     }
 }
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index 4df45033a77..dcb71c6718a 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -335,15 +335,18 @@ fn get_class_method(cdata: cmd, id: ast::node_id, name: str) -> ast::def_id {
 
 fn class_dtor(cdata: cmd, id: ast::node_id) -> option<ast::def_id> {
     let items = ebml::get_doc(ebml::doc(cdata.data), tag_items);
+    let mut found = none;
     let cls_items = alt maybe_find_item(id, items) {
             some(it) { it }
-            none     { ret none; }};
-    let mut rslt = none;
-    ebml::tagged_docs(cls_items, tag_item_dtor) {|f|
-        let did = parse_def_id(ebml::doc_data(f));
-        rslt = some(translate_def_id(cdata, did));
-    }
-    rslt
+            none     { fail (#fmt("class_dtor: class id not found \
+              when looking up dtor for %d", id)); }
+    };
+    ebml::tagged_docs(cls_items, tag_item_dtor) {|doc|
+         let doc1 = ebml::get_doc(doc, tag_def_id);
+         let did = parse_def_id(ebml::doc_data(doc1));
+         found = some(translate_def_id(cdata, did));
+    };
+    found
 }
 
 fn get_symbol(data: @[u8], id: ast::node_id) -> str {
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 113fafb73b3..215f73a6d4f 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -9,7 +9,7 @@ import ebml::writer;
 import syntax::ast::*;
 import syntax::print::pprust;
 import syntax::{ast_util, visit};
-import syntax::ast_util::local_def;
+import syntax::ast_util::*;
 import common::*;
 import middle::ty;
 import middle::ty::node_id_to_type;
@@ -206,12 +206,6 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
                 add_to_index(ebml_w, path, index, it.ident);
                 encode_named_def_id(ebml_w, it.ident,
                                     local_def(ctor.node.id));
-                /* Encode id for dtor */
-                option::iter(m_dtor) {|dtor|
-                        ebml_w.wr_tag(tag_item_dtor) {||
-                           encode_def_id(ebml_w, local_def(dtor.node.id));
-                    }
-                };
                 encode_class_item_paths(ebml_w, items, path + [it.ident],
                                         index);
             }
@@ -485,8 +479,8 @@ fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer,
         encode_family(ebml_w, purity_fn_family(decl.purity));
         encode_type_param_bounds(ebml_w, ecx, tps);
         let its_ty = node_id_to_type(ecx.tcx, id);
-        #debug("fn name = %s ty = %s", ident,
-               util::ppaux::ty_to_str(ecx.tcx, its_ty));
+        #debug("fn name = %s ty = %s its node id = %d", ident,
+               util::ppaux::ty_to_str(ecx.tcx, its_ty), id);
         encode_type(ecx, ebml_w, its_ty);
         encode_path(ebml_w, path, ast_map::path_name(ident));
         alt item {
@@ -623,13 +617,23 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_enum_variant_info(ecx, ebml_w, item.id, variants,
                                  path, index, tps);
       }
-      item_class(tps, ifaces, items, ctor, _dtor, rp) {
+      item_class(tps, ifaces, items, ctor, m_dtor, rp) {
         /* First, encode the fields and methods
            These come first because we need to write them to make
            the index, and the index needs to be in the item for the
            class itself */
         let idx = encode_info_for_class(ecx, ebml_w, item.id, path, tps,
                                           items, index);
+        /* Encode the dtor */
+        option::iter(m_dtor) {|dtor|
+          *index += [{val: dtor.node.id, pos: ebml_w.writer.tell()}];
+          encode_info_for_fn(ecx, ebml_w, dtor.node.id, item.ident
+                             + "_dtor", path, if tps.len() > 0u {
+                               some(ii_dtor(dtor, item.ident, tps,
+                                            local_def(item.id))) }
+                             else { none }, tps, ast_util::dtor_dec());
+        }
+
         /* Index the class*/
         add_to_index();
         /* Now, make an item for the class itself */
@@ -644,6 +648,14 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         for ifaces.each {|t|
            encode_iface_ref(ebml_w, ecx, t);
         }
+        /* Encode the dtor */
+        /* Encode id for dtor */
+        option::iter(m_dtor) {|dtor|
+            ebml_w.wr_tag(tag_item_dtor) {||
+                encode_def_id(ebml_w, local_def(dtor.node.id));
+            }
+        };
+
         /* Encode def_ids for each field and method
          for methods, write all the stuff get_iface_method
         needs to know*/
@@ -803,9 +815,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
                 encode_info_for_item(ecx, ebml_w, i, index, *pt);
                 /* encode ctor, then encode items */
                 alt i.node {
-                   item_class(tps, _, _, ctor, _, _) {
-                   /* this is assuming that ctors aren't inlined...
-                      probably shouldn't assume that */
+                   item_class(tps, _, _, ctor, m_dtor, _) {
                    #debug("encoding info for ctor %s %d", i.ident,
                           ctor.node.id);
                    *index += [{val: ctor.node.id, pos: ebml_w.writer.tell()}];
@@ -813,7 +823,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
                       *pt, if tps.len() > 0u {
                              some(ii_ctor(ctor, i.ident, tps,
                                           local_def(i.id))) }
-                           else { none }, tps, ctor.node.dec)
+                      else { none }, tps, ctor.node.dec);
                   }
                   _ {}
                 }
diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs
index d604505455c..0d6b158a9ae 100644
--- a/src/rustc/middle/astencode.rs
+++ b/src/rustc/middle/astencode.rs
@@ -427,6 +427,12 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item {
                               with ctor.node}
             with ctor}, nm, tps, parent_id)
       }
+      ast::ii_dtor(dtor, nm, tps, parent_id) {
+        let dtor_body = fld.fold_block(dtor.node.body);
+        ast::ii_dtor({node: {body: dtor_body
+                              with dtor.node}
+            with dtor}, nm, tps, parent_id)
+      }
     }
 }
 
@@ -464,6 +470,16 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item)
                               with ctor.node}
             with ctor}, nm, new_params, new_parent)
       }
+      ast::ii_dtor(dtor, nm, tps, parent_id) {
+        let dtor_body = fld.fold_block(dtor.node.body);
+        let new_params = fold::fold_ty_params(tps, fld);
+        let dtor_id = fld.new_id(dtor.node.id);
+        let new_parent = xcx.tr_def_id(parent_id);
+        let new_self = fld.new_id(dtor.node.self_id);
+        ast::ii_dtor({node: {id: dtor_id, self_id: new_self, body: dtor_body}
+                        with dtor},
+          nm, new_params, new_parent)
+      }
      }
 }
 
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index fe4046c3663..2423f04d11f 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -749,6 +749,12 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
       ty::ty_opaque_closure_ptr(ck) {
         closure::make_opaque_cbox_free_glue(bcx, ck, v)
       }
+      ty::ty_class(did,substs) {
+        // Call the dtor if there is one
+        option::map_default(ty::ty_dtor(bcx.tcx(), did), bcx) {|dt_id|
+          trans_class_drop(bcx, v, dt_id, did, substs)
+        }
+      }
       _ { bcx }
     };
     build_return(bcx);
@@ -2287,7 +2293,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
       }
       some(none) { fn_id } // Not inlinable
       none { // Not seen yet
-        alt check csearch::maybe_get_item_ast(
+        alt csearch::maybe_get_item_ast(
             ccx.tcx, fn_id,
             bind astencode::decode_inlined_item(_, _, ccx.maps, _, _)) {
 
@@ -2327,6 +2333,10 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
             trans_item(ccx, *item);
             local_def(my_id)
           }
+          csearch::found_parent(_, _) {
+              ccx.sess.bug("maybe_get_item_ast returned a found_parent \
+               with a non-item parent");
+          }
           csearch::found(ast::ii_method(impl_did, mth)) {
             ccx.external.insert(fn_id, some(mth.id));
             let {bounds: impl_bnds, rp: _, ty: impl_ty} =
@@ -2340,6 +2350,10 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
             }
             local_def(mth.id)
           }
+          csearch::found(ast::ii_dtor(dtor, nm, tps, parent_id)) {
+              ccx.external.insert(fn_id, some(dtor.node.id));
+              local_def(dtor.node.id)
+          }
         }
       }
     }
diff --git a/src/rustc/middle/trans/reachable.rs b/src/rustc/middle/trans/reachable.rs
index 25c60aa2793..2b708467874 100644
--- a/src/rustc/middle/trans/reachable.rs
+++ b/src/rustc/middle/trans/reachable.rs
@@ -9,7 +9,9 @@ import syntax::ast::*;
 import syntax::{visit, ast_util, ast_map};
 import syntax::ast_util::def_id_of_def;
 import syntax::attr;
+import syntax::print::pprust::expr_to_str;
 import std::map::hashmap;
+import driver::session::*;
 
 export map, find_reachable;
 
@@ -58,7 +60,11 @@ fn traverse_export(cx: ctx, exp_id: node_id) {
 
 fn traverse_def_id(cx: ctx, did: def_id) {
     if did.crate != local_crate { ret; }
-    alt cx.tcx.items.get(did.node) {
+    let n = alt cx.tcx.items.find(did.node) {
+        none { ret; } // This can happen for self, for example
+        some(n) { n }
+    };
+    alt n {
       ast_map::node_item(item, _) { traverse_public_item(cx, item); }
       ast_map::node_method(_, impl_id, _) { traverse_def_id(cx, impl_id); }
       ast_map::node_native_item(item, _, _) { cx.rmap.insert(item.id, ()); }
@@ -111,6 +117,10 @@ fn traverse_public_item(cx: ctx, item: @item) {
         cx.rmap.insert(ctor.node.id, ());
         option::iter(m_dtor) {|dtor|
             cx.rmap.insert(dtor.node.id, ());
+            // dtors don't have attrs
+            if tps.len() > 0u {
+                traverse_inline_body(cx, dtor.node.body);
+            }
         }
         for vec::each(items) {|item|
             alt item.node {
@@ -134,7 +144,13 @@ fn traverse_inline_body(cx: ctx, body: blk) {
     fn traverse_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
         alt e.node {
           expr_path(_) {
-            traverse_def_id(cx, def_id_of_def(cx.tcx.def_map.get(e.id)));
+            alt cx.tcx.def_map.find(e.id) {
+                some(d) {
+                  traverse_def_id(cx, def_id_of_def(d));
+                }
+                none      { cx.tcx.sess.span_bug(e.span, #fmt("Unbound node \
+                  id %? while traversing %s", e.id, expr_to_str(e))); }
+            }
           }
           expr_field(_, _, _) {
             alt cx.method_map.find(e.id) {