Skip to content

Commit 88fb06a

Browse files
committed
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 #88679 (comment)). 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 #88679. Fixes #93476 Fixes #88679 (comment) Fixes #88679 (comment)
2 parents 291bf94 + afc0030 commit 88fb06a

File tree

5 files changed

+53
-0
lines changed

5 files changed

+53
-0
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1369,10 +1369,27 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
13691369
)
13701370
}
13711371

1372+
/// Decodes all inherent impls in the crate (for rustdoc).
1373+
fn get_inherent_impls(self) -> impl Iterator<Item = (DefId, DefId)> + 'a {
1374+
(0..self.root.tables.inherent_impls.size()).flat_map(move |i| {
1375+
let ty_index = DefIndex::from_usize(i);
1376+
let ty_def_id = self.local_def_id(ty_index);
1377+
self.root
1378+
.tables
1379+
.inherent_impls
1380+
.get(self, ty_index)
1381+
.unwrap_or_else(Lazy::empty)
1382+
.decode(self)
1383+
.map(move |impl_index| (ty_def_id, self.local_def_id(impl_index)))
1384+
})
1385+
}
1386+
1387+
/// Decodes all traits in the crate (for rustdoc and rustc diagnostics).
13721388
fn get_traits(self) -> impl Iterator<Item = DefId> + 'a {
13731389
self.root.traits.decode(self).map(move |index| self.local_def_id(index))
13741390
}
13751391

1392+
/// Decodes all trait impls in the crate (for rustdoc).
13761393
fn get_trait_impls(self) -> impl Iterator<Item = (DefId, DefId, Option<SimplifiedType>)> + 'a {
13771394
self.cdata.trait_impls.iter().flat_map(move |((trait_cnum_raw, trait_index), impls)| {
13781395
let trait_def_id = DefId {

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+10
Original file line numberDiff line numberDiff line change
@@ -486,16 +486,26 @@ impl CStore {
486486
self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess)
487487
}
488488

489+
/// Decodes all traits in the crate (for rustdoc).
489490
pub fn traits_in_crate_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ {
490491
self.get_crate_data(cnum).get_traits()
491492
}
492493

494+
/// Decodes all trait impls in the crate (for rustdoc).
493495
pub fn trait_impls_in_crate_untracked(
494496
&self,
495497
cnum: CrateNum,
496498
) -> impl Iterator<Item = (DefId, DefId, Option<SimplifiedType>)> + '_ {
497499
self.get_crate_data(cnum).get_trait_impls()
498500
}
501+
502+
/// Decodes all inherent impls in the crate (for rustdoc).
503+
pub fn inherent_impls_in_crate_untracked(
504+
&self,
505+
cnum: CrateNum,
506+
) -> impl Iterator<Item = (DefId, DefId)> + '_ {
507+
self.get_crate_data(cnum).get_inherent_impls()
508+
}
499509
}
500510

501511
impl CrateStore for CStore {

src/librustdoc/passes/collect_intra_doc_links/early.rs

+7
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ impl IntraLinkCrateLoader<'_, '_> {
116116
let all_traits = Vec::from_iter(self.resolver.cstore().traits_in_crate_untracked(cnum));
117117
let all_trait_impls =
118118
Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum));
119+
let all_inherent_impls =
120+
Vec::from_iter(self.resolver.cstore().inherent_impls_in_crate_untracked(cnum));
119121

120122
// Querying traits in scope is expensive so we try to prune the impl and traits lists
121123
// using privacy, private traits and impls from other crates are never documented in
@@ -134,6 +136,11 @@ impl IntraLinkCrateLoader<'_, '_> {
134136
self.add_traits_in_parent_scope(impl_def_id);
135137
}
136138
}
139+
for (ty_def_id, impl_def_id) in all_inherent_impls {
140+
if self.resolver.cstore().visibility_untracked(ty_def_id) == Visibility::Public {
141+
self.add_traits_in_parent_scope(impl_def_id);
142+
}
143+
}
137144

138145
self.all_traits.extend(all_traits);
139146
self.all_trait_impls.extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#[derive(Clone)]
2+
pub struct PublicStruct;
3+
4+
mod inner {
5+
use super::PublicStruct;
6+
7+
impl PublicStruct {
8+
/// [PublicStruct::clone]
9+
pub fn method() {}
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Reexport of a structure with public inherent impls having doc links in their comments. The doc
2+
// link points to an associated item, so we check that traits in scope for that link are populated.
3+
4+
// aux-build:extern-inherent-impl-dep.rs
5+
6+
extern crate extern_inherent_impl_dep;
7+
8+
pub use extern_inherent_impl_dep::PublicStruct;

0 commit comments

Comments
 (0)