about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2015-05-12 07:56:37 +0300
committerEduard Burtescu <edy.burt@gmail.com>2015-05-12 07:56:37 +0300
commit592165fb17fb78e7aa1cfd054ddfdfe9401e92d7 (patch)
treec7ff98c4fa7012b52f14a0abf2df87060ff0da30
parentaeb92bab5d63313455e4bfd079ce84712a1a4bac (diff)
downloadrust-592165fb17fb78e7aa1cfd054ddfdfe9401e92d7.tar.gz
rust-592165fb17fb78e7aa1cfd054ddfdfe9401e92d7.zip
Fix ty::populate_implementations_for_trait_if_necessary to load the trait's impls from all the crates.
-rw-r--r--src/librustc/metadata/common.rs1
-rw-r--r--src/librustc/metadata/csearch.rs7
-rw-r--r--src/librustc/metadata/decoder.rs50
-rw-r--r--src/librustc/metadata/encoder.rs1
-rw-r--r--src/librustc/middle/ty.rs12
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 const tag_item_impl_vtables: usize = 0x7e;
 
 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<F>(cstore: &cstore::CStore,
 
 pub fn each_implementation_for_trait<F>(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<ast::DefId> {
+    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<F>(cdata: Cmd, mut callback: F) where
     F: FnMut(ast::DefId),
 {
@@ -1355,19 +1371,35 @@ pub fn each_inherent_implementation_for_type<F>(cdata: Cmd,
 }
 
 pub fn each_implementation_for_trait<F>(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 @@ impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
                     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 @@ impl<'tcx> TraitDef<'tcx> {
                        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);
     }