From 4f9fe856a25ab29345b90e7725509e9ee38a37be Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:41 +0200 Subject: Adding upstream version 1.69.0+dfsg1. Signed-off-by: Daniel Baumann --- src/librustdoc/passes/strip_hidden.rs | 117 ++++++++++++++++++++++++++-------- 1 file changed, 91 insertions(+), 26 deletions(-) (limited to 'src/librustdoc/passes/strip_hidden.rs') diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index e07a788a7..890b3e8d6 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,40 +44,97 @@ 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 + } + + /// In case `i` is a non-hidden impl block, then we special-case it by changing the value + /// of `is_in_hidden_item` to `true` because the impl children inherit its visibility. + fn recurse_in_impl_or_exported_macro(&mut self, i: Item) -> Item { + let prev = mem::replace(&mut self.is_in_hidden_item, false); + 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) { - 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 - // can show a placeholder "// some variants omitted". We need to keep - // private modules, because they can contain impl blocks, and impl - // block privacy is inherited from the type and trait, not from the - // 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 { - 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)); - self.update_retained = old; - return Some(ret); - } - _ => return None, + let has_doc_hidden = i.attrs.lists(sym::doc).has_word(sym::hidden); + let is_impl_or_exported_macro = match *i.kind { + clean::ImplItem(..) => true, + // If the macro has the `#[macro_export]` attribute, it means it's accessible at the + // crate level so it should be handled differently. + clean::MacroItem(..) => { + i.attrs.other_attrs.iter().any(|attr| attr.has_name(sym::macro_export)) } - } else { + _ => false, + }; + let mut is_hidden = has_doc_hidden; + if !is_impl_or_exported_macro { + 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 { if self.update_retained { self.retained.insert(i.item_id); } + return Some(if is_impl_or_exported_macro { + self.recurse_in_impl_or_exported_macro(i) + } else { + self.set_is_in_hidden_item_and_fold(false, i) + }); + } + 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 + // can show a placeholder "// some variants omitted". We need to keep + // private modules, because they can contain impl blocks, and impl + // block privacy is inherited from the type and trait, not from the + // 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 { + 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.set_is_in_hidden_item_and_fold(true, i)); + self.update_retained = old; + Some(ret) + } + _ => { + 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)) } } -- cgit v1.2.3