diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3cb6ad10e72..ee9d0e829f0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2225,21 +2225,17 @@ fn clean_maybe_renamed_item<'tcx>( get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs); } - if !extra_attrs.is_empty() { + let mut item = if !extra_attrs.is_empty() { extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id)); let attrs = Attributes::from_ast(&extra_attrs); let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg); - vec![Item::from_def_id_and_attrs_and_parts( - def_id, - Some(name), - kind, - Box::new(attrs), - cfg, - )] + Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg) } else { - vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)] - } + Item::from_def_id_and_parts(def_id, Some(name), kind, cx) + }; + item.inline_stmt_id = import_id.map(|def_id| def_id.to_def_id()); + vec![item] }) } diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index e07a788a72a..cfd2171395c 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -1,4 +1,6 @@ //! Strip all doc(hidden) items from the output. + +use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; use std::mem; @@ -7,6 +9,7 @@ use crate::clean::{Item, ItemIdSet, NestedAttributesExt}; use crate::core::DocContext; use crate::fold::{strip_item, DocFolder}; use crate::passes::{ImplStripper, Pass}; +use crate::visit_ast::inherits_doc_hidden; pub(crate) const STRIP_HIDDEN: Pass = Pass { name: "strip-hidden", @@ -21,7 +24,12 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea // strip all #[doc(hidden)] items let krate = { - let mut stripper = Stripper { retained: &mut retained, update_retained: true }; + let mut stripper = Stripper { + retained: &mut retained, + update_retained: true, + tcx: cx.tcx, + is_in_hidden_item: false, + }; stripper.fold_crate(krate) }; @@ -36,14 +44,38 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea stripper.fold_crate(krate) } -struct Stripper<'a> { +struct Stripper<'a, 'tcx> { retained: &'a mut ItemIdSet, update_retained: bool, + tcx: TyCtxt<'tcx>, + is_in_hidden_item: bool, } -impl<'a> DocFolder for Stripper<'a> { +impl<'a, 'tcx> Stripper<'a, 'tcx> { + fn set_is_in_hidden_item_and_fold(&mut self, is_in_hidden_item: bool, i: Item) -> Item { + let prev = self.is_in_hidden_item; + self.is_in_hidden_item |= is_in_hidden_item; + let ret = self.fold_item_recur(i); + self.is_in_hidden_item = prev; + ret + } +} + +impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { fn fold_item(&mut self, i: Item) -> Option { - if i.attrs.lists(sym::doc).has_word(sym::hidden) { + let has_doc_hidden = i.attrs.lists(sym::doc).has_word(sym::hidden); + let mut is_hidden = self.is_in_hidden_item || has_doc_hidden; + if !is_hidden && i.inline_stmt_id.is_none() { + // We don't need to check if it's coming from a reexport since the reexport itself was + // already checked. + is_hidden = i + .item_id + .as_def_id() + .and_then(|def_id| def_id.as_local()) + .map(|def_id| inherits_doc_hidden(self.tcx, def_id)) + .unwrap_or(false); + } + if is_hidden { debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name); // Use a dedicated hidden item for fields, variants, and modules. // We need to keep private fields and variants, so that the docs @@ -53,23 +85,31 @@ impl<'a> DocFolder for Stripper<'a> { // module it's defined in. Both of these are marked "stripped," and // not included in the final docs, but since they still have an effect // on the final doc, cannot be completely removed from the Clean IR. - match *i.kind { + return match *i.kind { clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => { // We need to recurse into stripped modules to // strip things like impl methods but when doing so // we must not add any items to the `retained` set. let old = mem::replace(&mut self.update_retained, false); - let ret = strip_item(self.fold_item_recur(i)); + let ret = strip_item(self.set_is_in_hidden_item_and_fold(true, i)); self.update_retained = old; - return Some(ret); + Some(ret) } - _ => return None, - } - } else { - if self.update_retained { - self.retained.insert(i.item_id); - } + _ => { + let ret = self.set_is_in_hidden_item_and_fold(true, i); + if has_doc_hidden { + // If the item itself has `#[doc(hidden)]`, then we simply remove it. + None + } else { + // However if it's a "descendant" of a `#[doc(hidden)]` item, then we strip it. + Some(strip_item(ret)) + } + } + }; } - Some(self.fold_item_recur(i)) + if self.update_retained { + self.retained.insert(i.item_id); + } + Some(self.set_is_in_hidden_item_and_fold(is_hidden, i)) } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c95ca6727b5..2d2afb83f9d 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -187,6 +187,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } self.inside_public_path = orig_inside_public_path; + debug!("Leaving module {:?}", m); } /// Tries to resolve the target of a `pub use` statement and inlines the @@ -290,7 +291,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { &mut self, item: &'tcx hir::Item<'_>, renamed: Option, - parent_id: Option, + import_id: Option, ) -> bool { debug!("visiting item {:?}", item); let name = renamed.unwrap_or(item.ident.name); @@ -347,7 +348,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - self.add_to_current_mod(item, renamed, parent_id); + self.add_to_current_mod(item, renamed, import_id); } } hir::ItemKind::Macro(ref macro_def, _) => { @@ -383,13 +384,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { | hir::ItemKind::Static(..) | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => { - self.add_to_current_mod(item, renamed, parent_id); + self.add_to_current_mod(item, renamed, import_id); } hir::ItemKind::Const(..) => { // Underscore constants do not correspond to a nameable item and // so are never useful in documentation. if name != kw::Underscore { - self.add_to_current_mod(item, renamed, parent_id); + self.add_to_current_mod(item, renamed, import_id); } } hir::ItemKind::Impl(impl_) => { @@ -437,12 +438,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> { } fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) { - let parent_id = if self.modules.len() > 1 { - Some(self.modules[self.modules.len() - 2].def_id) - } else { - None - }; - if self.visit_item_inner(i, None, parent_id) { + if self.visit_item_inner(i, None, None) { walk_item(self, i); } }