|
1 | 1 | //! A collection of utility functions for the `strip_*` passes.
|
2 | 2 | use rustc_hir::def_id::DefId;
|
3 | 3 | use rustc_middle::middle::privacy::EffectiveVisibilities;
|
| 4 | +use rustc_span::symbol::sym; |
| 5 | + |
4 | 6 | use std::mem;
|
5 | 7 |
|
6 |
| -use crate::clean::{self, Item, ItemId, ItemIdSet}; |
| 8 | +use crate::clean::{self, Item, ItemId, ItemIdSet, NestedAttributesExt}; |
7 | 9 | use crate::fold::{strip_item, DocFolder};
|
8 | 10 | use crate::formats::cache::Cache;
|
9 | 11 |
|
@@ -151,6 +153,22 @@ pub(crate) struct ImplStripper<'a> {
|
151 | 153 | pub(crate) document_private: bool,
|
152 | 154 | }
|
153 | 155 |
|
| 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.effective_visibilities.is_exported(for_def_id) |
| 165 | + && !item.attrs.lists(sym::doc).has_word(sym::hidden) |
| 166 | + } else { |
| 167 | + false |
| 168 | + } |
| 169 | + } |
| 170 | +} |
| 171 | + |
154 | 172 | impl<'a> DocFolder for ImplStripper<'a> {
|
155 | 173 | fn fold_item(&mut self, i: Item) -> Option<Item> {
|
156 | 174 | if let clean::ImplItem(ref imp) = *i.kind {
|
@@ -178,23 +196,25 @@ impl<'a> DocFolder for ImplStripper<'a> {
|
178 | 196 | return None;
|
179 | 197 | }
|
180 | 198 | }
|
| 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. |
181 | 202 | 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) { |
184 | 204 | debug!("ImplStripper: impl item for stripped type; removing");
|
185 | 205 | return None;
|
186 | 206 | }
|
187 | 207 | }
|
188 | 208 | 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) { |
190 | 210 | debug!("ImplStripper: impl item for stripped trait; removing");
|
191 | 211 | return None;
|
192 | 212 | }
|
193 | 213 | }
|
194 | 214 | if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
|
195 | 215 | for typaram in generics {
|
196 | 216 | 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) { |
198 | 218 | debug!(
|
199 | 219 | "ImplStripper: stripped item in trait's generics; removing impl"
|
200 | 220 | );
|
|
0 commit comments