Skip to content

Commit 1d643e1

Browse files
authored
Rollup merge of #112108 - GuillaumeGomez:reexport-doc-hidden-private, r=notriddle
Fix re-export of doc hidden item inside private item not displayed This PR fixes this bug: ```rust mod private_module { #[doc(hidden)] pub struct Public; } pub use crate::private_module::Public as Foo; ``` `pub use crate::private_module::Public as Foo;` should be visible in the generated doc (and not inlined!) but currently isn't. This PR fixes it. r? `@notriddle`
2 parents 88160ab + 9906504 commit 1d643e1

File tree

2 files changed

+48
-25
lines changed

2 files changed

+48
-25
lines changed

src/librustdoc/visit_ast.rs

+32-25
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
267267
let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline)
268268
|| use_attrs.lists(sym::doc).has_word(sym::hidden);
269269

270+
if is_no_inline {
271+
return false;
272+
}
273+
270274
// For cross-crate impl inlining we need to know whether items are
271275
// reachable in documentation -- a previously unreachable item can be
272276
// made reachable by cross-crate inlining which we're checking here.
@@ -281,31 +285,38 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
281285
};
282286

283287
let is_private = !self.cx.cache.effective_visibilities.is_directly_public(tcx, ori_res_did);
284-
let is_hidden = inherits_doc_hidden(tcx, res_did, None);
288+
let is_hidden = tcx.is_doc_hidden(ori_res_did);
289+
let item = tcx.hir().get_by_def_id(res_did);
285290

286-
// Only inline if requested or if the item would otherwise be stripped.
287-
if (!please_inline && !is_private && !is_hidden) || is_no_inline {
288-
return false;
289-
}
290-
291-
if !please_inline &&
292-
let Some(item_def_id) = reexport_chain(tcx, def_id, res_did).iter()
291+
if !please_inline {
292+
let inherits_hidden = inherits_doc_hidden(tcx, res_did, None);
293+
// Only inline if requested or if the item would otherwise be stripped.
294+
//
295+
// If it's a doc hidden module, we need to keep it in case some of its inner items
296+
// are re-exported.
297+
if (!is_private && !inherits_hidden) || (
298+
is_hidden &&
299+
!matches!(item, Node::Item(&hir::Item { kind: hir::ItemKind::Mod(_), .. }))
300+
) {
301+
return false;
302+
} else if let Some(item_def_id) = reexport_chain(tcx, def_id, res_did).iter()
293303
.flat_map(|reexport| reexport.id()).map(|id| id.expect_local())
294304
.chain(iter::once(res_did)).nth(1) &&
295-
item_def_id != def_id &&
296-
self
297-
.cx
298-
.cache
299-
.effective_visibilities
300-
.is_directly_public(tcx, item_def_id.to_def_id()) &&
301-
!inherits_doc_hidden(tcx, item_def_id, None)
302-
{
303-
// The imported item is public and not `doc(hidden)` so no need to inline it.
304-
return false;
305+
item_def_id != def_id &&
306+
self
307+
.cx
308+
.cache
309+
.effective_visibilities
310+
.is_directly_public(tcx, item_def_id.to_def_id()) &&
311+
!inherits_doc_hidden(tcx, item_def_id, None)
312+
{
313+
// The imported item is public and not `doc(hidden)` so no need to inline it.
314+
return false;
315+
}
305316
}
306317

307318
let is_bang_macro = matches!(
308-
tcx.hir().get_by_def_id(res_did),
319+
item,
309320
Node::Item(&hir::Item { kind: hir::ItemKind::Macro(_, MacroKind::Bang), .. })
310321
);
311322

@@ -317,12 +328,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
317328
// Bang macros are handled a bit on their because of how they are handled by the
318329
// compiler. If they have `#[doc(hidden)]` and the re-export doesn't have
319330
// `#[doc(inline)]`, then we don't inline it.
320-
Node::Item(_)
321-
if is_bang_macro
322-
&& !please_inline
323-
&& renamed.is_some()
324-
&& self.cx.tcx.is_doc_hidden(ori_res_did) =>
325-
{
331+
Node::Item(_) if is_bang_macro && !please_inline && renamed.is_some() && is_hidden => {
326332
return false;
327333
}
328334
Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => {
@@ -455,6 +461,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
455461
is_glob,
456462
please_inline,
457463
) {
464+
debug!("Inlining {:?}", item.owner_id.def_id);
458465
continue;
459466
}
460467
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// This test ensures that a re-export of `#[doc(hidden)]` item inside a private
2+
// module will still be displayed (the re-export, not the item).
3+
4+
#![crate_name = "foo"]
5+
6+
mod private_module {
7+
#[doc(hidden)]
8+
pub struct Public;
9+
}
10+
11+
// @has 'foo/index.html'
12+
// @has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;'
13+
pub use crate::private_module::Public as Foo;
14+
// Glob re-exports with no visible items should not be displayed.
15+
// @count - '//*[@class="item-table"]/li' 1
16+
pub use crate::private_module::*;

0 commit comments

Comments
 (0)