@@ -10,6 +10,7 @@ use rustc_hir::{Node, CRATE_HIR_ID};
1010use rustc_middle:: hir:: nested_filter;
1111use rustc_middle:: ty:: TyCtxt ;
1212use rustc_span:: def_id:: { CRATE_DEF_ID , LOCAL_CRATE } ;
13+ use rustc_span:: hygiene:: MacroKind ;
1314use rustc_span:: symbol:: { kw, sym, Symbol } ;
1415use rustc_span:: Span ;
1516
@@ -87,6 +88,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
8788 inside_public_path : bool ,
8889 exact_paths : DefIdMap < Vec < Symbol > > ,
8990 modules : Vec < Module < ' tcx > > ,
91+ is_importable_from_parent : bool ,
9092}
9193
9294impl < ' a , ' tcx > RustdocVisitor < ' a , ' tcx > {
@@ -107,6 +109,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
107109 inside_public_path : true ,
108110 exact_paths : Default :: default ( ) ,
109111 modules : vec ! [ om] ,
112+ is_importable_from_parent : true ,
110113 }
111114 }
112115
@@ -319,11 +322,23 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
319322 renamed : Option < Symbol > ,
320323 parent_id : Option < LocalDefId > ,
321324 ) {
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+ }
327342 }
328343
329344 fn visit_item_inner (
@@ -485,7 +500,22 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
485500
486501 fn visit_item ( & mut self , i : & ' tcx hir:: Item < ' tcx > ) {
487502 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) ;
488517 walk_item ( self , i) ;
518+ self . is_importable_from_parent = prev;
489519 }
490520
491521 fn visit_mod ( & mut self , _: & hir:: Mod < ' tcx > , _: Span , _: hir:: HirId ) {
0 commit comments