Skip to content

Commit 879f8de

Browse files
Correctly handle associated items of a trait inside a #[doc(hidden)] item
1 parent b778688 commit 879f8de

File tree

3 files changed

+35
-14
lines changed

3 files changed

+35
-14
lines changed

src/librustdoc/formats/cache.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,13 @@ impl Cache {
195195
impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
196196
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
197197
if item.item_id.is_local() {
198-
debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.item_id);
198+
let is_stripped = matches!(*item.kind, clean::ItemKind::StrippedItem(..));
199+
debug!(
200+
"folding {} (stripped: {is_stripped:?}) \"{:?}\", id {:?}",
201+
item.type_(),
202+
item.name,
203+
item.item_id
204+
);
199205
}
200206

201207
// If this is a stripped module,

src/librustdoc/passes/strip_hidden.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Strip all doc(hidden) items from the output.
22
3+
use rustc_hir::def_id::LocalDefId;
34
use rustc_middle::ty::TyCtxt;
45
use rustc_span::symbol::sym;
56
use std::mem;
@@ -29,6 +30,7 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
2930
update_retained: true,
3031
tcx: cx.tcx,
3132
is_in_hidden_item: false,
33+
last_reexport: None,
3234
};
3335
stripper.fold_crate(krate)
3436
};
@@ -49,13 +51,24 @@ struct Stripper<'a, 'tcx> {
4951
update_retained: bool,
5052
tcx: TyCtxt<'tcx>,
5153
is_in_hidden_item: bool,
54+
last_reexport: Option<LocalDefId>,
5255
}
5356

5457
impl<'a, 'tcx> Stripper<'a, 'tcx> {
58+
fn set_last_reexport_then_fold_item(&mut self, i: Item) -> Item {
59+
let prev_from_reexport = self.last_reexport;
60+
if i.inline_stmt_id.is_some() {
61+
self.last_reexport = i.item_id.as_def_id().and_then(|def_id| def_id.as_local());
62+
}
63+
let ret = self.fold_item_recur(i);
64+
self.last_reexport = prev_from_reexport;
65+
ret
66+
}
67+
5568
fn set_is_in_hidden_item_and_fold(&mut self, is_in_hidden_item: bool, i: Item) -> Item {
5669
let prev = self.is_in_hidden_item;
5770
self.is_in_hidden_item |= is_in_hidden_item;
58-
let ret = self.fold_item_recur(i);
71+
let ret = self.set_last_reexport_then_fold_item(i);
5972
self.is_in_hidden_item = prev;
6073
ret
6174
}
@@ -64,7 +77,7 @@ impl<'a, 'tcx> Stripper<'a, 'tcx> {
6477
/// of `is_in_hidden_item` to `true` because the impl children inherit its visibility.
6578
fn recurse_in_impl_or_exported_macro(&mut self, i: Item) -> Item {
6679
let prev = mem::replace(&mut self.is_in_hidden_item, false);
67-
let ret = self.fold_item_recur(i);
80+
let ret = self.set_last_reexport_then_fold_item(i);
6881
self.is_in_hidden_item = prev;
6982
ret
7083
}
@@ -86,13 +99,20 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
8699
if !is_impl_or_exported_macro {
87100
is_hidden = self.is_in_hidden_item || has_doc_hidden;
88101
if !is_hidden && i.inline_stmt_id.is_none() {
89-
// We don't need to check if it's coming from a reexport since the reexport itself was
90-
// already checked.
102+
// `i.inline_stmt_id` is `Some` if the item is directly reexported. If it is, we
103+
// don't need to check it, because the reexport itself was already checked.
104+
//
105+
// If this item is the child of a reexported module, `self.last_reexport` will be
106+
// `Some` even though `i.inline_stmt_id` is `None`. Hiddenness inheritance needs to
107+
// account for the possibility that an item's true parent module is hidden, but it's
108+
// inlined into a visible module true. This code shouldn't be reachable if the
109+
// module's reexport is itself hidden, for the same reason it doesn't need to be
110+
// checked if `i.inline_stmt_id` is Some: hidden reexports are never inlined.
91111
is_hidden = i
92112
.item_id
93113
.as_def_id()
94114
.and_then(|def_id| def_id.as_local())
95-
.map(|def_id| inherits_doc_hidden(self.tcx, def_id))
115+
.map(|def_id| inherits_doc_hidden(self.tcx, def_id, self.last_reexport))
96116
.unwrap_or(false);
97117
}
98118
}

src/librustdoc/visit_ast.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -500,19 +500,14 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
500500

501501
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
502502
self.visit_item_inner(i, None, None);
503-
let new_value = if self.is_importable_from_parent {
504-
matches!(
503+
let new_value = self.is_importable_from_parent
504+
&& matches!(
505505
i.kind,
506506
hir::ItemKind::Mod(..)
507507
| hir::ItemKind::ForeignMod { .. }
508508
| hir::ItemKind::Impl(..)
509509
| 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-
};
510+
);
516511
let prev = mem::replace(&mut self.is_importable_from_parent, new_value);
517512
walk_item(self, i);
518513
self.is_importable_from_parent = prev;

0 commit comments

Comments
 (0)