Skip to content

Commit d646891

Browse files
authored
Rollup merge of #110450 - GuillaumeGomez:fix-nested-items-on-private-doc, r=notriddle,jyn514
rustdoc: Fix invalid handling of nested items with `--document-private-items` Fixes #110422. The problem is that only impl block and re-exported `macro_rules!` items are "visible" as nested items. This PR adds the missing checks to handle this correctly. cc `@compiler-errors` r? `@notriddle`
2 parents 1e3a384 + c456e15 commit d646891

File tree

4 files changed

+106
-27
lines changed

4 files changed

+106
-27
lines changed

src/librustdoc/visit_ast.rs

+38-10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_hir::{Node, CRATE_HIR_ID};
1010
use rustc_middle::hir::nested_filter;
1111
use rustc_middle::ty::TyCtxt;
1212
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
13+
use rustc_span::hygiene::MacroKind;
1314
use rustc_span::symbol::{kw, sym, Symbol};
1415
use 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

9294
impl<'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,19 +322,31 @@ 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(
330345
&mut self,
331346
item: &'tcx hir::Item<'_>,
332347
renamed: Option<Symbol>,
333348
import_id: Option<LocalDefId>,
334-
) -> bool {
349+
) {
335350
debug!("visiting item {:?}", item);
336351
let name = renamed.unwrap_or(item.ident.name);
337352
let tcx = self.cx.tcx;
@@ -448,7 +463,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
448463
}
449464
}
450465
}
451-
true
452466
}
453467

454468
fn visit_foreign_item_inner(
@@ -485,9 +499,23 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
485499
}
486500

487501
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;
491519
}
492520

493521
fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
// check-pass
2+
13
fn f() -> impl Sized {
2-
enum E { //~ ERROR
4+
enum E {
35
V(E),
46
}
7+
58
unimplemented!()
69
}

tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr

-16
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/110422>.
2+
// This test ensures that inner items (except for implementations and macros)
3+
// don't appear in documentation.
4+
5+
// compile-flags: --document-private-items
6+
7+
#![crate_name = "foo"]
8+
9+
// @has 'foo/index.html'
10+
// Checking there is no "trait" entry.
11+
// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 4
12+
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs'
13+
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Constants'
14+
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Functions'
15+
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Macros'
16+
17+
// @has - '//a[@href="fn.foo.html"]' 'foo'
18+
fn foo() {
19+
fn bar() {}
20+
21+
// @has - '//a[@class="macro"]' 'visible_macro'
22+
// @!has - '//a[@class="macro"]' 'non_visible_macro'
23+
// @has 'foo/macro.visible_macro.html'
24+
// @!has 'foo/macro.non_visible_macro.html'
25+
#[macro_export]
26+
macro_rules! visible_macro {
27+
() => {}
28+
}
29+
30+
macro_rules! non_visible_macro {
31+
() => {}
32+
}
33+
}
34+
35+
// @has 'foo/index.html'
36+
// @has - '//a[@href="struct.Bar.html"]' 'Bar'
37+
struct Bar;
38+
39+
const BAR: i32 = {
40+
// @!has - '//a[@href="fn.yo.html"]' 'yo'
41+
// @!has 'foo/fn.yo.html'
42+
fn yo() {}
43+
44+
// @!has 'foo/index.html' '//a[@href="trait.Foo.html"]' 'Foo'
45+
// @!has 'foo/trait.Foo.html'
46+
trait Foo {
47+
fn babar() {}
48+
}
49+
impl Foo for Bar {}
50+
51+
// @has 'foo/struct.Bar.html'
52+
// @has - '//*[@id="method.foo"]/*[@class="code-header"]' 'pub(crate) fn foo()'
53+
// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3
54+
// We now check that the `Foo` trait is not documented nor visible on `Bar` page.
55+
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Implementations'
56+
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Auto Trait Implementations'
57+
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Blanket Implementations'
58+
// @!has - '//*[@href="trait.Foo.html#method.babar"]/*[@class="code-header"]' 'fn babar()'
59+
impl Bar {
60+
fn foo() {}
61+
}
62+
63+
1
64+
};

0 commit comments

Comments
 (0)