Handle class destructors correctly in metadata

This allows destructors to be inlined, which is necessary since
classes can have both ty params and destructors.
This commit is contained in:
Tim Chevalier 2012-06-12 16:25:09 -07:00
parent e9fc19c3c2
commit aa9d2d88d3
8 changed files with 91 additions and 26 deletions

View file

@ -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 */)
}
//

View file

@ -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));

View file

@ -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);
}
}
}
}

View file

@ -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 {

View file

@ -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);
}
_ {}
}

View file

@ -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)
}
}
}

View file

@ -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)
}
}
}
}

View file

@ -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) {