Skip to content

Commit 5b654a7

Browse files
Fix handling of items inside a doc(hidden) block
1 parent 3468548 commit 5b654a7

File tree

3 files changed

+66
-34
lines changed

3 files changed

+66
-34
lines changed

src/librustdoc/clean/mod.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -2225,21 +2225,17 @@ fn clean_maybe_renamed_item<'tcx>(
22252225
get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs);
22262226
}
22272227

2228-
if !extra_attrs.is_empty() {
2228+
let mut item = if !extra_attrs.is_empty() {
22292229
extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
22302230
let attrs = Attributes::from_ast(&extra_attrs);
22312231
let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
22322232

2233-
vec![Item::from_def_id_and_attrs_and_parts(
2234-
def_id,
2235-
Some(name),
2236-
kind,
2237-
Box::new(attrs),
2238-
cfg,
2239-
)]
2233+
Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg)
22402234
} else {
2241-
vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
2242-
}
2235+
Item::from_def_id_and_parts(def_id, Some(name), kind, cx)
2236+
};
2237+
item.inline_stmt_id = import_id.map(|def_id| def_id.to_def_id());
2238+
vec![item]
22432239
})
22442240
}
22452241

src/librustdoc/passes/strip_hidden.rs

+54-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
//! Strip all doc(hidden) items from the output.
2+
3+
use rustc_middle::ty::TyCtxt;
24
use rustc_span::symbol::sym;
35
use std::mem;
46

@@ -7,6 +9,7 @@ use crate::clean::{Item, ItemIdSet, NestedAttributesExt};
79
use crate::core::DocContext;
810
use crate::fold::{strip_item, DocFolder};
911
use crate::passes::{ImplStripper, Pass};
12+
use crate::visit_ast::inherits_doc_hidden;
1013

1114
pub(crate) const STRIP_HIDDEN: Pass = Pass {
1215
name: "strip-hidden",
@@ -21,7 +24,12 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
2124

2225
// strip all #[doc(hidden)] items
2326
let krate = {
24-
let mut stripper = Stripper { retained: &mut retained, update_retained: true };
27+
let mut stripper = Stripper {
28+
retained: &mut retained,
29+
update_retained: true,
30+
tcx: cx.tcx,
31+
is_in_hidden_item: false,
32+
};
2533
stripper.fold_crate(krate)
2634
};
2735

@@ -36,14 +44,38 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
3644
stripper.fold_crate(krate)
3745
}
3846

39-
struct Stripper<'a> {
47+
struct Stripper<'a, 'tcx> {
4048
retained: &'a mut ItemIdSet,
4149
update_retained: bool,
50+
tcx: TyCtxt<'tcx>,
51+
is_in_hidden_item: bool,
52+
}
53+
54+
impl<'a, 'tcx> Stripper<'a, 'tcx> {
55+
fn set_is_in_hidden_item_and_fold(&mut self, is_in_hidden_item: bool, i: Item) -> Item {
56+
let prev = self.is_in_hidden_item;
57+
self.is_in_hidden_item |= is_in_hidden_item;
58+
let ret = self.fold_item_recur(i);
59+
self.is_in_hidden_item = prev;
60+
ret
61+
}
4262
}
4363

44-
impl<'a> DocFolder for Stripper<'a> {
64+
impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
4565
fn fold_item(&mut self, i: Item) -> Option<Item> {
46-
if i.attrs.lists(sym::doc).has_word(sym::hidden) {
66+
let has_doc_hidden = i.attrs.lists(sym::doc).has_word(sym::hidden);
67+
let mut is_hidden = self.is_in_hidden_item || has_doc_hidden;
68+
if !is_hidden && i.inline_stmt_id.is_none() {
69+
// We don't need to check if it's coming from a reexport since the reexport itself was
70+
// already checked.
71+
is_hidden = i
72+
.item_id
73+
.as_def_id()
74+
.and_then(|def_id| def_id.as_local())
75+
.map(|def_id| inherits_doc_hidden(self.tcx, def_id))
76+
.unwrap_or(false);
77+
}
78+
if is_hidden {
4779
debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
4880
// Use a dedicated hidden item for fields, variants, and modules.
4981
// We need to keep private fields and variants, so that the docs
@@ -53,23 +85,31 @@ impl<'a> DocFolder for Stripper<'a> {
5385
// module it's defined in. Both of these are marked "stripped," and
5486
// not included in the final docs, but since they still have an effect
5587
// on the final doc, cannot be completely removed from the Clean IR.
56-
match *i.kind {
88+
return match *i.kind {
5789
clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
5890
// We need to recurse into stripped modules to
5991
// strip things like impl methods but when doing so
6092
// we must not add any items to the `retained` set.
6193
let old = mem::replace(&mut self.update_retained, false);
62-
let ret = strip_item(self.fold_item_recur(i));
94+
let ret = strip_item(self.set_is_in_hidden_item_and_fold(true, i));
6395
self.update_retained = old;
64-
return Some(ret);
96+
Some(ret)
97+
}
98+
_ => {
99+
let ret = self.set_is_in_hidden_item_and_fold(true, i);
100+
if has_doc_hidden {
101+
// If the item itself has `#[doc(hidden)]`, then we simply remove it.
102+
None
103+
} else {
104+
// However if it's a "descendant" of a `#[doc(hidden)]` item, then we strip it.
105+
Some(strip_item(ret))
106+
}
65107
}
66-
_ => return None,
67-
}
68-
} else {
69-
if self.update_retained {
70-
self.retained.insert(i.item_id);
71-
}
108+
};
109+
}
110+
if self.update_retained {
111+
self.retained.insert(i.item_id);
72112
}
73-
Some(self.fold_item_recur(i))
113+
Some(self.set_is_in_hidden_item_and_fold(is_hidden, i))
74114
}
75115
}

src/librustdoc/visit_ast.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
187187
}
188188
}
189189
self.inside_public_path = orig_inside_public_path;
190+
debug!("Leaving module {:?}", m);
190191
}
191192

192193
/// Tries to resolve the target of a `pub use` statement and inlines the
@@ -290,7 +291,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
290291
&mut self,
291292
item: &'tcx hir::Item<'_>,
292293
renamed: Option<Symbol>,
293-
parent_id: Option<LocalDefId>,
294+
import_id: Option<LocalDefId>,
294295
) -> bool {
295296
debug!("visiting item {:?}", item);
296297
let name = renamed.unwrap_or(item.ident.name);
@@ -347,7 +348,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
347348
}
348349
}
349350

350-
self.add_to_current_mod(item, renamed, parent_id);
351+
self.add_to_current_mod(item, renamed, import_id);
351352
}
352353
}
353354
hir::ItemKind::Macro(ref macro_def, _) => {
@@ -383,13 +384,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
383384
| hir::ItemKind::Static(..)
384385
| hir::ItemKind::Trait(..)
385386
| hir::ItemKind::TraitAlias(..) => {
386-
self.add_to_current_mod(item, renamed, parent_id);
387+
self.add_to_current_mod(item, renamed, import_id);
387388
}
388389
hir::ItemKind::Const(..) => {
389390
// Underscore constants do not correspond to a nameable item and
390391
// so are never useful in documentation.
391392
if name != kw::Underscore {
392-
self.add_to_current_mod(item, renamed, parent_id);
393+
self.add_to_current_mod(item, renamed, import_id);
393394
}
394395
}
395396
hir::ItemKind::Impl(impl_) => {
@@ -437,12 +438,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
437438
}
438439

439440
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
440-
let parent_id = if self.modules.len() > 1 {
441-
Some(self.modules[self.modules.len() - 2].def_id)
442-
} else {
443-
None
444-
};
445-
if self.visit_item_inner(i, None, parent_id) {
441+
if self.visit_item_inner(i, None, None) {
446442
walk_item(self, i);
447443
}
448444
}

0 commit comments

Comments
 (0)