@@ -2,6 +2,7 @@ use crate::clean::Attributes;
22use crate :: core:: ResolverCaches ;
33use crate :: passes:: collect_intra_doc_links:: preprocessed_markdown_links;
44use crate :: passes:: collect_intra_doc_links:: { Disambiguator , PreprocessedMarkdownLink } ;
5+ use crate :: visit_lib:: early_lib_embargo_visit_item;
56
67use rustc_ast:: visit:: { self , AssocCtxt , Visitor } ;
78use rustc_ast:: { self as ast, ItemKind } ;
@@ -34,6 +35,8 @@ pub(crate) fn early_resolve_intra_doc_links(
3435 traits_in_scope : Default :: default ( ) ,
3536 all_trait_impls : Default :: default ( ) ,
3637 all_macro_rules : Default :: default ( ) ,
38+ extern_doc_reachable : Default :: default ( ) ,
39+ local_doc_reachable : Default :: default ( ) ,
3740 document_private_items,
3841 } ;
3942
@@ -61,6 +64,7 @@ pub(crate) fn early_resolve_intra_doc_links(
6164 traits_in_scope : link_resolver. traits_in_scope ,
6265 all_trait_impls : Some ( link_resolver. all_trait_impls ) ,
6366 all_macro_rules : link_resolver. all_macro_rules ,
67+ extern_doc_reachable : link_resolver. extern_doc_reachable ,
6468 }
6569}
6670
@@ -77,6 +81,15 @@ struct EarlyDocLinkResolver<'r, 'ra> {
7781 traits_in_scope : DefIdMap < Vec < TraitCandidate > > ,
7882 all_trait_impls : Vec < DefId > ,
7983 all_macro_rules : FxHashMap < Symbol , Res < ast:: NodeId > > ,
84+ /// This set is used as a seed for `effective_visibilities`, which are then extended by some
85+ /// more items using `lib_embargo_visit_item` during doc inlining.
86+ extern_doc_reachable : DefIdSet ,
87+ /// This is an easily identifiable superset of items added to `effective_visibilities`
88+ /// using `lib_embargo_visit_item` during doc inlining.
89+ /// The union of `(extern,local)_doc_reachable` is therefore a superset of
90+ /// `effective_visibilities` and can be used for pruning extern impls here
91+ /// in early doc link resolution.
92+ local_doc_reachable : DefIdSet ,
8093 document_private_items : bool ,
8194}
8295
@@ -105,6 +118,10 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
105118 }
106119 }
107120
121+ fn is_doc_reachable ( & self , def_id : DefId ) -> bool {
122+ self . extern_doc_reachable . contains ( & def_id) || self . local_doc_reachable . contains ( & def_id)
123+ }
124+
108125 /// Add traits in scope for links in impls collected by the `collect-intra-doc-links` pass.
109126 /// That pass filters impls using type-based information, but we don't yet have such
110127 /// information here, so we just conservatively calculate traits in scope for *all* modules
@@ -114,6 +131,14 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
114131 let mut start_cnum = 0 ;
115132 loop {
116133 let crates = Vec :: from_iter ( self . resolver . cstore ( ) . crates_untracked ( ) ) ;
134+ for cnum in & crates[ start_cnum..] {
135+ early_lib_embargo_visit_item (
136+ self . resolver ,
137+ & mut self . extern_doc_reachable ,
138+ cnum. as_def_id ( ) ,
139+ true ,
140+ ) ;
141+ }
117142 for & cnum in & crates[ start_cnum..] {
118143 let all_trait_impls =
119144 Vec :: from_iter ( self . resolver . cstore ( ) . trait_impls_in_crate_untracked ( cnum) ) ;
@@ -127,28 +152,26 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
127152 // privacy, private traits and impls from other crates are never documented in
128153 // the current crate, and links in their doc comments are not resolved.
129154 for & ( trait_def_id, impl_def_id, simplified_self_ty) in & all_trait_impls {
130- if self . resolver . cstore ( ) . visibility_untracked ( trait_def_id) . is_public ( )
131- && simplified_self_ty. and_then ( |ty| ty . def ( ) ) . map_or ( true , |ty_def_id| {
132- self . resolver . cstore ( ) . visibility_untracked ( ty_def_id ) . is_public ( )
133- } )
155+ if self . is_doc_reachable ( trait_def_id)
156+ && simplified_self_ty
157+ . and_then ( |ty| ty . def ( ) )
158+ . map_or ( true , |ty_def_id| self . is_doc_reachable ( ty_def_id ) )
134159 {
135160 if self . visited_mods . insert ( trait_def_id) {
136161 self . resolve_doc_links_extern_impl ( trait_def_id, false ) ;
137162 }
138163 self . resolve_doc_links_extern_impl ( impl_def_id, false ) ;
139164 }
165+ self . all_trait_impls . push ( impl_def_id) ;
140166 }
141167 for ( ty_def_id, impl_def_id) in all_inherent_impls {
142- if self . resolver . cstore ( ) . visibility_untracked ( ty_def_id) . is_public ( ) {
168+ if self . is_doc_reachable ( ty_def_id) {
143169 self . resolve_doc_links_extern_impl ( impl_def_id, true ) ;
144170 }
145171 }
146172 for impl_def_id in all_incoherent_impls {
147173 self . resolve_doc_links_extern_impl ( impl_def_id, true ) ;
148174 }
149-
150- self . all_trait_impls
151- . extend ( all_trait_impls. into_iter ( ) . map ( |( _, def_id, _) | def_id) ) ;
152175 }
153176
154177 if crates. len ( ) > start_cnum {
@@ -298,6 +321,7 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
298321 && module_id. is_local ( )
299322 {
300323 if let Some ( def_id) = child. res . opt_def_id ( ) && !def_id. is_local ( ) {
324+ self . local_doc_reachable . insert ( def_id) ;
301325 let scope_id = match child. res {
302326 Res :: Def (
303327 DefKind :: Variant
0 commit comments