Skip to content

Commit 79f8a7f

Browse files
committed
Properly track and export information about vtables for impls in metadata.
Partially rework how vtables are handled in default method calls. Closes rust-lang#7460.
1 parent 304a5f0 commit 79f8a7f

File tree

12 files changed

+202
-80
lines changed

12 files changed

+202
-80
lines changed

src/librustc/metadata/common.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ pub static tag_misc_info: uint = 0x7f;
180180
pub static tag_misc_info_crate_items: uint = 0x80;
181181

182182
pub static tag_item_method_provided_source: uint = 0x81;
183+
pub static tag_item_impl_vtables: uint = 0x82;
183184

184185
pub struct LinkMeta {
185186
name: @str,

src/librustc/metadata/csearch.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use metadata::cstore;
1616
use metadata::decoder;
1717
use metadata;
1818
use middle::ty;
19+
use middle::typeck;
1920

2021
use std::vec;
2122
use reader = extra::ebml::reader;
@@ -216,6 +217,14 @@ pub fn get_impl_trait(tcx: ty::ctxt,
216217
decoder::get_impl_trait(cdata, def.node, tcx)
217218
}
218219

220+
// Given a def_id for an impl, return information about its vtables
221+
pub fn get_impl_vtables(tcx: ty::ctxt,
222+
def: ast::def_id) -> typeck::impl_res {
223+
let cstore = tcx.cstore;
224+
let cdata = cstore::get_crate_data(cstore, def.crate);
225+
decoder::get_impl_vtables(cdata, def.node, tcx)
226+
}
227+
219228
pub fn get_impl_method(cstore: @mut cstore::CStore,
220229
def: ast::def_id,
221230
mname: ast::ident)

src/librustc/metadata/decoder.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ use metadata::tydecode::{parse_ty_data, parse_def_id,
2121
parse_type_param_def_data,
2222
parse_bare_fn_ty_data, parse_trait_ref_data};
2323
use middle::ty;
24+
use middle::typeck;
25+
use middle::astencode::vtable_decoder_helpers;
26+
2427

2528
use std::hash::HashUtil;
2629
use std::int;
@@ -410,6 +413,21 @@ pub fn get_impl_trait(cdata: cmd,
410413
}
411414
}
412415

416+
pub fn get_impl_vtables(cdata: cmd,
417+
id: ast::node_id,
418+
tcx: ty::ctxt) -> typeck::impl_res
419+
{
420+
let item_doc = lookup_item(id, cdata.data);
421+
let vtables_doc = reader::get_doc(item_doc, tag_item_impl_vtables);
422+
let mut decoder = reader::Decoder(vtables_doc);
423+
424+
typeck::impl_res {
425+
trait_vtables: decoder.read_vtable_res(tcx, cdata),
426+
self_vtables: decoder.read_vtable_param_res(tcx, cdata)
427+
}
428+
}
429+
430+
413431
pub fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
414432
name: ast::ident) -> Option<ast::def_id> {
415433
let items = reader::get_doc(reader::Doc(cdata.data), tag_items);

src/librustc/metadata/encoder.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use metadata::decoder;
1717
use metadata::tyencode;
1818
use middle::ty::{node_id_to_type, lookup_item_type};
1919
use middle::ty;
20+
use middle::typeck;
21+
use middle::astencode;
2022
use middle;
2123

2224
use std::hash::HashUtil;
@@ -162,6 +164,15 @@ fn encode_trait_ref(ebml_w: &mut writer::Encoder,
162164
ebml_w.end_tag();
163165
}
164166

167+
fn encode_impl_vtables(ebml_w: &mut writer::Encoder,
168+
ecx: &EncodeContext,
169+
vtables: &typeck::impl_res) {
170+
ebml_w.start_tag(tag_item_impl_vtables);
171+
astencode::encode_vtable_res(ecx, ebml_w, vtables.trait_vtables);
172+
astencode::encode_vtable_param_res(ecx, ebml_w, vtables.self_vtables);
173+
ebml_w.end_tag();
174+
}
175+
165176
// Item info table encoding
166177
fn encode_family(ebml_w: &mut writer::Encoder, c: char) {
167178
ebml_w.start_tag(tag_items_data_item_family);
@@ -1009,6 +1020,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
10091020
let trait_ref = ty::node_id_to_trait_ref(
10101021
tcx, ast_trait_ref.ref_id);
10111022
encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
1023+
let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1024+
encode_impl_vtables(ebml_w, ecx, &impl_vtables);
10121025
}
10131026
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
10141027
ebml_w.end_tag();

src/librustc/middle/astencode.rs

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,21 @@ impl<S:serialize::Encoder> def_id_encoder_helpers for S {
250250

251251
trait def_id_decoder_helpers {
252252
fn read_def_id(&mut self, xcx: @ExtendedDecodeContext) -> ast::def_id;
253+
fn read_def_id_noxcx(&mut self,
254+
cdata: @cstore::crate_metadata) -> ast::def_id;
253255
}
254256

255257
impl<D:serialize::Decoder> def_id_decoder_helpers for D {
256258
fn read_def_id(&mut self, xcx: @ExtendedDecodeContext) -> ast::def_id {
257259
let did: ast::def_id = Decodable::decode(self);
258260
did.tr(xcx)
259261
}
262+
263+
fn read_def_id_noxcx(&mut self,
264+
cdata: @cstore::crate_metadata) -> ast::def_id {
265+
let did: ast::def_id = Decodable::decode(self);
266+
decoder::translate_def_id(cdata, did)
267+
}
260268
}
261269

262270
// ______________________________________________________________________
@@ -595,21 +603,28 @@ impl tr for method_origin {
595603
// ______________________________________________________________________
596604
// Encoding and decoding vtable_res
597605

598-
fn encode_vtable_res(ecx: &e::EncodeContext,
606+
pub fn encode_vtable_res(ecx: &e::EncodeContext,
599607
ebml_w: &mut writer::Encoder,
600608
dr: typeck::vtable_res) {
601609
// can't autogenerate this code because automatic code of
602610
// ty::t doesn't work, and there is no way (atm) to have
603611
// hand-written encoding routines combine with auto-generated
604612
// ones. perhaps we should fix this.
605613
do ebml_w.emit_from_vec(*dr) |ebml_w, param_tables| {
606-
do ebml_w.emit_from_vec(**param_tables) |ebml_w, vtable_origin| {
607-
encode_vtable_origin(ecx, ebml_w, vtable_origin)
608-
}
614+
encode_vtable_param_res(ecx, ebml_w, *param_tables);
609615
}
610616
}
611617

612-
fn encode_vtable_origin(ecx: &e::EncodeContext,
618+
pub fn encode_vtable_param_res(ecx: &e::EncodeContext,
619+
ebml_w: &mut writer::Encoder,
620+
param_tables: typeck::vtable_param_res) {
621+
do ebml_w.emit_from_vec(*param_tables) |ebml_w, vtable_origin| {
622+
encode_vtable_origin(ecx, ebml_w, vtable_origin)
623+
}
624+
}
625+
626+
627+
pub fn encode_vtable_origin(ecx: &e::EncodeContext,
613628
ebml_w: &mut writer::Encoder,
614629
vtable_origin: &typeck::vtable_origin) {
615630
do ebml_w.emit_enum("vtable_origin") |ebml_w| {
@@ -648,22 +663,35 @@ fn encode_vtable_origin(ecx: &e::EncodeContext,
648663
}
649664
}
650665

651-
trait vtable_decoder_helpers {
652-
fn read_vtable_res(&mut self, xcx: @ExtendedDecodeContext)
666+
pub trait vtable_decoder_helpers {
667+
fn read_vtable_res(&mut self,
668+
tcx: ty::ctxt, cdata: @cstore::crate_metadata)
653669
-> typeck::vtable_res;
654-
fn read_vtable_origin(&mut self, xcx: @ExtendedDecodeContext)
670+
fn read_vtable_param_res(&mut self,
671+
tcx: ty::ctxt, cdata: @cstore::crate_metadata)
672+
-> typeck::vtable_param_res;
673+
fn read_vtable_origin(&mut self,
674+
tcx: ty::ctxt, cdata: @cstore::crate_metadata)
655675
-> typeck::vtable_origin;
656676
}
657677

658678
impl vtable_decoder_helpers for reader::Decoder {
659-
fn read_vtable_res(&mut self, xcx: @ExtendedDecodeContext)
679+
fn read_vtable_res(&mut self,
680+
tcx: ty::ctxt, cdata: @cstore::crate_metadata)
660681
-> typeck::vtable_res {
661682
@self.read_to_vec(|this|
662-
@this.read_to_vec(|this|
663-
this.read_vtable_origin(xcx)))
683+
this.read_vtable_param_res(tcx, cdata))
664684
}
665685

666-
fn read_vtable_origin(&mut self, xcx: @ExtendedDecodeContext)
686+
fn read_vtable_param_res(&mut self,
687+
tcx: ty::ctxt, cdata: @cstore::crate_metadata)
688+
-> typeck::vtable_param_res {
689+
@self.read_to_vec(|this|
690+
this.read_vtable_origin(tcx, cdata))
691+
}
692+
693+
fn read_vtable_origin(&mut self,
694+
tcx: ty::ctxt, cdata: @cstore::crate_metadata)
667695
-> typeck::vtable_origin {
668696
do self.read_enum("vtable_origin") |this| {
669697
do this.read_enum_variant(["vtable_static",
@@ -674,13 +702,13 @@ impl vtable_decoder_helpers for reader::Decoder {
674702
0 => {
675703
typeck::vtable_static(
676704
do this.read_enum_variant_arg(0u) |this| {
677-
this.read_def_id(xcx)
705+
this.read_def_id_noxcx(cdata)
678706
},
679707
do this.read_enum_variant_arg(1u) |this| {
680-
this.read_tys(xcx)
708+
this.read_tys_noxcx(tcx, cdata)
681709
},
682710
do this.read_enum_variant_arg(2u) |this| {
683-
this.read_vtable_res(xcx)
711+
this.read_vtable_res(tcx, cdata)
684712
}
685713
)
686714
}
@@ -697,7 +725,7 @@ impl vtable_decoder_helpers for reader::Decoder {
697725
2 => {
698726
typeck::vtable_self(
699727
do this.read_enum_variant_arg(0u) |this| {
700-
this.read_def_id(xcx)
728+
this.read_def_id_noxcx(cdata)
701729
}
702730
)
703731
}
@@ -995,9 +1023,35 @@ trait ebml_decoder_decoder_helpers {
9951023
source: DefIdSource,
9961024
did: ast::def_id)
9971025
-> ast::def_id;
1026+
1027+
// Versions of the type reading functions that don't need the full
1028+
// ExtendedDecodeContext.
1029+
fn read_ty_noxcx(&mut self,
1030+
tcx: ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t;
1031+
fn read_tys_noxcx(&mut self,
1032+
tcx: ty::ctxt,
1033+
cdata: @cstore::crate_metadata) -> ~[ty::t];
9981034
}
9991035

10001036
impl ebml_decoder_decoder_helpers for reader::Decoder {
1037+
fn read_ty_noxcx(&mut self,
1038+
tcx: ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t {
1039+
do self.read_opaque |_, doc| {
1040+
tydecode::parse_ty_data(
1041+
*doc.data,
1042+
cdata.cnum,
1043+
doc.start,
1044+
tcx,
1045+
|_, id| decoder::translate_def_id(cdata, id))
1046+
}
1047+
}
1048+
1049+
fn read_tys_noxcx(&mut self,
1050+
tcx: ty::ctxt,
1051+
cdata: @cstore::crate_metadata) -> ~[ty::t] {
1052+
self.read_to_vec(|this| this.read_ty_noxcx(tcx, cdata) )
1053+
}
1054+
10011055
fn read_ty(&mut self, xcx: @ExtendedDecodeContext) -> ty::t {
10021056
// Note: regions types embed local node ids. In principle, we
10031057
// should translate these node ids into the new decode
@@ -1160,8 +1214,9 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
11601214
val_dsr.read_method_map_entry(xcx));
11611215
}
11621216
c::tag_table_vtable_map => {
1163-
dcx.maps.vtable_map.insert(id,
1164-
val_dsr.read_vtable_res(xcx));
1217+
dcx.maps.vtable_map.insert(
1218+
id,
1219+
val_dsr.read_vtable_res(xcx.dcx.tcx, xcx.dcx.cdata));
11651220
}
11661221
c::tag_table_adjustments => {
11671222
let adj: @ty::AutoAdjustment = @Decodable::decode(val_dsr);

src/librustc/middle/trans/callee.rs

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -193,42 +193,27 @@ pub fn trans_fn_ref_with_vtables_to_callee(
193193
type_params, vtables))}
194194
}
195195

196-
fn get_impl_resolutions(bcx: @mut Block,
197-
impl_id: ast::def_id)
198-
-> typeck::vtable_res {
199-
if impl_id.crate == ast::local_crate {
200-
bcx.ccx().maps.vtable_map.get_copy(&impl_id.node)
201-
} else {
202-
// XXX: This is a temporary hack to work around not properly
203-
// exporting information about resolutions for impls.
204-
// This doesn't actually work if the trait has param bounds,
205-
// but it does allow us to survive the case when it does not.
206-
let trait_ref = ty::impl_trait_ref(bcx.tcx(), impl_id).get();
207-
@vec::from_elem(trait_ref.substs.tps.len(), @~[])
208-
}
209-
}
210-
211196
fn resolve_default_method_vtables(bcx: @mut Block,
212197
impl_id: ast::def_id,
213198
method: &ty::Method,
214199
substs: &ty::substs,
215200
impl_vtables: Option<typeck::vtable_res>)
216-
-> typeck::vtable_res {
201+
-> (typeck::vtable_res, typeck::vtable_param_res) {
217202

218203
// Get the vtables that the impl implements the trait at
219-
let trait_vtables = get_impl_resolutions(bcx, impl_id);
204+
let impl_res = ty::lookup_impl_vtables(bcx.tcx(), impl_id);
220205

221206
// Build up a param_substs that we are going to resolve the
222207
// trait_vtables under.
223208
let param_substs = Some(@param_substs {
224209
tys: substs.tps.clone(),
225210
self_ty: substs.self_ty,
226211
vtables: impl_vtables,
227-
self_vtable: None
212+
self_vtables: None
228213
});
229214

230215
let trait_vtables_fixed = resolve_vtables_under_param_substs(
231-
bcx.tcx(), param_substs, trait_vtables);
216+
bcx.tcx(), param_substs, impl_res.trait_vtables);
232217

233218
// Now we pull any vtables for parameters on the actual method.
234219
let num_method_vtables = method.generics.type_param_defs.len();
@@ -241,7 +226,12 @@ fn resolve_default_method_vtables(bcx: @mut Block,
241226
None => vec::from_elem(num_method_vtables, @~[])
242227
};
243228

244-
@(*trait_vtables_fixed + method_vtables)
229+
let param_vtables = @(*trait_vtables_fixed + method_vtables);
230+
231+
let self_vtables = resolve_param_vtables_under_param_substs(
232+
bcx.tcx(), param_substs, impl_res.self_vtables);
233+
234+
(param_vtables, self_vtables)
245235
}
246236

247237

@@ -296,7 +286,7 @@ pub fn trans_fn_ref_with_vtables(
296286
// We need to do a bunch of special handling for default methods.
297287
// We need to modify the def_id and our substs in order to monomorphize
298288
// the function.
299-
let (is_default, def_id, substs, self_vtable, vtables) =
289+
let (is_default, def_id, substs, self_vtables, vtables) =
300290
match ty::provided_source(tcx, def_id) {
301291
None => (false, def_id, substs, None, vtables),
302292
Some(source_id) => {
@@ -319,20 +309,6 @@ pub fn trans_fn_ref_with_vtables(
319309
.expect("could not find trait_ref for impl with \
320310
default methods");
321311

322-
// Get all of the type params for the receiver
323-
let param_defs = method.generics.type_param_defs;
324-
let receiver_substs =
325-
type_params.initn(param_defs.len()).to_owned();
326-
let receiver_vtables = match vtables {
327-
None => @~[],
328-
Some(call_vtables) => {
329-
@call_vtables.initn(param_defs.len()).to_owned()
330-
}
331-
};
332-
333-
let self_vtable =
334-
typeck::vtable_static(impl_id, receiver_substs,
335-
receiver_vtables);
336312
// Compute the first substitution
337313
let first_subst = make_substs_for_receiver_types(
338314
tcx, impl_id, trait_ref, method);
@@ -341,20 +317,22 @@ pub fn trans_fn_ref_with_vtables(
341317
let new_substs = first_subst.subst(tcx, &substs);
342318

343319

344-
let vtables =
320+
let (param_vtables, self_vtables) =
345321
resolve_default_method_vtables(bcx, impl_id,
346322
method, &substs, vtables);
347323

348324
debug!("trans_fn_with_vtables - default method: \
349325
substs = %s, trait_subst = %s, \
350326
first_subst = %s, new_subst = %s, \
351-
self_vtable = %s, vtables = %s",
327+
vtables = %s, \
328+
self_vtable = %s, param_vtables = %s",
352329
substs.repr(tcx), trait_ref.substs.repr(tcx),
353330
first_subst.repr(tcx), new_substs.repr(tcx),
354-
self_vtable.repr(tcx), vtables.repr(tcx));
331+
vtables.repr(tcx),
332+
self_vtables.repr(tcx), param_vtables.repr(tcx));
355333

356334
(true, source_id,
357-
new_substs, Some(self_vtable), Some(vtables))
335+
new_substs, Some(self_vtables), Some(param_vtables))
358336
}
359337
};
360338

@@ -400,7 +378,7 @@ pub fn trans_fn_ref_with_vtables(
400378

401379
let (val, must_cast) =
402380
monomorphize::monomorphic_fn(ccx, def_id, &substs,
403-
vtables, self_vtable,
381+
vtables, self_vtables,
404382
Some(ref_id));
405383
let mut val = val;
406384
if must_cast && ref_id != 0 {

0 commit comments

Comments
 (0)