about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume.gomez@huawei.com>2023-04-17 14:34:50 +0200
committerGuillaume Gomez <guillaume.gomez@huawei.com>2023-04-17 14:34:50 +0200
commitc3c9f8f5f8cb96e0536bc8d4e76e66c5e7caba56 (patch)
treeeb17b32e5b15bbba2b1e656c6c4e590eba3b44f0
parentf91d02b153a357b9937d6a5193db931076795deb (diff)
downloadrust-c3c9f8f5f8cb96e0536bc8d4e76e66c5e7caba56.tar.gz
rust-c3c9f8f5f8cb96e0536bc8d4e76e66c5e7caba56.zip
Fix invalid handling of nested items with `--document-private-items`
-rw-r--r--src/librustdoc/visit_ast.rs40
1 files changed, 35 insertions, 5 deletions
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 5ac68da150a..071a85f4da6 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -10,6 +10,7 @@ use rustc_hir::{Node, CRATE_HIR_ID};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 
@@ -87,6 +88,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
     inside_public_path: bool,
     exact_paths: DefIdMap<Vec<Symbol>>,
     modules: Vec<Module<'tcx>>,
+    is_importable_from_parent: bool,
 }
 
 impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -107,6 +109,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             inside_public_path: true,
             exact_paths: Default::default(),
             modules: vec![om],
+            is_importable_from_parent: true,
         }
     }
 
@@ -319,11 +322,23 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         renamed: Option<Symbol>,
         parent_id: Option<LocalDefId>,
     ) {
-        self.modules
-            .last_mut()
-            .unwrap()
-            .items
-            .insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
+        if self.is_importable_from_parent
+            // If we're inside an item, only impl blocks and `macro_rules!` with the `macro_export`
+            // attribute can still be visible.
+            || match item.kind {
+                hir::ItemKind::Impl(..) => true,
+                hir::ItemKind::Macro(_, MacroKind::Bang) => {
+                    self.cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export)
+                }
+                _ => false,
+            }
+        {
+            self.modules
+                .last_mut()
+                .unwrap()
+                .items
+                .insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
+        }
     }
 
     fn visit_item_inner(
@@ -485,7 +500,22 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
 
     fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
         self.visit_item_inner(i, None, None);
+        let new_value = if self.is_importable_from_parent {
+            matches!(
+                i.kind,
+                hir::ItemKind::Mod(..)
+                    | hir::ItemKind::ForeignMod { .. }
+                    | hir::ItemKind::Impl(..)
+                    | hir::ItemKind::Trait(..)
+            )
+        } else {
+            // Whatever the context, if it's an impl block, the items inside it can be used so they
+            // should be visible.
+            matches!(i.kind, hir::ItemKind::Impl(..))
+        };
+        let prev = mem::replace(&mut self.is_importable_from_parent, new_value);
         walk_item(self, i);
+        self.is_importable_from_parent = prev;
     }
 
     fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {