11use crate :: clean:: Attributes ;
22use crate :: core:: ResolverCaches ;
3- use crate :: html:: markdown:: markdown_links;
3+ use crate :: html:: markdown:: { markdown_links, MarkdownLink } ;
44use crate :: passes:: collect_intra_doc_links:: preprocess_link;
55
66use rustc_ast:: visit:: { self , AssocCtxt , Visitor } ;
77use rustc_ast:: { self as ast, ItemKind } ;
88use rustc_ast_lowering:: ResolverAstLowering ;
9- use rustc_hir:: def:: Namespace :: TypeNS ;
10- use rustc_hir:: def:: { DefKind , Res } ;
9+ use rustc_data_structures:: fx:: FxHashMap ;
10+ use rustc_hir:: def:: Namespace :: * ;
11+ use rustc_hir:: def:: { DefKind , Namespace , Res } ;
1112use rustc_hir:: def_id:: { DefId , DefIdMap , DefIdSet , LocalDefId , CRATE_DEF_ID } ;
1213use rustc_hir:: TraitCandidate ;
1314use rustc_middle:: ty:: { DefIdTree , Visibility } ;
1415use rustc_resolve:: { ParentScope , Resolver } ;
1516use rustc_session:: config:: Externs ;
16- use rustc_span:: SyntaxContext ;
17+ use rustc_span:: { Symbol , SyntaxContext } ;
1718
1819use std:: collections:: hash_map:: Entry ;
1920use std:: mem;
@@ -28,6 +29,8 @@ crate fn early_resolve_intra_doc_links(
2829 resolver,
2930 current_mod : CRATE_DEF_ID ,
3031 visited_mods : Default :: default ( ) ,
32+ markdown_links : Default :: default ( ) ,
33+ doc_link_resolutions : Default :: default ( ) ,
3134 traits_in_scope : Default :: default ( ) ,
3235 all_traits : Default :: default ( ) ,
3336 all_trait_impls : Default :: default ( ) ,
@@ -36,7 +39,7 @@ crate fn early_resolve_intra_doc_links(
3639
3740 // Overridden `visit_item` below doesn't apply to the crate root,
3841 // so we have to visit its attributes and reexports separately.
39- link_resolver. load_links_in_attrs ( & krate. attrs ) ;
42+ link_resolver. resolve_doc_links_local ( & krate. attrs ) ;
4043 link_resolver. process_module_children_or_reexports ( CRATE_DEF_ID . to_def_id ( ) ) ;
4144 visit:: walk_crate ( & mut link_resolver, krate) ;
4245 link_resolver. process_extern_impls ( ) ;
@@ -50,17 +53,27 @@ crate fn early_resolve_intra_doc_links(
5053 }
5154
5255 ResolverCaches {
56+ markdown_links : Some ( link_resolver. markdown_links ) ,
57+ doc_link_resolutions : link_resolver. doc_link_resolutions ,
5358 traits_in_scope : link_resolver. traits_in_scope ,
5459 all_traits : Some ( link_resolver. all_traits ) ,
5560 all_trait_impls : Some ( link_resolver. all_trait_impls ) ,
5661 all_macro_rules : link_resolver. resolver . take_all_macro_rules ( ) ,
5762 }
5863}
5964
65+ fn doc_attrs < ' a > ( attrs : impl Iterator < Item = & ' a ast:: Attribute > ) -> Attributes {
66+ let mut attrs = Attributes :: from_ast_iter ( attrs. filter ( |attr| attr. doc_str ( ) . is_some ( ) ) , None ) ;
67+ attrs. unindent_doc_comments ( ) ;
68+ attrs
69+ }
70+
6071struct EarlyDocLinkResolver < ' r , ' ra > {
6172 resolver : & ' r mut Resolver < ' ra > ,
6273 current_mod : LocalDefId ,
6374 visited_mods : DefIdSet ,
75+ markdown_links : FxHashMap < String , Vec < MarkdownLink > > ,
76+ doc_link_resolutions : FxHashMap < ( Symbol , Namespace , DefId ) , Option < Res < ast:: NodeId > > > ,
6477 traits_in_scope : DefIdMap < Vec < TraitCandidate > > ,
6578 all_traits : Vec < DefId > ,
6679 all_trait_impls : Vec < DefId > ,
@@ -92,18 +105,11 @@ impl EarlyDocLinkResolver<'_, '_> {
92105 }
93106 }
94107
95- fn add_traits_in_parent_scope ( & mut self , def_id : DefId ) {
96- if let Some ( module_id) = self . resolver . parent ( def_id) {
97- self . add_traits_in_scope ( module_id) ;
98- }
99- }
100-
101108 /// Add traits in scope for links in impls collected by the `collect-intra-doc-links` pass.
102109 /// That pass filters impls using type-based information, but we don't yet have such
103110 /// information here, so we just conservatively calculate traits in scope for *all* modules
104111 /// having impls in them.
105112 fn process_extern_impls ( & mut self ) {
106- // FIXME: Need to resolve doc links on all these impl and trait items below.
107113 // Resolving links in already existing crates may trigger loading of new crates.
108114 let mut start_cnum = 0 ;
109115 loop {
@@ -124,7 +130,7 @@ impl EarlyDocLinkResolver<'_, '_> {
124130 // the current crate, and links in their doc comments are not resolved.
125131 for & def_id in & all_traits {
126132 if self . resolver . cstore ( ) . visibility_untracked ( def_id) == Visibility :: Public {
127- self . add_traits_in_parent_scope ( def_id) ;
133+ self . resolve_doc_links_extern_impl ( def_id, false ) ;
128134 }
129135 }
130136 for & ( trait_def_id, impl_def_id, simplified_self_ty) in & all_trait_impls {
@@ -135,17 +141,17 @@ impl EarlyDocLinkResolver<'_, '_> {
135141 == Visibility :: Public
136142 } )
137143 {
138- self . add_traits_in_parent_scope ( impl_def_id) ;
144+ self . resolve_doc_links_extern_impl ( impl_def_id, false ) ;
139145 }
140146 }
141147 for ( ty_def_id, impl_def_id) in all_inherent_impls {
142148 if self . resolver . cstore ( ) . visibility_untracked ( ty_def_id) == Visibility :: Public
143149 {
144- self . add_traits_in_parent_scope ( impl_def_id) ;
150+ self . resolve_doc_links_extern_impl ( impl_def_id, true ) ;
145151 }
146152 }
147- for def_id in all_incoherent_impls {
148- self . add_traits_in_parent_scope ( def_id ) ;
153+ for impl_def_id in all_incoherent_impls {
154+ self . resolve_doc_links_extern_impl ( impl_def_id , true ) ;
149155 }
150156
151157 self . all_traits . extend ( all_traits) ;
@@ -161,16 +167,52 @@ impl EarlyDocLinkResolver<'_, '_> {
161167 }
162168 }
163169
164- fn load_links_in_attrs ( & mut self , attrs : & [ ast:: Attribute ] ) {
170+ fn resolve_doc_links_extern_impl ( & mut self , def_id : DefId , _is_inherent : bool ) {
171+ // FIXME: Resolve links in associated items in addition to traits themselves,
172+ // `force` is used to provide traits in scope for the associated items.
173+ self . resolve_doc_links_extern_outer ( def_id, def_id, true ) ;
174+ }
175+
176+ fn resolve_doc_links_extern_outer ( & mut self , def_id : DefId , scope_id : DefId , force : bool ) {
177+ if !force && !self . resolver . cstore ( ) . may_have_doc_links_untracked ( def_id) {
178+ return ;
179+ }
180+ // FIXME: actually resolve links, not just add traits in scope.
181+ if let Some ( parent_id) = self . resolver . parent ( scope_id) {
182+ self . add_traits_in_scope ( parent_id) ;
183+ }
184+ }
185+
186+ fn resolve_doc_links_extern_inner ( & mut self , def_id : DefId ) {
187+ if !self . resolver . cstore ( ) . may_have_doc_links_untracked ( def_id) {
188+ return ;
189+ }
190+ // FIXME: actually resolve links, not just add traits in scope.
191+ self . add_traits_in_scope ( def_id) ;
192+ }
193+
194+ fn resolve_doc_links_local ( & mut self , attrs : & [ ast:: Attribute ] ) {
195+ if !attrs. iter ( ) . any ( |attr| attr. may_have_doc_links ( ) ) {
196+ return ;
197+ }
165198 let module_id = self . current_mod . to_def_id ( ) ;
199+ self . resolve_doc_links ( doc_attrs ( attrs. iter ( ) ) , module_id) ;
200+ }
201+
202+ fn resolve_doc_links ( & mut self , attrs : Attributes , module_id : DefId ) {
166203 let mut need_traits_in_scope = false ;
167- for ( doc_module, doc) in
168- Attributes :: from_ast ( attrs, None ) . collapsed_doc_value_by_module_level ( )
169- {
204+ for ( doc_module, doc) in attrs. collapsed_doc_value_by_module_level ( ) {
170205 assert_eq ! ( doc_module, None ) ;
171- for link in markdown_links ( & doc. as_str ( ) ) {
206+ for link in self . markdown_links . entry ( doc) . or_insert_with_key ( |doc| markdown_links ( doc) )
207+ {
172208 if let Some ( Ok ( pinfo) ) = preprocess_link ( & link) {
173- self . resolver . resolve_rustdoc_path ( & pinfo. path_str , TypeNS , module_id) ;
209+ // FIXME: Resolve the path in all namespaces and resolve its prefixes too.
210+ let ns = TypeNS ;
211+ self . doc_link_resolutions
212+ . entry ( ( Symbol :: intern ( & pinfo. path_str ) , ns, module_id) )
213+ . or_insert_with_key ( |( path, ns, module_id) | {
214+ self . resolver . resolve_rustdoc_path ( path. as_str ( ) , * ns, * module_id)
215+ } ) ;
174216 need_traits_in_scope = true ;
175217 }
176218 }
@@ -197,15 +239,13 @@ impl EarlyDocLinkResolver<'_, '_> {
197239 && module_id. is_local ( )
198240 {
199241 if let Some ( def_id) = child. res . opt_def_id ( ) && !def_id. is_local ( ) {
200- // FIXME: Need to resolve doc links on all these extern items
201- // reached through reexports.
202242 let scope_id = match child. res {
203243 Res :: Def ( DefKind :: Variant , ..) => self . resolver . parent ( def_id) . unwrap ( ) ,
204244 _ => def_id,
205245 } ;
206- self . add_traits_in_parent_scope ( scope_id) ; // Outer attribute scope
246+ self . resolve_doc_links_extern_outer ( def_id , scope_id, false ) ; // Outer attribute scope
207247 if let Res :: Def ( DefKind :: Mod , ..) = child. res {
208- self . add_traits_in_scope ( def_id) ; // Inner attribute scope
248+ self . resolve_doc_links_extern_inner ( def_id) ; // Inner attribute scope
209249 }
210250 // Traits are processed in `add_extern_traits_in_scope`.
211251 if let Res :: Def ( DefKind :: Mod | DefKind :: Enum , ..) = child. res {
@@ -219,10 +259,10 @@ impl EarlyDocLinkResolver<'_, '_> {
219259
220260impl Visitor < ' _ > for EarlyDocLinkResolver < ' _ , ' _ > {
221261 fn visit_item ( & mut self , item : & ast:: Item ) {
222- self . load_links_in_attrs ( & item. attrs ) ; // Outer attribute scope
262+ self . resolve_doc_links_local ( & item. attrs ) ; // Outer attribute scope
223263 if let ItemKind :: Mod ( ..) = item. kind {
224264 let old_mod = mem:: replace ( & mut self . current_mod , self . resolver . local_def_id ( item. id ) ) ;
225- self . load_links_in_attrs ( & item. attrs ) ; // Inner attribute scope
265+ self . resolve_doc_links_local ( & item. attrs ) ; // Inner attribute scope
226266 self . process_module_children_or_reexports ( self . current_mod . to_def_id ( ) ) ;
227267 visit:: walk_item ( self , item) ;
228268 self . current_mod = old_mod;
@@ -241,22 +281,22 @@ impl Visitor<'_> for EarlyDocLinkResolver<'_, '_> {
241281 }
242282
243283 fn visit_assoc_item ( & mut self , item : & ast:: AssocItem , ctxt : AssocCtxt ) {
244- self . load_links_in_attrs ( & item. attrs ) ;
284+ self . resolve_doc_links_local ( & item. attrs ) ;
245285 visit:: walk_assoc_item ( self , item, ctxt)
246286 }
247287
248288 fn visit_foreign_item ( & mut self , item : & ast:: ForeignItem ) {
249- self . load_links_in_attrs ( & item. attrs ) ;
289+ self . resolve_doc_links_local ( & item. attrs ) ;
250290 visit:: walk_foreign_item ( self , item)
251291 }
252292
253293 fn visit_variant ( & mut self , v : & ast:: Variant ) {
254- self . load_links_in_attrs ( & v. attrs ) ;
294+ self . resolve_doc_links_local ( & v. attrs ) ;
255295 visit:: walk_variant ( self , v)
256296 }
257297
258298 fn visit_field_def ( & mut self , field : & ast:: FieldDef ) {
259- self . load_links_in_attrs ( & field. attrs ) ;
299+ self . resolve_doc_links_local ( & field. attrs ) ;
260300 visit:: walk_field_def ( self , field)
261301 }
262302
0 commit comments