@@ -10,6 +10,7 @@ use rustc_hir::{Node, CRATE_HIR_ID};
10
10
use rustc_middle:: hir:: nested_filter;
11
11
use rustc_middle:: ty:: TyCtxt ;
12
12
use rustc_span:: def_id:: { CRATE_DEF_ID , LOCAL_CRATE } ;
13
+ use rustc_span:: hygiene:: MacroKind ;
13
14
use rustc_span:: symbol:: { kw, sym, Symbol } ;
14
15
use rustc_span:: Span ;
15
16
@@ -87,6 +88,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
87
88
inside_public_path : bool ,
88
89
exact_paths : DefIdMap < Vec < Symbol > > ,
89
90
modules : Vec < Module < ' tcx > > ,
91
+ is_importable_from_parent : bool ,
90
92
}
91
93
92
94
impl < ' a , ' tcx > RustdocVisitor < ' a , ' tcx > {
@@ -107,6 +109,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
107
109
inside_public_path : true ,
108
110
exact_paths : Default :: default ( ) ,
109
111
modules : vec ! [ om] ,
112
+ is_importable_from_parent : true ,
110
113
}
111
114
}
112
115
@@ -319,19 +322,31 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
319
322
renamed : Option < Symbol > ,
320
323
parent_id : Option < LocalDefId > ,
321
324
) {
322
- self . modules
323
- . last_mut ( )
324
- . unwrap ( )
325
- . items
326
- . insert ( ( item. owner_id . def_id , renamed) , ( item, renamed, parent_id) ) ;
325
+ if self . is_importable_from_parent
326
+ // If we're inside an item, only impl blocks and `macro_rules!` with the `macro_export`
327
+ // attribute can still be visible.
328
+ || match item. kind {
329
+ hir:: ItemKind :: Impl ( ..) => true ,
330
+ hir:: ItemKind :: Macro ( _, MacroKind :: Bang ) => {
331
+ self . cx . tcx . has_attr ( item. owner_id . def_id , sym:: macro_export)
332
+ }
333
+ _ => false ,
334
+ }
335
+ {
336
+ self . modules
337
+ . last_mut ( )
338
+ . unwrap ( )
339
+ . items
340
+ . insert ( ( item. owner_id . def_id , renamed) , ( item, renamed, parent_id) ) ;
341
+ }
327
342
}
328
343
329
344
fn visit_item_inner (
330
345
& mut self ,
331
346
item : & ' tcx hir:: Item < ' _ > ,
332
347
renamed : Option < Symbol > ,
333
348
import_id : Option < LocalDefId > ,
334
- ) -> bool {
349
+ ) {
335
350
debug ! ( "visiting item {:?}" , item) ;
336
351
let name = renamed. unwrap_or ( item. ident . name ) ;
337
352
let tcx = self . cx . tcx ;
@@ -448,7 +463,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
448
463
}
449
464
}
450
465
}
451
- true
452
466
}
453
467
454
468
fn visit_foreign_item_inner (
@@ -485,9 +499,23 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
485
499
}
486
500
487
501
fn visit_item ( & mut self , i : & ' tcx hir:: Item < ' tcx > ) {
488
- if self . visit_item_inner ( i, None , None ) {
489
- walk_item ( self , i) ;
490
- }
502
+ self . visit_item_inner ( i, None , None ) ;
503
+ let new_value = if self . is_importable_from_parent {
504
+ matches ! (
505
+ i. kind,
506
+ hir:: ItemKind :: Mod ( ..)
507
+ | hir:: ItemKind :: ForeignMod { .. }
508
+ | hir:: ItemKind :: Impl ( ..)
509
+ | hir:: ItemKind :: Trait ( ..)
510
+ )
511
+ } else {
512
+ // Whatever the context, if it's an impl block, the items inside it can be used so they
513
+ // should be visible.
514
+ matches ! ( i. kind, hir:: ItemKind :: Impl ( ..) )
515
+ } ;
516
+ let prev = mem:: replace ( & mut self . is_importable_from_parent , new_value) ;
517
+ walk_item ( self , i) ;
518
+ self . is_importable_from_parent = prev;
491
519
}
492
520
493
521
fn visit_mod ( & mut self , _: & hir:: Mod < ' tcx > , _: Span , _: hir:: HirId ) {
0 commit comments