about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2022-02-01 15:37:30 +0800
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2022-02-04 22:26:33 +0800
commitafc0030ed3cf2ddaac52b637eeb1e629f8f39800 (patch)
treeb045142e1442b541536c4247d698f25288665691
parent4e8fb743ccbec27344b2dd42de7057f41d4ebfdd (diff)
rustdoc: Collect traits in scope for foreign inherent impls
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs17
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs10
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links/early.rs7
-rw-r--r--src/test/rustdoc/intra-doc/auxiliary/extern-inherent-impl-dep.rs11
-rw-r--r--src/test/rustdoc/intra-doc/extern-inherent-impl.rs8
5 files changed, 53 insertions, 0 deletions
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index fb1c71fb8cd..bb729807cad 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1369,10 +1369,27 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         )
     }
 
+    /// Decodes all inherent impls in the crate (for rustdoc).
+    fn get_inherent_impls(self) -> impl Iterator<Item = (DefId, DefId)> + 'a {
+        (0..self.root.tables.inherent_impls.size()).flat_map(move |i| {
+            let ty_index = DefIndex::from_usize(i);
+            let ty_def_id = self.local_def_id(ty_index);
+            self.root
+                .tables
+                .inherent_impls
+                .get(self, ty_index)
+                .unwrap_or_else(Lazy::empty)
+                .decode(self)
+                .map(move |impl_index| (ty_def_id, self.local_def_id(impl_index)))
+        })
+    }
+
+    /// Decodes all traits in the crate (for rustdoc and rustc diagnostics).
     fn get_traits(self) -> impl Iterator<Item = DefId> + 'a {
         self.root.traits.decode(self).map(move |index| self.local_def_id(index))
     }
 
+    /// Decodes all trait impls in the crate (for rustdoc).
     fn get_trait_impls(self) -> impl Iterator<Item = (DefId, DefId, Option<SimplifiedType>)> + 'a {
         self.cdata.trait_impls.iter().flat_map(move |((trait_cnum_raw, trait_index), impls)| {
             let trait_def_id = DefId {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 2f8e35648ec..a94c4e2f4e0 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -486,16 +486,26 @@ impl CStore {
         self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess)
     }
 
+    /// Decodes all traits in the crate (for rustdoc).
     pub fn traits_in_crate_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ {
         self.get_crate_data(cnum).get_traits()
     }
 
+    /// Decodes all trait impls in the crate (for rustdoc).
     pub fn trait_impls_in_crate_untracked(
         &self,
         cnum: CrateNum,
     ) -> impl Iterator<Item = (DefId, DefId, Option<SimplifiedType>)> + '_ {
         self.get_crate_data(cnum).get_trait_impls()
     }
+
+    /// Decodes all inherent impls in the crate (for rustdoc).
+    pub fn inherent_impls_in_crate_untracked(
+        &self,
+        cnum: CrateNum,
+    ) -> impl Iterator<Item = (DefId, DefId)> + '_ {
+        self.get_crate_data(cnum).get_inherent_impls()
+    }
 }
 
 impl CrateStore for CStore {
diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs
index edd4e9da66d..e28034b2b0d 100644
--- a/src/librustdoc/passes/collect_intra_doc_links/early.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs
@@ -116,6 +116,8 @@ impl IntraLinkCrateLoader<'_, '_> {
             let all_traits = Vec::from_iter(self.resolver.cstore().traits_in_crate_untracked(cnum));
             let all_trait_impls =
                 Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum));
+            let all_inherent_impls =
+                Vec::from_iter(self.resolver.cstore().inherent_impls_in_crate_untracked(cnum));
 
             // Querying traits in scope is expensive so we try to prune the impl and traits lists
             // using privacy, private traits and impls from other crates are never documented in
@@ -134,6 +136,11 @@ impl IntraLinkCrateLoader<'_, '_> {
                     self.add_traits_in_parent_scope(impl_def_id);
                 }
             }
+            for (ty_def_id, impl_def_id) in all_inherent_impls {
+                if self.resolver.cstore().visibility_untracked(ty_def_id) == Visibility::Public {
+                    self.add_traits_in_parent_scope(impl_def_id);
+                }
+            }
 
             self.all_traits.extend(all_traits);
             self.all_trait_impls.extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id));
diff --git a/src/test/rustdoc/intra-doc/auxiliary/extern-inherent-impl-dep.rs b/src/test/rustdoc/intra-doc/auxiliary/extern-inherent-impl-dep.rs
new file mode 100644
index 00000000000..ee4138b6865
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/auxiliary/extern-inherent-impl-dep.rs
@@ -0,0 +1,11 @@
+#[derive(Clone)]
+pub struct PublicStruct;
+
+mod inner {
+    use super::PublicStruct;
+
+    impl PublicStruct {
+        /// [PublicStruct::clone]
+        pub fn method() {}
+    }
+}
diff --git a/src/test/rustdoc/intra-doc/extern-inherent-impl.rs b/src/test/rustdoc/intra-doc/extern-inherent-impl.rs
new file mode 100644
index 00000000000..2e41c2214f4
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/extern-inherent-impl.rs
@@ -0,0 +1,8 @@
+// Reexport of a structure with public inherent impls having doc links in their comments. The doc
+// link points to an associated item, so we check that traits in scope for that link are populated.
+
+// aux-build:extern-inherent-impl-dep.rs
+
+extern crate extern_inherent_impl_dep;
+
+pub use extern_inherent_impl_dep::PublicStruct;