Skip to content

Commit f0234f1

Browse files
Add missing impl blocks for item reexported from private mod in JSON output
1 parent 607878d commit f0234f1

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

src/librustdoc/passes/stripper.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
//! A collection of utility functions for the `strip_*` passes.
22
use rustc_hir::def_id::DefId;
33
use rustc_middle::middle::privacy::EffectiveVisibilities;
4+
use rustc_span::symbol::sym;
5+
46
use std::mem;
57

6-
use crate::clean::{self, Item, ItemId, ItemIdSet};
8+
use crate::clean::{self, Item, ItemId, ItemIdSet, NestedAttributesExt};
79
use crate::fold::{strip_item, DocFolder};
810
use crate::formats::cache::Cache;
911

@@ -151,6 +153,22 @@ pub(crate) struct ImplStripper<'a> {
151153
pub(crate) document_private: bool,
152154
}
153155

156+
impl<'a> ImplStripper<'a> {
157+
#[inline]
158+
fn should_keep_impl(&self, item: &Item, for_def_id: DefId) -> bool {
159+
if !for_def_id.is_local() || self.retained.contains(&for_def_id.into()) {
160+
true
161+
} else if self.is_json_output {
162+
// If the "for" item is exported and the impl block isn't `#[doc(hidden)]`, then we
163+
// need to keep it.
164+
self.cache.access_levels.is_exported(for_def_id)
165+
&& !item.attrs.lists(sym::doc).has_word(sym::hidden)
166+
} else {
167+
false
168+
}
169+
}
170+
}
171+
154172
impl<'a> DocFolder for ImplStripper<'a> {
155173
fn fold_item(&mut self, i: Item) -> Option<Item> {
156174
if let clean::ImplItem(ref imp) = *i.kind {
@@ -178,23 +196,25 @@ impl<'a> DocFolder for ImplStripper<'a> {
178196
return None;
179197
}
180198
}
199+
// Because we don't inline in `maybe_inline_local` if the output format is JSON,
200+
// we need to make a special check for JSON output: we want to keep it unless it has
201+
// a `#[doc(hidden)]` attribute if the `for_` type is exported.
181202
if let Some(did) = imp.for_.def_id(self.cache) {
182-
if did.is_local() && !imp.for_.is_assoc_ty() && !self.retained.contains(&did.into())
183-
{
203+
if !imp.for_.is_assoc_ty() && !self.should_keep_impl(&i, did) {
184204
debug!("ImplStripper: impl item for stripped type; removing");
185205
return None;
186206
}
187207
}
188208
if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) {
189-
if did.is_local() && !self.retained.contains(&did.into()) {
209+
if !self.should_keep_impl(&i, did) {
190210
debug!("ImplStripper: impl item for stripped trait; removing");
191211
return None;
192212
}
193213
}
194214
if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
195215
for typaram in generics {
196216
if let Some(did) = typaram.def_id(self.cache) {
197-
if did.is_local() && !self.retained.contains(&did.into()) {
217+
if !self.should_keep_impl(&i, did) {
198218
debug!(
199219
"ImplStripper: stripped item in trait's generics; removing impl"
200220
);

0 commit comments

Comments
 (0)