@@ -7,7 +7,6 @@ use rustc_hir::def::{DefKind, Res};
77use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId , LocalDefIdSet } ;
88use rustc_hir:: intravisit:: { walk_item, Visitor } ;
99use rustc_hir:: { Node , CRATE_HIR_ID } ;
10- use rustc_middle:: hir:: map:: Map ;
1110use rustc_middle:: hir:: nested_filter;
1211use rustc_middle:: ty:: { DefIdTree , TyCtxt } ;
1312use rustc_span:: def_id:: { CRATE_DEF_ID , LOCAL_CRATE } ;
@@ -74,7 +73,6 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
7473 inside_public_path : bool ,
7574 exact_paths : DefIdMap < Vec < Symbol > > ,
7675 modules : Vec < Module < ' tcx > > ,
77- map : Map < ' tcx > ,
7876}
7977
8078impl < ' a , ' tcx > RustdocVisitor < ' a , ' tcx > {
@@ -87,7 +85,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
8785 CRATE_DEF_ID ,
8886 cx. tcx . hir ( ) . root_module ( ) . spans . inner_span ,
8987 ) ;
90- let map = cx. tcx . hir ( ) ;
9188
9289 RustdocVisitor {
9390 cx,
@@ -96,7 +93,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
9693 inside_public_path : true ,
9794 exact_paths : Default :: default ( ) ,
9895 modules : vec ! [ om] ,
99- map,
10096 }
10197 }
10298
@@ -105,6 +101,94 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
105101 self . exact_paths . entry ( did) . or_insert_with ( || def_id_to_path ( tcx, did) ) ;
106102 }
107103
104+ pub ( crate ) fn visit ( mut self ) -> Module < ' tcx > {
105+ let root_module = self . cx . tcx . hir ( ) . root_module ( ) ;
106+ self . visit_mod_contents ( CRATE_DEF_ID , root_module) ;
107+
108+ let mut top_level_module = self . modules . pop ( ) . unwrap ( ) ;
109+
110+ // `#[macro_export] macro_rules!` items are reexported at the top level of the
111+ // crate, regardless of where they're defined. We want to document the
112+ // top level rexport of the macro, not its original definition, since
113+ // the rexport defines the path that a user will actually see. Accordingly,
114+ // we add the rexport as an item here, and then skip over the original
115+ // definition in `visit_item()` below.
116+ //
117+ // We also skip `#[macro_export] macro_rules!` that have already been inserted,
118+ // it can happen if within the same module a `#[macro_export] macro_rules!`
119+ // is declared but also a reexport of itself producing two exports of the same
120+ // macro in the same module.
121+ let mut inserted = FxHashSet :: default ( ) ;
122+ for export in self . cx . tcx . module_reexports ( CRATE_DEF_ID ) . unwrap_or ( & [ ] ) {
123+ if let Res :: Def ( DefKind :: Macro ( _) , def_id) = export. res &&
124+ let Some ( local_def_id) = def_id. as_local ( ) &&
125+ self . cx . tcx . has_attr ( def_id, sym:: macro_export) &&
126+ inserted. insert ( def_id)
127+ {
128+ let item = self . cx . tcx . hir ( ) . expect_item ( local_def_id) ;
129+ top_level_module. items . push ( ( item, None , None ) ) ;
130+ }
131+ }
132+
133+ self . cx . cache . hidden_cfg = self
134+ . cx
135+ . tcx
136+ . hir ( )
137+ . attrs ( CRATE_HIR_ID )
138+ . iter ( )
139+ . filter ( |attr| attr. has_name ( sym:: doc) )
140+ . flat_map ( |attr| attr. meta_item_list ( ) . into_iter ( ) . flatten ( ) )
141+ . filter ( |attr| attr. has_name ( sym:: cfg_hide) )
142+ . flat_map ( |attr| {
143+ attr. meta_item_list ( )
144+ . unwrap_or ( & [ ] )
145+ . iter ( )
146+ . filter_map ( |attr| {
147+ Cfg :: parse ( attr. meta_item ( ) ?)
148+ . map_err ( |e| self . cx . sess ( ) . diagnostic ( ) . span_err ( e. span , e. msg ) )
149+ . ok ( )
150+ } )
151+ . collect :: < Vec < _ > > ( )
152+ } )
153+ . chain (
154+ [ Cfg :: Cfg ( sym:: test, None ) , Cfg :: Cfg ( sym:: doc, None ) , Cfg :: Cfg ( sym:: doctest, None ) ]
155+ . into_iter ( ) ,
156+ )
157+ . collect ( ) ;
158+
159+ self . cx . cache . exact_paths = self . exact_paths ;
160+ top_level_module
161+ }
162+
163+ /// This method will go through the given module items in two passes:
164+ /// 1. The items which are not glob imports/reexports.
165+ /// 2. The glob imports/reexports.
166+ fn visit_mod_contents ( & mut self , def_id : LocalDefId , m : & ' tcx hir:: Mod < ' tcx > ) {
167+ debug ! ( "Going through module {:?}" , m) ;
168+ // Keep track of if there were any private modules in the path.
169+ let orig_inside_public_path = self . inside_public_path ;
170+ self . inside_public_path &= self . cx . tcx . local_visibility ( def_id) . is_public ( ) ;
171+
172+ // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
173+ // the second loop):
174+ for & i in m. item_ids {
175+ let item = self . cx . tcx . hir ( ) . item ( i) ;
176+ if !matches ! ( item. kind, hir:: ItemKind :: Use ( _, hir:: UseKind :: Glob ) ) {
177+ self . visit_item ( item) ;
178+ }
179+ }
180+ for & i in m. item_ids {
181+ let item = self . cx . tcx . hir ( ) . item ( i) ;
182+ // To match the way import precedence works, visit glob imports last.
183+ // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
184+ // imported items appear last, then they'll be the ones that get discarded.
185+ if matches ! ( item. kind, hir:: ItemKind :: Use ( _, hir:: UseKind :: Glob ) ) {
186+ self . visit_item ( item) ;
187+ }
188+ }
189+ self . inside_public_path = orig_inside_public_path;
190+ }
191+
108192 /// Tries to resolve the target of a `pub use` statement and inlines the
109193 /// target if it is defined locally and would not be documented otherwise,
110194 /// or when it is specifically requested with `please_inline`.
@@ -197,7 +281,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
197281 & mut self ,
198282 item : & ' tcx hir:: Item < ' _ > ,
199283 renamed : Option < Symbol > ,
200- parent_id : Option < hir :: HirId > ,
284+ parent_id : Option < LocalDefId > ,
201285 ) {
202286 self . modules . last_mut ( ) . unwrap ( ) . items . push ( ( item, renamed, parent_id) )
203287 }
@@ -330,65 +414,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
330414 }
331415 }
332416
333- pub ( crate ) fn visit ( mut self ) -> Module < ' tcx > {
334- let root_module = self . cx . tcx . hir ( ) . root_module ( ) ;
335- self . visit_mod_contents ( CRATE_DEF_ID , root_module) ;
336-
337- let mut top_level_module = self . modules . pop ( ) . unwrap ( ) ;
338-
339- // `#[macro_export] macro_rules!` items are reexported at the top level of the
340- // crate, regardless of where they're defined. We want to document the
341- // top level rexport of the macro, not its original definition, since
342- // the rexport defines the path that a user will actually see. Accordingly,
343- // we add the rexport as an item here, and then skip over the original
344- // definition in `visit_item()` below.
345- //
346- // We also skip `#[macro_export] macro_rules!` that have already been inserted,
347- // it can happen if within the same module a `#[macro_export] macro_rules!`
348- // is declared but also a reexport of itself producing two exports of the same
349- // macro in the same module.
350- let mut inserted = FxHashSet :: default ( ) ;
351- for export in self . cx . tcx . module_reexports ( CRATE_DEF_ID ) . unwrap_or ( & [ ] ) {
352- if let Res :: Def ( DefKind :: Macro ( _) , def_id) = export. res &&
353- let Some ( local_def_id) = def_id. as_local ( ) &&
354- self . cx . tcx . has_attr ( def_id, sym:: macro_export) &&
355- inserted. insert ( def_id)
356- {
357- let item = self . cx . tcx . hir ( ) . expect_item ( local_def_id) ;
358- top_level_module. items . push ( ( item, None , None ) ) ;
359- }
360- }
361-
362- self . cx . cache . hidden_cfg = self
363- . cx
364- . tcx
365- . hir ( )
366- . attrs ( CRATE_HIR_ID )
367- . iter ( )
368- . filter ( |attr| attr. has_name ( sym:: doc) )
369- . flat_map ( |attr| attr. meta_item_list ( ) . into_iter ( ) . flatten ( ) )
370- . filter ( |attr| attr. has_name ( sym:: cfg_hide) )
371- . flat_map ( |attr| {
372- attr. meta_item_list ( )
373- . unwrap_or ( & [ ] )
374- . iter ( )
375- . filter_map ( |attr| {
376- Cfg :: parse ( attr. meta_item ( ) ?)
377- . map_err ( |e| self . cx . sess ( ) . diagnostic ( ) . span_err ( e. span , e. msg ) )
378- . ok ( )
379- } )
380- . collect :: < Vec < _ > > ( )
381- } )
382- . chain (
383- [ Cfg :: Cfg ( sym:: test, None ) , Cfg :: Cfg ( sym:: doc, None ) , Cfg :: Cfg ( sym:: doctest, None ) ]
384- . into_iter ( ) ,
385- )
386- . collect ( ) ;
387-
388- self . cx . cache . exact_paths = self . exact_paths ;
389- top_level_module
390- }
391-
392417 /// This method will create a new module and push it onto the "modules stack" then call
393418 /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
394419 /// add into the list of modules of the current module.
@@ -400,34 +425,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
400425 let last = self . modules . pop ( ) . unwrap ( ) ;
401426 self . modules . last_mut ( ) . unwrap ( ) . mods . push ( last) ;
402427 }
403-
404- /// This method will go through the given module items in two passes:
405- /// 1. The items which are not glob imports/reexports.
406- /// 2. The glob imports/reexports.
407- fn visit_mod_contents ( & mut self , def_id : LocalDefId , m : & ' tcx hir:: Mod < ' tcx > ) {
408- debug ! ( "Going through module {:?}" , m) ;
409- // Keep track of if there were any private modules in the path.
410- let orig_inside_public_path = self . inside_public_path ;
411- self . inside_public_path &= self . cx . tcx . local_visibility ( def_id) . is_public ( ) ;
412-
413- // Reimplementation of `walk_mod`:
414- for & i in m. item_ids {
415- let item = self . cx . tcx . hir ( ) . item ( i) ;
416- if !matches ! ( item. kind, hir:: ItemKind :: Use ( _, hir:: UseKind :: Glob ) ) {
417- self . visit_item ( item) ;
418- }
419- }
420- for & i in m. item_ids {
421- let item = self . cx . tcx . hir ( ) . item ( i) ;
422- // To match the way import precedence works, visit glob imports last.
423- // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
424- // imported items appear last, then they'll be the ones that get discarded.
425- if matches ! ( item. kind, hir:: ItemKind :: Use ( _, hir:: UseKind :: Glob ) ) {
426- self . visit_item ( item) ;
427- }
428- }
429- self . inside_public_path = orig_inside_public_path;
430- }
431428}
432429
433430// We need to implement this visitor so it'll go everywhere and retrieve items we're interested in
@@ -436,7 +433,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
436433 type NestedFilter = nested_filter:: All ;
437434
438435 fn nested_visit_map ( & mut self ) -> Self :: Map {
439- self . map
436+ self . cx . tcx . hir ( )
440437 }
441438
442439 fn visit_item ( & mut self , i : & ' tcx hir:: Item < ' tcx > ) {
0 commit comments