about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-02-05 18:27:06 +0000
committerbors <bors@rust-lang.org>2022-02-05 18:27:06 +0000
commit88fb06a1f331926bccb448acdb52966fd1ec8a92 (patch)
treeb22d7f3ae052860d29a30ee334f22121234062a0
parent291bf94cfd6456602d67f0e3be109bcd8c125b1a (diff)
parentafc0030ed3cf2ddaac52b637eeb1e629f8f39800 (diff)
downloadrust-88fb06a1f331926bccb448acdb52966fd1ec8a92.tar.gz
rust-88fb06a1f331926bccb448acdb52966fd1ec8a92.zip
Auto merge of #93539 - petrochenkov:doclink, r=camelid,michaelwoerister
rustdoc: Collect traits in scope for foreign inherent impls

Inherent impls can be inlined for variety of reasons (impls of reexported types, impls available through `Deref`, impls inlined for unclear reasons like in https://github.com/rust-lang/rust/pull/88679#issuecomment-1023929480).
If an impl is inlined, then doc links in its comments are resolved and we may need the set of traits that are in scope at that impl's definition point.
So in this PR we simply collect traits in scope for *all* inherent impls from other crates if their `Self` type is public, which is very similar for the strategy for trait impls previously used in https://github.com/rust-lang/rust/pull/88679.

Fixes https://github.com/rust-lang/rust/issues/93476
Fixes https://github.com/rust-lang/rust/pull/88679#issuecomment-1026520300
Fixes https://github.com/rust-lang/rust/pull/88679#issuecomment-1023929480
-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;