From 592165fb17fb78e7aa1cfd054ddfdfe9401e92d7 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 12 May 2015 07:56:37 +0300 Subject: [PATCH] Fix ty::populate_implementations_for_trait_if_necessary to load the trait's impls from all the crates. --- src/librustc/metadata/common.rs | 1 + src/librustc/metadata/csearch.rs | 7 +++-- src/librustc/metadata/decoder.rs | 50 ++++++++++++++++++++++++++------ src/librustc/metadata/encoder.rs | 1 + src/librustc/middle/ty.rs | 12 ++++---- 5 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 06a40f1dd27..b6202084296 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -189,6 +189,7 @@ pub enum astencode_tag { // Reserves 0x50 -- 0x6f pub const tag_impls: usize = 0x109; // top-level only pub const tag_impls_impl: usize = 0x7f; +pub const tag_impls_impl_trait_def_id: usize = 0x8d; pub const tag_items_data_item_inherent_impl: usize = 0x80; pub const tag_items_data_item_extension_impl: usize = 0x81; diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 4d59bf5d96a..369d1aeabd4 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -324,11 +324,12 @@ pub fn each_inherent_implementation_for_type(cstore: &cstore::CStore, pub fn each_implementation_for_trait(cstore: &cstore::CStore, def_id: ast::DefId, - callback: F) where + mut callback: F) where F: FnMut(ast::DefId), { - let cdata = cstore.get_crate_data(def_id.krate); - decoder::each_implementation_for_trait(&*cdata, def_id.node, callback) + cstore.iter_crate_data(|_, cdata| { + decoder::each_implementation_for_trait(cdata, def_id, &mut callback) + }) } /// If the given def ID describes an item belonging to a trait (either a diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index c5ef97c75f8..4cb6e748190 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1328,6 +1328,22 @@ pub fn translate_def_id(cdata: Cmd, did: ast::DefId) -> ast::DefId { } } +// Translate a DefId from the current compilation environment to a DefId +// for an external crate. +fn reverse_translate_def_id(cdata: Cmd, did: ast::DefId) -> Option { + if did.krate == cdata.cnum { + return Some(ast::DefId { krate: ast::LOCAL_CRATE, node: did.node }); + } + + for (&local, &global) in &cdata.cnum_map { + if global == did.krate { + return Some(ast::DefId { krate: local, node: did.node }); + } + } + + None +} + pub fn each_impl(cdata: Cmd, mut callback: F) where F: FnMut(ast::DefId), { @@ -1355,19 +1371,35 @@ pub fn each_inherent_implementation_for_type(cdata: Cmd, } pub fn each_implementation_for_trait(cdata: Cmd, - id: ast::NodeId, + def_id: ast::DefId, mut callback: F) where F: FnMut(ast::DefId), { - let item_doc = lookup_item(id, cdata.data()); + if cdata.cnum == def_id.krate { + let item_doc = lookup_item(def_id.node, cdata.data()); + let _ = reader::tagged_docs(item_doc, + tag_items_data_item_extension_impl, + |impl_doc| { + callback(item_def_id(impl_doc, cdata)); + true + }); + return; + } - let _ = reader::tagged_docs(item_doc, - tag_items_data_item_extension_impl, - |impl_doc| { - let implementation_def_id = item_def_id(impl_doc, cdata); - callback(implementation_def_id); - true - }); + // Do a reverse lookup beforehand to avoid touching the crate_num + // hash map in the loop below. + if let Some(crate_local_did) = reverse_translate_def_id(cdata, def_id) { + let def_id_u64 = def_to_u64(crate_local_did); + + let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls); + let _ = reader::tagged_docs(impls_doc, tag_impls_impl, |impl_doc| { + let impl_trait = reader::get_doc(impl_doc, tag_impls_impl_trait_def_id); + if reader::doc_as_u64(impl_trait) == def_id_u64 { + callback(item_def_id(impl_doc, cdata)); + } + true + }); + } } pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index d7d30cada81..afc71f83975 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1895,6 +1895,7 @@ fn visit_item(&mut self, item: &ast::Item) { def_id.krate != ast::LOCAL_CRATE { self.rbml_w.start_tag(tag_impls_impl); encode_def_id(self.rbml_w, local_def(item.id)); + self.rbml_w.wr_tagged_u64(tag_impls_impl_trait_def_id, def_to_u64(def_id)); self.rbml_w.end_tag(); } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 38cd6d91a31..3ec400b35c9 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2564,9 +2564,11 @@ pub fn record_impl(&self, tcx: &ctxt<'tcx>, impl_def_id: DefId, impl_trait_ref: TraitRef<'tcx>) { + debug!("TraitDef::record_impl for {}, from {}", + self.repr(tcx), impl_trait_ref.repr(tcx)); + // We don't want to borrow_mut after we already populated all impls, // so check if an impl is present with an immutable borrow first. - if let Some(sty) = fast_reject::simplify_type(tcx, impl_trait_ref.self_ty(), false) { 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, /// Populates the type context with all the implementations for the given /// trait if necessary. -pub fn populate_implementations_for_trait_if_necessary( - tcx: &ctxt, - trait_id: ast::DefId) { +pub fn populate_implementations_for_trait_if_necessary(tcx: &ctxt, trait_id: ast::DefId) { if trait_id.krate == LOCAL_CRATE { return } let def = lookup_trait_def(tcx, trait_id); if def.flags.get().intersects(TraitFlags::IMPLS_VALID) { - return + return; } + debug!("populate_implementations_for_trait_if_necessary: searching for {}", def.repr(tcx)); + if csearch::is_defaulted_trait(&tcx.sess.cstore, trait_id) { record_trait_has_default_impl(tcx, trait_id); } -- GitLab