Skip to content

Commit aa9d2d8

Browse files
committed
Handle class destructors correctly in metadata
This allows destructors to be inlined, which is necessary since classes can have both ty params and destructors.
1 parent e9fc19c commit aa9d2d8

File tree

8 files changed

+91
-26
lines changed

8 files changed

+91
-26
lines changed

src/libsyntax/ast.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,8 @@ enum inlined_item {
730730
ii_item(@item),
731731
ii_method(def_id /* impl id */, @method),
732732
ii_native(@native_item),
733-
ii_ctor(class_ctor, ident, [ty_param], def_id /* parent id */)
733+
ii_ctor(class_ctor, ident, [ty_param], def_id /* parent id */),
734+
ii_dtor(class_dtor, ident, [ty_param], def_id /* parent id */)
734735
}
735736

736737
//

src/libsyntax/ast_map.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ fn map_decoded_item(diag: span_handler,
106106
// don't decode and instantiate the impl, but just the method, we have to
107107
// add it to the table now:
108108
alt ii {
109-
ii_item(_) | ii_ctor(_,_,_,_) { /* fallthrough */ }
109+
ii_item(*) | ii_ctor(*) | ii_dtor(*) { /* fallthrough */ }
110110
ii_native(i) {
111111
cx.map.insert(i.id, node_native_item(i, native_abi_rust_intrinsic,
112112
@path));

src/libsyntax/ast_util.rs

+5
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ impl inlined_item_methods for inlined_item {
320320
ii_native(i) { /* FIXME: bad */ copy i.ident }
321321
ii_method(_, m) { /* FIXME: bad */ copy m.ident }
322322
ii_ctor(_, nm, _, _) { /* FIXME: bad */ copy nm }
323+
ii_dtor(_, nm, _, _) { /* FIXME: bad */ copy nm }
323324
}
324325
}
325326

@@ -329,6 +330,7 @@ impl inlined_item_methods for inlined_item {
329330
ii_native(i) { i.id }
330331
ii_method(_, m) { m.id }
331332
ii_ctor(ctor, _, _, _) { ctor.node.id }
333+
ii_dtor(dtor, _, _, _) { dtor.node.id }
332334
}
333335
}
334336

@@ -340,6 +342,9 @@ impl inlined_item_methods for inlined_item {
340342
ii_ctor(ctor, nm, tps, parent_id) {
341343
visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v);
342344
}
345+
ii_dtor(dtor, nm, tps, parent_id) {
346+
visit::visit_class_dtor_helper(dtor, tps, parent_id, e, v);
347+
}
343348
}
344349
}
345350
}

src/rustc/metadata/decoder.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -335,15 +335,18 @@ fn get_class_method(cdata: cmd, id: ast::node_id, name: str) -> ast::def_id {
335335

336336
fn class_dtor(cdata: cmd, id: ast::node_id) -> option<ast::def_id> {
337337
let items = ebml::get_doc(ebml::doc(cdata.data), tag_items);
338+
let mut found = none;
338339
let cls_items = alt maybe_find_item(id, items) {
339340
some(it) { it }
340-
none { ret none; }};
341-
let mut rslt = none;
342-
ebml::tagged_docs(cls_items, tag_item_dtor) {|f|
343-
let did = parse_def_id(ebml::doc_data(f));
344-
rslt = some(translate_def_id(cdata, did));
345-
}
346-
rslt
341+
none { fail (#fmt("class_dtor: class id not found \
342+
when looking up dtor for %d", id)); }
343+
};
344+
ebml::tagged_docs(cls_items, tag_item_dtor) {|doc|
345+
let doc1 = ebml::get_doc(doc, tag_def_id);
346+
let did = parse_def_id(ebml::doc_data(doc1));
347+
found = some(translate_def_id(cdata, did));
348+
};
349+
found
347350
}
348351

349352
fn get_symbol(data: @[u8], id: ast::node_id) -> str {

src/rustc/metadata/encoder.rs

+24-14
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import ebml::writer;
99
import syntax::ast::*;
1010
import syntax::print::pprust;
1111
import syntax::{ast_util, visit};
12-
import syntax::ast_util::local_def;
12+
import syntax::ast_util::*;
1313
import common::*;
1414
import middle::ty;
1515
import middle::ty::node_id_to_type;
@@ -206,12 +206,6 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
206206
add_to_index(ebml_w, path, index, it.ident);
207207
encode_named_def_id(ebml_w, it.ident,
208208
local_def(ctor.node.id));
209-
/* Encode id for dtor */
210-
option::iter(m_dtor) {|dtor|
211-
ebml_w.wr_tag(tag_item_dtor) {||
212-
encode_def_id(ebml_w, local_def(dtor.node.id));
213-
}
214-
};
215209
encode_class_item_paths(ebml_w, items, path + [it.ident],
216210
index);
217211
}
@@ -485,8 +479,8 @@ fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer,
485479
encode_family(ebml_w, purity_fn_family(decl.purity));
486480
encode_type_param_bounds(ebml_w, ecx, tps);
487481
let its_ty = node_id_to_type(ecx.tcx, id);
488-
#debug("fn name = %s ty = %s", ident,
489-
util::ppaux::ty_to_str(ecx.tcx, its_ty));
482+
#debug("fn name = %s ty = %s its node id = %d", ident,
483+
util::ppaux::ty_to_str(ecx.tcx, its_ty), id);
490484
encode_type(ecx, ebml_w, its_ty);
491485
encode_path(ebml_w, path, ast_map::path_name(ident));
492486
alt item {
@@ -623,13 +617,23 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
623617
encode_enum_variant_info(ecx, ebml_w, item.id, variants,
624618
path, index, tps);
625619
}
626-
item_class(tps, ifaces, items, ctor, _dtor, rp) {
620+
item_class(tps, ifaces, items, ctor, m_dtor, rp) {
627621
/* First, encode the fields and methods
628622
These come first because we need to write them to make
629623
the index, and the index needs to be in the item for the
630624
class itself */
631625
let idx = encode_info_for_class(ecx, ebml_w, item.id, path, tps,
632626
items, index);
627+
/* Encode the dtor */
628+
option::iter(m_dtor) {|dtor|
629+
*index += [{val: dtor.node.id, pos: ebml_w.writer.tell()}];
630+
encode_info_for_fn(ecx, ebml_w, dtor.node.id, item.ident
631+
+ "_dtor", path, if tps.len() > 0u {
632+
some(ii_dtor(dtor, item.ident, tps,
633+
local_def(item.id))) }
634+
else { none }, tps, ast_util::dtor_dec());
635+
}
636+
633637
/* Index the class*/
634638
add_to_index();
635639
/* 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,
644648
for ifaces.each {|t|
645649
encode_iface_ref(ebml_w, ecx, t);
646650
}
651+
/* Encode the dtor */
652+
/* Encode id for dtor */
653+
option::iter(m_dtor) {|dtor|
654+
ebml_w.wr_tag(tag_item_dtor) {||
655+
encode_def_id(ebml_w, local_def(dtor.node.id));
656+
}
657+
};
658+
647659
/* Encode def_ids for each field and method
648660
for methods, write all the stuff get_iface_method
649661
needs to know*/
@@ -803,17 +815,15 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
803815
encode_info_for_item(ecx, ebml_w, i, index, *pt);
804816
/* encode ctor, then encode items */
805817
alt i.node {
806-
item_class(tps, _, _, ctor, _, _) {
807-
/* this is assuming that ctors aren't inlined...
808-
probably shouldn't assume that */
818+
item_class(tps, _, _, ctor, m_dtor, _) {
809819
#debug("encoding info for ctor %s %d", i.ident,
810820
ctor.node.id);
811821
*index += [{val: ctor.node.id, pos: ebml_w.writer.tell()}];
812822
encode_info_for_fn(ecx, ebml_w, ctor.node.id, i.ident,
813823
*pt, if tps.len() > 0u {
814824
some(ii_ctor(ctor, i.ident, tps,
815825
local_def(i.id))) }
816-
else { none }, tps, ctor.node.dec)
826+
else { none }, tps, ctor.node.dec);
817827
}
818828
_ {}
819829
}

src/rustc/middle/astencode.rs

+16
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,12 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item {
427427
with ctor.node}
428428
with ctor}, nm, tps, parent_id)
429429
}
430+
ast::ii_dtor(dtor, nm, tps, parent_id) {
431+
let dtor_body = fld.fold_block(dtor.node.body);
432+
ast::ii_dtor({node: {body: dtor_body
433+
with dtor.node}
434+
with dtor}, nm, tps, parent_id)
435+
}
430436
}
431437
}
432438

@@ -464,6 +470,16 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item)
464470
with ctor.node}
465471
with ctor}, nm, new_params, new_parent)
466472
}
473+
ast::ii_dtor(dtor, nm, tps, parent_id) {
474+
let dtor_body = fld.fold_block(dtor.node.body);
475+
let new_params = fold::fold_ty_params(tps, fld);
476+
let dtor_id = fld.new_id(dtor.node.id);
477+
let new_parent = xcx.tr_def_id(parent_id);
478+
let new_self = fld.new_id(dtor.node.self_id);
479+
ast::ii_dtor({node: {id: dtor_id, self_id: new_self, body: dtor_body}
480+
with dtor},
481+
nm, new_params, new_parent)
482+
}
467483
}
468484
}
469485

src/rustc/middle/trans/base.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,12 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
749749
ty::ty_opaque_closure_ptr(ck) {
750750
closure::make_opaque_cbox_free_glue(bcx, ck, v)
751751
}
752+
ty::ty_class(did,substs) {
753+
// Call the dtor if there is one
754+
option::map_default(ty::ty_dtor(bcx.tcx(), did), bcx) {|dt_id|
755+
trans_class_drop(bcx, v, dt_id, did, substs)
756+
}
757+
}
752758
_ { bcx }
753759
};
754760
build_return(bcx);
@@ -2287,7 +2293,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
22872293
}
22882294
some(none) { fn_id } // Not inlinable
22892295
none { // Not seen yet
2290-
alt check csearch::maybe_get_item_ast(
2296+
alt csearch::maybe_get_item_ast(
22912297
ccx.tcx, fn_id,
22922298
bind astencode::decode_inlined_item(_, _, ccx.maps, _, _)) {
22932299

@@ -2327,6 +2333,10 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
23272333
trans_item(ccx, *item);
23282334
local_def(my_id)
23292335
}
2336+
csearch::found_parent(_, _) {
2337+
ccx.sess.bug("maybe_get_item_ast returned a found_parent \
2338+
with a non-item parent");
2339+
}
23302340
csearch::found(ast::ii_method(impl_did, mth)) {
23312341
ccx.external.insert(fn_id, some(mth.id));
23322342
let {bounds: impl_bnds, rp: _, ty: impl_ty} =
@@ -2340,6 +2350,10 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
23402350
}
23412351
local_def(mth.id)
23422352
}
2353+
csearch::found(ast::ii_dtor(dtor, nm, tps, parent_id)) {
2354+
ccx.external.insert(fn_id, some(dtor.node.id));
2355+
local_def(dtor.node.id)
2356+
}
23432357
}
23442358
}
23452359
}

src/rustc/middle/trans/reachable.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import syntax::ast::*;
99
import syntax::{visit, ast_util, ast_map};
1010
import syntax::ast_util::def_id_of_def;
1111
import syntax::attr;
12+
import syntax::print::pprust::expr_to_str;
1213
import std::map::hashmap;
14+
import driver::session::*;
1315

1416
export map, find_reachable;
1517

@@ -58,7 +60,11 @@ fn traverse_export(cx: ctx, exp_id: node_id) {
5860

5961
fn traverse_def_id(cx: ctx, did: def_id) {
6062
if did.crate != local_crate { ret; }
61-
alt cx.tcx.items.get(did.node) {
63+
let n = alt cx.tcx.items.find(did.node) {
64+
none { ret; } // This can happen for self, for example
65+
some(n) { n }
66+
};
67+
alt n {
6268
ast_map::node_item(item, _) { traverse_public_item(cx, item); }
6369
ast_map::node_method(_, impl_id, _) { traverse_def_id(cx, impl_id); }
6470
ast_map::node_native_item(item, _, _) { cx.rmap.insert(item.id, ()); }
@@ -111,6 +117,10 @@ fn traverse_public_item(cx: ctx, item: @item) {
111117
cx.rmap.insert(ctor.node.id, ());
112118
option::iter(m_dtor) {|dtor|
113119
cx.rmap.insert(dtor.node.id, ());
120+
// dtors don't have attrs
121+
if tps.len() > 0u {
122+
traverse_inline_body(cx, dtor.node.body);
123+
}
114124
}
115125
for vec::each(items) {|item|
116126
alt item.node {
@@ -134,7 +144,13 @@ fn traverse_inline_body(cx: ctx, body: blk) {
134144
fn traverse_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
135145
alt e.node {
136146
expr_path(_) {
137-
traverse_def_id(cx, def_id_of_def(cx.tcx.def_map.get(e.id)));
147+
alt cx.tcx.def_map.find(e.id) {
148+
some(d) {
149+
traverse_def_id(cx, def_id_of_def(d));
150+
}
151+
none { cx.tcx.sess.span_bug(e.span, #fmt("Unbound node \
152+
id %? while traversing %s", e.id, expr_to_str(e))); }
153+
}
138154
}
139155
expr_field(_, _, _) {
140156
alt cx.method_map.find(e.id) {

0 commit comments

Comments
 (0)