Skip to content

Commit 592165f

Browse files
committed
Fix ty::populate_implementations_for_trait_if_necessary to load the trait's impls from all the crates.
1 parent aeb92ba commit 592165f

File tree

5 files changed

+54
-17
lines changed

5 files changed

+54
-17
lines changed

src/librustc/metadata/common.rs

+1
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ pub const tag_item_impl_vtables: usize = 0x7e;
189189

190190
pub const tag_impls: usize = 0x109; // top-level only
191191
pub const tag_impls_impl: usize = 0x7f;
192+
pub const tag_impls_impl_trait_def_id: usize = 0x8d;
192193

193194
pub const tag_items_data_item_inherent_impl: usize = 0x80;
194195
pub const tag_items_data_item_extension_impl: usize = 0x81;

src/librustc/metadata/csearch.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -324,11 +324,12 @@ pub fn each_inherent_implementation_for_type<F>(cstore: &cstore::CStore,
324324

325325
pub fn each_implementation_for_trait<F>(cstore: &cstore::CStore,
326326
def_id: ast::DefId,
327-
callback: F) where
327+
mut callback: F) where
328328
F: FnMut(ast::DefId),
329329
{
330-
let cdata = cstore.get_crate_data(def_id.krate);
331-
decoder::each_implementation_for_trait(&*cdata, def_id.node, callback)
330+
cstore.iter_crate_data(|_, cdata| {
331+
decoder::each_implementation_for_trait(cdata, def_id, &mut callback)
332+
})
332333
}
333334

334335
/// If the given def ID describes an item belonging to a trait (either a

src/librustc/metadata/decoder.rs

+41-9
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,22 @@ pub fn translate_def_id(cdata: Cmd, did: ast::DefId) -> ast::DefId {
13281328
}
13291329
}
13301330

1331+
// Translate a DefId from the current compilation environment to a DefId
1332+
// for an external crate.
1333+
fn reverse_translate_def_id(cdata: Cmd, did: ast::DefId) -> Option<ast::DefId> {
1334+
if did.krate == cdata.cnum {
1335+
return Some(ast::DefId { krate: ast::LOCAL_CRATE, node: did.node });
1336+
}
1337+
1338+
for (&local, &global) in &cdata.cnum_map {
1339+
if global == did.krate {
1340+
return Some(ast::DefId { krate: local, node: did.node });
1341+
}
1342+
}
1343+
1344+
None
1345+
}
1346+
13311347
pub fn each_impl<F>(cdata: Cmd, mut callback: F) where
13321348
F: FnMut(ast::DefId),
13331349
{
@@ -1355,19 +1371,35 @@ pub fn each_inherent_implementation_for_type<F>(cdata: Cmd,
13551371
}
13561372

13571373
pub fn each_implementation_for_trait<F>(cdata: Cmd,
1358-
id: ast::NodeId,
1374+
def_id: ast::DefId,
13591375
mut callback: F) where
13601376
F: FnMut(ast::DefId),
13611377
{
1362-
let item_doc = lookup_item(id, cdata.data());
1378+
if cdata.cnum == def_id.krate {
1379+
let item_doc = lookup_item(def_id.node, cdata.data());
1380+
let _ = reader::tagged_docs(item_doc,
1381+
tag_items_data_item_extension_impl,
1382+
|impl_doc| {
1383+
callback(item_def_id(impl_doc, cdata));
1384+
true
1385+
});
1386+
return;
1387+
}
13631388

1364-
let _ = reader::tagged_docs(item_doc,
1365-
tag_items_data_item_extension_impl,
1366-
|impl_doc| {
1367-
let implementation_def_id = item_def_id(impl_doc, cdata);
1368-
callback(implementation_def_id);
1369-
true
1370-
});
1389+
// Do a reverse lookup beforehand to avoid touching the crate_num
1390+
// hash map in the loop below.
1391+
if let Some(crate_local_did) = reverse_translate_def_id(cdata, def_id) {
1392+
let def_id_u64 = def_to_u64(crate_local_did);
1393+
1394+
let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls);
1395+
let _ = reader::tagged_docs(impls_doc, tag_impls_impl, |impl_doc| {
1396+
let impl_trait = reader::get_doc(impl_doc, tag_impls_impl_trait_def_id);
1397+
if reader::doc_as_u64(impl_trait) == def_id_u64 {
1398+
callback(item_def_id(impl_doc, cdata));
1399+
}
1400+
true
1401+
});
1402+
}
13711403
}
13721404

13731405
pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)

src/librustc/metadata/encoder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1895,6 +1895,7 @@ impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
18951895
def_id.krate != ast::LOCAL_CRATE {
18961896
self.rbml_w.start_tag(tag_impls_impl);
18971897
encode_def_id(self.rbml_w, local_def(item.id));
1898+
self.rbml_w.wr_tagged_u64(tag_impls_impl_trait_def_id, def_to_u64(def_id));
18981899
self.rbml_w.end_tag();
18991900
}
19001901
}

src/librustc/middle/ty.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -2564,9 +2564,11 @@ impl<'tcx> TraitDef<'tcx> {
25642564
tcx: &ctxt<'tcx>,
25652565
impl_def_id: DefId,
25662566
impl_trait_ref: TraitRef<'tcx>) {
2567+
debug!("TraitDef::record_impl for {}, from {}",
2568+
self.repr(tcx), impl_trait_ref.repr(tcx));
2569+
25672570
// We don't want to borrow_mut after we already populated all impls,
25682571
// so check if an impl is present with an immutable borrow first.
2569-
25702572
if let Some(sty) = fast_reject::simplify_type(tcx,
25712573
impl_trait_ref.self_ty(), false) {
25722574
if let Some(is) = self.nonblanket_impls.borrow().get(&sty) {
@@ -6366,18 +6368,18 @@ pub fn populate_inherent_implementations_for_type_if_necessary(tcx: &ctxt,
63666368

63676369
/// Populates the type context with all the implementations for the given
63686370
/// trait if necessary.
6369-
pub fn populate_implementations_for_trait_if_necessary(
6370-
tcx: &ctxt,
6371-
trait_id: ast::DefId) {
6371+
pub fn populate_implementations_for_trait_if_necessary(tcx: &ctxt, trait_id: ast::DefId) {
63726372
if trait_id.krate == LOCAL_CRATE {
63736373
return
63746374
}
63756375

63766376
let def = lookup_trait_def(tcx, trait_id);
63776377
if def.flags.get().intersects(TraitFlags::IMPLS_VALID) {
6378-
return
6378+
return;
63796379
}
63806380

6381+
debug!("populate_implementations_for_trait_if_necessary: searching for {}", def.repr(tcx));
6382+
63816383
if csearch::is_defaulted_trait(&tcx.sess.cstore, trait_id) {
63826384
record_trait_has_default_impl(tcx, trait_id);
63836385
}

0 commit comments

Comments
 (0)