Add missing impl blocks for item reexported from private mod in JSON output

This commit is contained in:
Guillaume Gomez 2022-10-27 21:48:34 +02:00
parent 607878d069
commit f0234f1976

View File

@ -1,9 +1,11 @@
//! A collection of utility functions for the `strip_*` passes. //! A collection of utility functions for the `strip_*` passes.
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_span::symbol::sym;
use std::mem; use std::mem;
use crate::clean::{self, Item, ItemId, ItemIdSet}; use crate::clean::{self, Item, ItemId, ItemIdSet, NestedAttributesExt};
use crate::fold::{strip_item, DocFolder}; use crate::fold::{strip_item, DocFolder};
use crate::formats::cache::Cache; use crate::formats::cache::Cache;
@ -151,6 +153,22 @@ pub(crate) struct ImplStripper<'a> {
pub(crate) document_private: bool, pub(crate) document_private: bool,
} }
impl<'a> ImplStripper<'a> {
#[inline]
fn should_keep_impl(&self, item: &Item, for_def_id: DefId) -> bool {
if !for_def_id.is_local() || self.retained.contains(&for_def_id.into()) {
true
} else if self.is_json_output {
// If the "for" item is exported and the impl block isn't `#[doc(hidden)]`, then we
// need to keep it.
self.cache.access_levels.is_exported(for_def_id)
&& !item.attrs.lists(sym::doc).has_word(sym::hidden)
} else {
false
}
}
}
impl<'a> DocFolder for ImplStripper<'a> { impl<'a> DocFolder for ImplStripper<'a> {
fn fold_item(&mut self, i: Item) -> Option<Item> { fn fold_item(&mut self, i: Item) -> Option<Item> {
if let clean::ImplItem(ref imp) = *i.kind { if let clean::ImplItem(ref imp) = *i.kind {
@ -178,15 +196,17 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
return None; return None;
} }
} }
// Because we don't inline in `maybe_inline_local` if the output format is JSON,
// we need to make a special check for JSON output: we want to keep it unless it has
// a `#[doc(hidden)]` attribute if the `for_` type is exported.
if let Some(did) = imp.for_.def_id(self.cache) { if let Some(did) = imp.for_.def_id(self.cache) {
if did.is_local() && !imp.for_.is_assoc_ty() && !self.retained.contains(&did.into()) if !imp.for_.is_assoc_ty() && !self.should_keep_impl(&i, did) {
{
debug!("ImplStripper: impl item for stripped type; removing"); debug!("ImplStripper: impl item for stripped type; removing");
return None; return None;
} }
} }
if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) { if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) {
if did.is_local() && !self.retained.contains(&did.into()) { if !self.should_keep_impl(&i, did) {
debug!("ImplStripper: impl item for stripped trait; removing"); debug!("ImplStripper: impl item for stripped trait; removing");
return None; return None;
} }
@ -194,7 +214,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) { if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
for typaram in generics { for typaram in generics {
if let Some(did) = typaram.def_id(self.cache) { if let Some(did) = typaram.def_id(self.cache) {
if did.is_local() && !self.retained.contains(&did.into()) { if !self.should_keep_impl(&i, did) {
debug!( debug!(
"ImplStripper: stripped item in trait's generics; removing impl" "ImplStripper: stripped item in trait's generics; removing impl"
); );