@@ -8,7 +8,6 @@ use rustc_hir::def_id::DefId;
88use rustc_hir:: intravisit:: { walk_item, Visitor } ;
99use rustc_hir:: Node ;
1010use rustc_hir:: CRATE_HIR_ID ;
11- use rustc_middle:: hir:: map:: Map ;
1211use rustc_middle:: hir:: nested_filter;
1312use rustc_middle:: ty:: TyCtxt ;
1413use rustc_span:: def_id:: { CRATE_DEF_ID , LOCAL_CRATE } ;
@@ -68,7 +67,6 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
6867 inside_public_path : bool ,
6968 exact_paths : FxHashMap < DefId , Vec < Symbol > > ,
7069 modules : Vec < Module < ' tcx > > ,
71- map : Map < ' tcx > ,
7270}
7371
7472impl < ' a , ' tcx > RustdocVisitor < ' a , ' tcx > {
@@ -81,7 +79,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
8179 hir:: CRATE_HIR_ID ,
8280 cx. tcx . hir ( ) . root_module ( ) . spans . inner_span ,
8381 ) ;
84- let map = cx. tcx . hir ( ) ;
8582
8683 RustdocVisitor {
8784 cx,
@@ -90,7 +87,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
9087 inside_public_path : true ,
9188 exact_paths : FxHashMap :: default ( ) ,
9289 modules : vec ! [ om] ,
93- map,
9490 }
9591 }
9692
@@ -99,6 +95,95 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
9995 self . exact_paths . entry ( did) . or_insert_with ( || def_id_to_path ( tcx, did) ) ;
10096 }
10197
98+ pub ( crate ) fn visit ( mut self ) -> Module < ' tcx > {
99+ let root_module = self . cx . tcx . hir ( ) . root_module ( ) ;
100+ self . visit_mod_contents ( CRATE_HIR_ID , root_module) ;
101+
102+ let mut top_level_module = self . modules . pop ( ) . unwrap ( ) ;
103+
104+ // `#[macro_export] macro_rules!` items are reexported at the top level of the
105+ // crate, regardless of where they're defined. We want to document the
106+ // top level rexport of the macro, not its original definition, since
107+ // the rexport defines the path that a user will actually see. Accordingly,
108+ // we add the rexport as an item here, and then skip over the original
109+ // definition in `visit_item()` below.
110+ //
111+ // We also skip `#[macro_export] macro_rules!` that have already been inserted,
112+ // it can happen if within the same module a `#[macro_export] macro_rules!`
113+ // is declared but also a reexport of itself producing two exports of the same
114+ // macro in the same module.
115+ let mut inserted = FxHashSet :: default ( ) ;
116+ for export in self . cx . tcx . module_reexports ( CRATE_DEF_ID ) . unwrap_or ( & [ ] ) {
117+ if let Res :: Def ( DefKind :: Macro ( _) , def_id) = export. res &&
118+ let Some ( local_def_id) = def_id. as_local ( ) &&
119+ self . cx . tcx . has_attr ( def_id, sym:: macro_export) &&
120+ inserted. insert ( def_id)
121+ {
122+ let item = self . cx . tcx . hir ( ) . expect_item ( local_def_id) ;
123+ top_level_module. items . push ( ( item, None , None ) ) ;
124+ }
125+ }
126+
127+ self . cx . cache . hidden_cfg = self
128+ . cx
129+ . tcx
130+ . hir ( )
131+ . attrs ( CRATE_HIR_ID )
132+ . iter ( )
133+ . filter ( |attr| attr. has_name ( sym:: doc) )
134+ . flat_map ( |attr| attr. meta_item_list ( ) . into_iter ( ) . flatten ( ) )
135+ . filter ( |attr| attr. has_name ( sym:: cfg_hide) )
136+ . flat_map ( |attr| {
137+ attr. meta_item_list ( )
138+ . unwrap_or ( & [ ] )
139+ . iter ( )
140+ . filter_map ( |attr| {
141+ Cfg :: parse ( attr. meta_item ( ) ?)
142+ . map_err ( |e| self . cx . sess ( ) . diagnostic ( ) . span_err ( e. span , e. msg ) )
143+ . ok ( )
144+ } )
145+ . collect :: < Vec < _ > > ( )
146+ } )
147+ . chain (
148+ [ Cfg :: Cfg ( sym:: test, None ) , Cfg :: Cfg ( sym:: doc, None ) , Cfg :: Cfg ( sym:: doctest, None ) ]
149+ . into_iter ( ) ,
150+ )
151+ . collect ( ) ;
152+
153+ self . cx . cache . exact_paths = self . exact_paths ;
154+ top_level_module
155+ }
156+
157+ /// This method will go through the given module items in two passes:
158+ /// 1. The items which are not glob imports/reexports.
159+ /// 2. The glob imports/reexports.
160+ fn visit_mod_contents ( & mut self , id : hir:: HirId , m : & ' tcx hir:: Mod < ' tcx > ) {
161+ debug ! ( "Going through module {:?}" , m) ;
162+ let def_id = self . cx . tcx . hir ( ) . local_def_id ( id) . to_def_id ( ) ;
163+ // Keep track of if there were any private modules in the path.
164+ let orig_inside_public_path = self . inside_public_path ;
165+ self . inside_public_path &= self . cx . tcx . visibility ( def_id) . is_public ( ) ;
166+
167+ // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
168+ // the second loop):
169+ for & i in m. item_ids {
170+ let item = self . cx . tcx . hir ( ) . item ( i) ;
171+ if !matches ! ( item. kind, hir:: ItemKind :: Use ( _, hir:: UseKind :: Glob ) ) {
172+ self . visit_item ( item) ;
173+ }
174+ }
175+ for & i in m. item_ids {
176+ let item = self . cx . tcx . hir ( ) . item ( i) ;
177+ // To match the way import precedence works, visit glob imports last.
178+ // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
179+ // imported items appear last, then they'll be the ones that get discarded.
180+ if matches ! ( item. kind, hir:: ItemKind :: Use ( _, hir:: UseKind :: Glob ) ) {
181+ self . visit_item ( item) ;
182+ }
183+ }
184+ self . inside_public_path = orig_inside_public_path;
185+ }
186+
102187 /// Tries to resolve the target of a `pub use` statement and inlines the
103188 /// target if it is defined locally and would not be documented otherwise,
104189 /// or when it is specifically requested with `please_inline`.
@@ -323,65 +408,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
323408 }
324409 }
325410
326- pub ( crate ) fn visit ( mut self ) -> Module < ' tcx > {
327- let root_module = self . cx . tcx . hir ( ) . root_module ( ) ;
328- self . visit_mod_contents ( CRATE_HIR_ID , root_module) ;
329-
330- let mut top_level_module = self . modules . pop ( ) . unwrap ( ) ;
331-
332- // `#[macro_export] macro_rules!` items are reexported at the top level of the
333- // crate, regardless of where they're defined. We want to document the
334- // top level rexport of the macro, not its original definition, since
335- // the rexport defines the path that a user will actually see. Accordingly,
336- // we add the rexport as an item here, and then skip over the original
337- // definition in `visit_item()` below.
338- //
339- // We also skip `#[macro_export] macro_rules!` that have already been inserted,
340- // it can happen if within the same module a `#[macro_export] macro_rules!`
341- // is declared but also a reexport of itself producing two exports of the same
342- // macro in the same module.
343- let mut inserted = FxHashSet :: default ( ) ;
344- for export in self . cx . tcx . module_reexports ( CRATE_DEF_ID ) . unwrap_or ( & [ ] ) {
345- if let Res :: Def ( DefKind :: Macro ( _) , def_id) = export. res &&
346- let Some ( local_def_id) = def_id. as_local ( ) &&
347- self . cx . tcx . has_attr ( def_id, sym:: macro_export) &&
348- inserted. insert ( def_id)
349- {
350- let item = self . cx . tcx . hir ( ) . expect_item ( local_def_id) ;
351- top_level_module. items . push ( ( item, None , None ) ) ;
352- }
353- }
354-
355- self . cx . cache . hidden_cfg = self
356- . cx
357- . tcx
358- . hir ( )
359- . attrs ( CRATE_HIR_ID )
360- . iter ( )
361- . filter ( |attr| attr. has_name ( sym:: doc) )
362- . flat_map ( |attr| attr. meta_item_list ( ) . into_iter ( ) . flatten ( ) )
363- . filter ( |attr| attr. has_name ( sym:: cfg_hide) )
364- . flat_map ( |attr| {
365- attr. meta_item_list ( )
366- . unwrap_or ( & [ ] )
367- . iter ( )
368- . filter_map ( |attr| {
369- Cfg :: parse ( attr. meta_item ( ) ?)
370- . map_err ( |e| self . cx . sess ( ) . diagnostic ( ) . span_err ( e. span , e. msg ) )
371- . ok ( )
372- } )
373- . collect :: < Vec < _ > > ( )
374- } )
375- . chain (
376- [ Cfg :: Cfg ( sym:: test, None ) , Cfg :: Cfg ( sym:: doc, None ) , Cfg :: Cfg ( sym:: doctest, None ) ]
377- . into_iter ( ) ,
378- )
379- . collect ( ) ;
380-
381- self . cx . cache . exact_paths = self . exact_paths ;
382- top_level_module
383- }
384-
385411 /// This method will create a new module and push it onto the "modules stack" then call
386412 /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
387413 /// add into into the list of modules of the current module.
@@ -393,35 +419,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
393419 let last = self . modules . pop ( ) . unwrap ( ) ;
394420 self . modules . last_mut ( ) . unwrap ( ) . mods . push ( last) ;
395421 }
396-
397- /// This method will go through the given module items in two passes:
398- /// 1. The items which are not glob imports/reexports.
399- /// 2. The glob imports/reexports.
400- fn visit_mod_contents ( & mut self , id : hir:: HirId , m : & ' tcx hir:: Mod < ' tcx > ) {
401- debug ! ( "Going through module {:?}" , m) ;
402- let def_id = self . cx . tcx . hir ( ) . local_def_id ( id) . to_def_id ( ) ;
403- // Keep track of if there were any private modules in the path.
404- let orig_inside_public_path = self . inside_public_path ;
405- self . inside_public_path &= self . cx . tcx . visibility ( def_id) . is_public ( ) ;
406-
407- // Reimplementation of `walk_mod`:
408- for & i in m. item_ids {
409- let item = self . cx . tcx . hir ( ) . item ( i) ;
410- if !matches ! ( item. kind, hir:: ItemKind :: Use ( _, hir:: UseKind :: Glob ) ) {
411- self . visit_item ( item) ;
412- }
413- }
414- for & i in m. item_ids {
415- let item = self . cx . tcx . hir ( ) . item ( i) ;
416- // To match the way import precedence works, visit glob imports last.
417- // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
418- // imported items appear last, then they'll be the ones that get discarded.
419- if matches ! ( item. kind, hir:: ItemKind :: Use ( _, hir:: UseKind :: Glob ) ) {
420- self . visit_item ( item) ;
421- }
422- }
423- self . inside_public_path = orig_inside_public_path;
424- }
425422}
426423
427424// We need to implement this visitor so it'll go everywhere and retrieve items we're interested in
@@ -430,7 +427,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
430427 type NestedFilter = nested_filter:: All ;
431428
432429 fn nested_visit_map ( & mut self ) -> Self :: Map {
433- self . map
430+ self . cx . tcx . hir ( )
434431 }
435432
436433 fn visit_item ( & mut self , i : & ' tcx hir:: Item < ' tcx > ) {
0 commit comments