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_item(@item),
ii_method(def_id /* impl id */, @method), ii_method(def_id /* impl id */, @method),
ii_native(@native_item), 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 // don't decode and instantiate the impl, but just the method, we have to
// add it to the table now: // add it to the table now:
alt ii { alt ii {
ii_item(_) | ii_ctor(_,_,_,_) { /* fallthrough */ } ii_item(*) | ii_ctor(*) | ii_dtor(*) { /* fallthrough */ }
ii_native(i) { ii_native(i) {
cx.map.insert(i.id, node_native_item(i, native_abi_rust_intrinsic, cx.map.insert(i.id, node_native_item(i, native_abi_rust_intrinsic,
@path)); @path));

View file

@ -320,6 +320,7 @@ impl inlined_item_methods for inlined_item {
ii_native(i) { /* FIXME: bad */ copy i.ident } ii_native(i) { /* FIXME: bad */ copy i.ident }
ii_method(_, m) { /* FIXME: bad */ copy m.ident } ii_method(_, m) { /* FIXME: bad */ copy m.ident }
ii_ctor(_, nm, _, _) { /* FIXME: bad */ copy nm } 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_native(i) { i.id }
ii_method(_, m) { m.id } ii_method(_, m) { m.id }
ii_ctor(ctor, _, _, _) { ctor.node.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) { ii_ctor(ctor, nm, tps, parent_id) {
visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v); 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> { 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 items = ebml::get_doc(ebml::doc(cdata.data), tag_items);
let mut found = none;
let cls_items = alt maybe_find_item(id, items) { let cls_items = alt maybe_find_item(id, items) {
some(it) { it } some(it) { it }
none { ret none; }}; none { fail (#fmt("class_dtor: class id not found \
let mut rslt = none; when looking up dtor for %d", id)); }
ebml::tagged_docs(cls_items, tag_item_dtor) {|f| };
let did = parse_def_id(ebml::doc_data(f)); ebml::tagged_docs(cls_items, tag_item_dtor) {|doc|
rslt = some(translate_def_id(cdata, did)); let doc1 = ebml::get_doc(doc, tag_def_id);
} let did = parse_def_id(ebml::doc_data(doc1));
rslt found = some(translate_def_id(cdata, did));
};
found
} }
fn get_symbol(data: @[u8], id: ast::node_id) -> str { fn get_symbol(data: @[u8], id: ast::node_id) -> str {

View file

@ -9,7 +9,7 @@ import ebml::writer;
import syntax::ast::*; import syntax::ast::*;
import syntax::print::pprust; import syntax::print::pprust;
import syntax::{ast_util, visit}; import syntax::{ast_util, visit};
import syntax::ast_util::local_def; import syntax::ast_util::*;
import common::*; import common::*;
import middle::ty; import middle::ty;
import middle::ty::node_id_to_type; 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); add_to_index(ebml_w, path, index, it.ident);
encode_named_def_id(ebml_w, it.ident, encode_named_def_id(ebml_w, it.ident,
local_def(ctor.node.id)); 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], encode_class_item_paths(ebml_w, items, path + [it.ident],
index); 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_family(ebml_w, purity_fn_family(decl.purity));
encode_type_param_bounds(ebml_w, ecx, tps); encode_type_param_bounds(ebml_w, ecx, tps);
let its_ty = node_id_to_type(ecx.tcx, id); let its_ty = node_id_to_type(ecx.tcx, id);
#debug("fn name = %s ty = %s", ident, #debug("fn name = %s ty = %s its node id = %d", ident,
util::ppaux::ty_to_str(ecx.tcx, its_ty)); util::ppaux::ty_to_str(ecx.tcx, its_ty), id);
encode_type(ecx, ebml_w, its_ty); encode_type(ecx, ebml_w, its_ty);
encode_path(ebml_w, path, ast_map::path_name(ident)); encode_path(ebml_w, path, ast_map::path_name(ident));
alt item { 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, encode_enum_variant_info(ecx, ebml_w, item.id, variants,
path, index, tps); 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 /* First, encode the fields and methods
These come first because we need to write them to make These come first because we need to write them to make
the index, and the index needs to be in the item for the the index, and the index needs to be in the item for the
class itself */ class itself */
let idx = encode_info_for_class(ecx, ebml_w, item.id, path, tps, let idx = encode_info_for_class(ecx, ebml_w, item.id, path, tps,
items, index); 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*/ /* Index the class*/
add_to_index(); add_to_index();
/* Now, make an item for the class itself */ /* 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| for ifaces.each {|t|
encode_iface_ref(ebml_w, ecx, 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 /* Encode def_ids for each field and method
for methods, write all the stuff get_iface_method for methods, write all the stuff get_iface_method
needs to know*/ 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_info_for_item(ecx, ebml_w, i, index, *pt);
/* encode ctor, then encode items */ /* encode ctor, then encode items */
alt i.node { alt i.node {
item_class(tps, _, _, ctor, _, _) { item_class(tps, _, _, ctor, m_dtor, _) {
/* this is assuming that ctors aren't inlined...
probably shouldn't assume that */
#debug("encoding info for ctor %s %d", i.ident, #debug("encoding info for ctor %s %d", i.ident,
ctor.node.id); ctor.node.id);
*index += [{val: ctor.node.id, pos: ebml_w.writer.tell()}]; *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 { *pt, if tps.len() > 0u {
some(ii_ctor(ctor, i.ident, tps, some(ii_ctor(ctor, i.ident, tps,
local_def(i.id))) } 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.node}
with ctor}, nm, tps, parent_id) 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.node}
with ctor}, nm, new_params, new_parent) 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) { ty::ty_opaque_closure_ptr(ck) {
closure::make_opaque_cbox_free_glue(bcx, ck, v) 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 } _ { bcx }
}; };
build_return(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 some(none) { fn_id } // Not inlinable
none { // Not seen yet none { // Not seen yet
alt check csearch::maybe_get_item_ast( alt csearch::maybe_get_item_ast(
ccx.tcx, fn_id, ccx.tcx, fn_id,
bind astencode::decode_inlined_item(_, _, ccx.maps, _, _)) { 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); trans_item(ccx, *item);
local_def(my_id) 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)) { csearch::found(ast::ii_method(impl_did, mth)) {
ccx.external.insert(fn_id, some(mth.id)); ccx.external.insert(fn_id, some(mth.id));
let {bounds: impl_bnds, rp: _, ty: impl_ty} = 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) 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::{visit, ast_util, ast_map};
import syntax::ast_util::def_id_of_def; import syntax::ast_util::def_id_of_def;
import syntax::attr; import syntax::attr;
import syntax::print::pprust::expr_to_str;
import std::map::hashmap; import std::map::hashmap;
import driver::session::*;
export map, find_reachable; 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) { fn traverse_def_id(cx: ctx, did: def_id) {
if did.crate != local_crate { ret; } 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_item(item, _) { traverse_public_item(cx, item); }
ast_map::node_method(_, impl_id, _) { traverse_def_id(cx, impl_id); } ast_map::node_method(_, impl_id, _) { traverse_def_id(cx, impl_id); }
ast_map::node_native_item(item, _, _) { cx.rmap.insert(item.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, ()); cx.rmap.insert(ctor.node.id, ());
option::iter(m_dtor) {|dtor| option::iter(m_dtor) {|dtor|
cx.rmap.insert(dtor.node.id, ()); 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| for vec::each(items) {|item|
alt item.node { 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>) { fn traverse_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
alt e.node { alt e.node {
expr_path(_) { 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(_, _, _) { expr_field(_, _, _) {
alt cx.method_map.find(e.id) { alt cx.method_map.find(e.id) {