From afc0030ed3cf2ddaac52b637eeb1e629f8f39800 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 1 Feb 2022 15:37:30 +0800 Subject: [PATCH] rustdoc: Collect traits in scope for foreign inherent impls --- compiler/rustc_metadata/src/rmeta/decoder.rs | 17 +++++++++++++++++ .../src/rmeta/decoder/cstore_impl.rs | 10 ++++++++++ .../passes/collect_intra_doc_links/early.rs | 7 +++++++ .../auxiliary/extern-inherent-impl-dep.rs | 11 +++++++++++ .../rustdoc/intra-doc/extern-inherent-impl.rs | 8 ++++++++ 5 files changed, 53 insertions(+) create mode 100644 src/test/rustdoc/intra-doc/auxiliary/extern-inherent-impl-dep.rs create mode 100644 src/test/rustdoc/intra-doc/extern-inherent-impl.rs diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index fb1c71fb8cdbe..bb729807cad9a 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 + '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 + '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)> + '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 2f8e35648ec2d..a94c4e2f4e0e8 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 + '_ { 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)> + '_ { 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 + '_ { + 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 edd4e9da66d99..e28034b2b0d7a 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 0000000000000..ee4138b6865a0 --- /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 0000000000000..2e41c2214f4fe --- /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;