Skip to content

Commit 6c37e3b

Browse files
committed
librustc: Implement basic lazy implementation loading.
This is only for implementations defined in the same crate as the trait they implement.
1 parent ff7b8d6 commit 6c37e3b

File tree

12 files changed

+384
-79
lines changed

12 files changed

+384
-79
lines changed

src/librustc/metadata/common.rs

+3
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ pub static tag_item_impl_vtables: uint = 0x82;
185185
pub static tag_impls: uint = 0x83;
186186
pub static tag_impls_impl: uint = 0x84;
187187

188+
pub static tag_items_data_item_inherent_impl: uint = 0x85;
189+
pub static tag_items_data_item_extension_impl: uint = 0x86;
190+
188191
pub struct LinkMeta {
189192
name: @str,
190193
vers: @str,

src/librustc/metadata/csearch.rs

+25
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,28 @@ pub fn each_impl(cstore: @mut cstore::CStore,
272272
decoder::each_impl(cdata, callback)
273273
}
274274

275+
pub fn each_implementation_for_type(cstore: @mut cstore::CStore,
276+
def_id: ast::def_id,
277+
callback: &fn(ast::def_id)) {
278+
let cdata = cstore::get_crate_data(cstore, def_id.crate);
279+
decoder::each_implementation_for_type(cdata, def_id.node, callback)
280+
}
281+
282+
pub fn each_implementation_for_trait(cstore: @mut cstore::CStore,
283+
def_id: ast::def_id,
284+
callback: &fn(ast::def_id)) {
285+
let cdata = cstore::get_crate_data(cstore, def_id.crate);
286+
decoder::each_implementation_for_trait(cdata, def_id.node, callback)
287+
}
288+
289+
/// If the given def ID describes a method belonging to a trait (either a
290+
/// default method or an implementation of a trait method), returns the ID of
291+
/// the trait that the method belongs to. Otherwise, returns `None`.
292+
pub fn get_trait_of_method(cstore: @mut cstore::CStore,
293+
def_id: ast::def_id,
294+
tcx: ty::ctxt)
295+
-> Option<ast::def_id> {
296+
let cdata = cstore::get_crate_data(cstore, def_id.crate);
297+
decoder::get_trait_of_method(cdata, def_id.node, tcx)
298+
}
299+

src/librustc/metadata/decoder.rs

+61-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use metadata::decoder;
2020
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};
23+
use middle::ty::{ImplContainer, TraitContainer};
2324
use middle::ty;
2425
use middle::typeck;
2526
use middle::astencode::vtable_decoder_helpers;
@@ -958,8 +959,15 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::NodeId,
958959
{
959960
let method_doc = lookup_item(id, cdata.data);
960961
let def_id = item_def_id(method_doc, cdata);
962+
961963
let container_id = item_reqd_and_translated_parent_item(cdata.cnum,
962964
method_doc);
965+
let container_doc = lookup_item(container_id.node, cdata.data);
966+
let container = match item_family(container_doc) {
967+
Trait => TraitContainer(container_id),
968+
_ => ImplContainer(container_id),
969+
};
970+
963971
let name = item_name(intr, method_doc);
964972
let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
965973
tag_item_method_tps);
@@ -980,7 +988,7 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::NodeId,
980988
explicit_self,
981989
vis,
982990
def_id,
983-
container_id,
991+
container,
984992
provided_source
985993
)
986994
}
@@ -1391,4 +1399,56 @@ pub fn each_impl(cdata: cmd, callback: &fn(ast::def_id)) {
13911399
};
13921400
}
13931401

1402+
pub fn each_implementation_for_type(cdata: cmd,
1403+
id: ast::NodeId,
1404+
callback: &fn(ast::def_id)) {
1405+
let item_doc = lookup_item(id, cdata.data);
1406+
/*println(fmt!(">>> reading inherent impls from %s",
1407+
token::ident_to_str(&item_name(token::get_ident_interner(),
1408+
item_doc))));*/
1409+
do reader::tagged_docs(item_doc, tag_items_data_item_inherent_impl)
1410+
|impl_doc| {
1411+
let implementation_def_id = item_def_id(impl_doc, cdata);
1412+
/*println(fmt!(">>>>> read inherent impl: %d:%d",
1413+
implementation_def_id.crate,
1414+
implementation_def_id.node));*/
1415+
callback(implementation_def_id);
1416+
true
1417+
};
1418+
}
1419+
1420+
pub fn each_implementation_for_trait(cdata: cmd,
1421+
id: ast::NodeId,
1422+
callback: &fn(ast::def_id)) {
1423+
let item_doc = lookup_item(id, cdata.data);
1424+
1425+
let _ = do reader::tagged_docs(item_doc,
1426+
tag_items_data_item_extension_impl)
1427+
|impl_doc| {
1428+
let implementation_def_id = item_def_id(impl_doc, cdata);
1429+
callback(implementation_def_id);
1430+
true
1431+
};
1432+
}
1433+
1434+
pub fn get_trait_of_method(cdata: cmd, id: ast::NodeId, tcx: ty::ctxt)
1435+
-> Option<ast::def_id> {
1436+
let item_doc = lookup_item(id, cdata.data);
1437+
let parent_item_id = match item_parent_item(item_doc) {
1438+
None => return None,
1439+
Some(item_id) => item_id,
1440+
};
1441+
let parent_item_id = translate_def_id(cdata, parent_item_id);
1442+
let parent_item_doc = lookup_item(parent_item_id.node, cdata.data);
1443+
match item_family(parent_item_doc) {
1444+
Trait => Some(item_def_id(parent_item_doc, cdata)),
1445+
Impl => {
1446+
do reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref).map
1447+
|_| {
1448+
item_trait_ref(parent_item_doc, tcx, cdata).def_id
1449+
}
1450+
}
1451+
_ => None
1452+
}
1453+
}
13941454

src/librustc/metadata/encoder.rs

+69-4
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,38 @@ fn should_inline(attrs: &[Attribute]) -> bool {
799799
}
800800
}
801801

802+
// Encodes the inherent implementations of a structure, enumeration, or trait.
803+
fn encode_inherent_implementations(ecx: &EncodeContext,
804+
ebml_w: &mut writer::Encoder,
805+
def_id: def_id) {
806+
match ecx.tcx.inherent_impls.find(&def_id) {
807+
None => {}
808+
Some(&implementations) => {
809+
for implementation in implementations.iter() {
810+
ebml_w.start_tag(tag_items_data_item_inherent_impl);
811+
encode_def_id(ebml_w, implementation.did);
812+
ebml_w.end_tag();
813+
}
814+
}
815+
}
816+
}
817+
818+
// Encodes the implementations of a trait defined in this crate.
819+
fn encode_extension_implementations(ecx: &EncodeContext,
820+
ebml_w: &mut writer::Encoder,
821+
trait_def_id: def_id) {
822+
match ecx.tcx.trait_impls.find(&trait_def_id) {
823+
None => {}
824+
Some(&implementations) => {
825+
for implementation in implementations.iter() {
826+
ebml_w.start_tag(tag_items_data_item_extension_impl);
827+
encode_def_id(ebml_w, implementation.did);
828+
ebml_w.end_tag();
829+
}
830+
}
831+
}
832+
}
833+
802834
fn encode_info_for_item(ecx: &EncodeContext,
803835
ebml_w: &mut writer::Encoder,
804836
item: @item,
@@ -902,6 +934,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
902934
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
903935
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
904936
encode_region_param(ecx, ebml_w, item);
937+
938+
// Encode inherent implementations for this enumeration.
939+
encode_inherent_implementations(ecx, ebml_w, def_id);
940+
905941
ebml_w.end_tag();
906942

907943
encode_enum_variant_info(ecx,
@@ -954,6 +990,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
954990
}
955991
}
956992

993+
// Encode inherent implementations for this structure.
994+
encode_inherent_implementations(ecx, ebml_w, def_id);
995+
957996
/* Each class has its own index -- encode it */
958997
let bkts = create_index(idx);
959998
encode_index(ebml_w, bkts, write_i64);
@@ -1069,6 +1108,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
10691108
let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
10701109
encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
10711110
}
1111+
1112+
// Encode the implementations of this trait.
1113+
encode_extension_implementations(ecx, ebml_w, def_id);
1114+
10721115
ebml_w.end_tag();
10731116

10741117
// Now output the method info for each method.
@@ -1130,6 +1173,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
11301173

11311174
ebml_w.end_tag();
11321175
}
1176+
1177+
// Encode inherent implementations for this trait.
1178+
encode_inherent_implementations(ecx, ebml_w, def_id);
11331179
}
11341180
item_mac(*) => fail!("item macros unimplemented")
11351181
}
@@ -1523,17 +1569,36 @@ struct ImplVisitor<'self> {
15231569
impl<'self> Visitor<()> for ImplVisitor<'self> {
15241570
fn visit_item(&mut self, item: @item, _: ()) {
15251571
match item.node {
1526-
item_impl(*) => {
1527-
self.ebml_w.start_tag(tag_impls_impl);
1528-
encode_def_id(self.ebml_w, local_def(item.id));
1529-
self.ebml_w.end_tag();
1572+
item_impl(_, Some(ref trait_ref), _, _) => {
1573+
let def_map = self.ecx.tcx.def_map;
1574+
let trait_def = def_map.get_copy(&trait_ref.ref_id);
1575+
let def_id = ast_util::def_id_of_def(trait_def);
1576+
1577+
// Load eagerly if this is an implementation of the Drop trait
1578+
// or if the trait is not defined in this crate.
1579+
if def_id == self.ecx.tcx.lang_items.drop_trait().unwrap() ||
1580+
def_id.crate != LOCAL_CRATE {
1581+
self.ebml_w.start_tag(tag_impls_impl);
1582+
encode_def_id(self.ebml_w, local_def(item.id));
1583+
self.ebml_w.end_tag();
1584+
}
15301585
}
15311586
_ => {}
15321587
}
15331588
visit::walk_item(self, item, ());
15341589
}
15351590
}
15361591

1592+
/// Encodes implementations that are eagerly loaded.
1593+
///
1594+
/// None of this is necessary in theory; we can load all implementations
1595+
/// lazily. However, in two cases the optimizations to lazily load
1596+
/// implementations are not yet implemented. These two cases, which require us
1597+
/// to load implementations eagerly, are:
1598+
///
1599+
/// * Destructors (implementations of the Drop trait).
1600+
///
1601+
/// * Implementations of traits not defined in this crate.
15371602
fn encode_impls(ecx: &EncodeContext,
15381603
crate: &Crate,
15391604
ebml_w: &mut writer::Encoder) {

src/librustc/middle/privacy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ impl PrivacyVisitor {
225225

226226
if method_id.crate == LOCAL_CRATE {
227227
let is_private = self.method_is_private(span, method_id.node);
228-
let container_id = ty::method(self.tcx, method_id).container_id;
228+
let container_id = ty::method(self.tcx, method_id).container_id();
229229
if is_private &&
230230
(container_id.crate != LOCAL_CRATE ||
231231
!self.privileged_items.iter().any(|x| x == &(container_id.node))) {

src/librustc/middle/trans/callee.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,14 @@ pub fn trans_fn_ref_with_vtables(
283283
self_ty: None,
284284
tps: /*bad*/ type_params.to_owned() };
285285

286+
// Load the info for the appropriate trait if necessary.
287+
match ty::trait_of_method(tcx, def_id) {
288+
None => {}
289+
Some(trait_id) => {
290+
ty::populate_implementations_for_trait_if_necessary(tcx, trait_id)
291+
}
292+
}
293+
286294
// We need to do a bunch of special handling for default methods.
287295
// We need to modify the def_id and our substs in order to monomorphize
288296
// the function.
@@ -303,7 +311,7 @@ pub fn trans_fn_ref_with_vtables(
303311
// So, what we need to do is find this substitution and
304312
// compose it with the one we already have.
305313

306-
let impl_id = ty::method(tcx, def_id).container_id;
314+
let impl_id = ty::method(tcx, def_id).container_id();
307315
let method = ty::method(tcx, source_id);
308316
let trait_ref = ty::impl_trait_ref(tcx, impl_id)
309317
.expect("could not find trait_ref for impl with \

src/librustc/middle/trans/meth.rs

+8
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ pub fn trans_method_callee(bcx: @mut Block,
176176
}) => {
177177
match bcx.fcx.param_substs {
178178
Some(substs) => {
179+
ty::populate_implementations_for_trait_if_necessary(
180+
bcx.tcx(),
181+
trait_id);
182+
179183
let vtbl = find_vtable(bcx.tcx(), substs,
180184
p, b);
181185
trans_monomorphized_callee(bcx, callee_id, this, mentry,
@@ -210,6 +214,8 @@ pub fn trans_static_method_callee(bcx: @mut Block,
210214
callee_id);
211215
let _indenter = indenter();
212216

217+
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trait_id);
218+
213219
// When we translate a static fn defined in a trait like:
214220
//
215221
// trait<T1...Tn> Trait {
@@ -575,6 +581,8 @@ fn emit_vtable_methods(bcx: @mut Block,
575581
make a vtable for a type impl!")
576582
};
577583

584+
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trt_id);
585+
578586
let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
579587
do trait_method_def_ids.map |method_def_id| {
580588
let ident = ty::method(tcx, *method_def_id).ident;

0 commit comments

Comments
 (0)