]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/passes/stripper.rs
Rollup merge of #93480 - est31:remove_unstable_deprecated, r=Mark-Simulacrum
[rust.git] / src / librustdoc / passes / stripper.rs
1 //! A collection of utility functions for the `strip_*` passes.
2 use rustc_hir::def_id::DefId;
3 use rustc_middle::middle::privacy::AccessLevels;
4 use std::mem;
5
6 use crate::clean::{self, Item, ItemIdSet};
7 use crate::fold::{strip_item, DocFolder};
8 use crate::formats::cache::Cache;
9
10 crate struct Stripper<'a> {
11     crate retained: &'a mut ItemIdSet,
12     crate access_levels: &'a AccessLevels<DefId>,
13     crate update_retained: bool,
14 }
15
16 impl<'a> DocFolder for Stripper<'a> {
17     fn fold_item(&mut self, i: Item) -> Option<Item> {
18         match *i.kind {
19             clean::StrippedItem(..) => {
20                 // We need to recurse into stripped modules to strip things
21                 // like impl methods but when doing so we must not add any
22                 // items to the `retained` set.
23                 debug!("Stripper: recursing into stripped {:?} {:?}", i.type_(), i.name);
24                 let old = mem::replace(&mut self.update_retained, false);
25                 let ret = self.fold_item_recur(i);
26                 self.update_retained = old;
27                 return Some(ret);
28             }
29             // These items can all get re-exported
30             clean::OpaqueTyItem(..)
31             | clean::TypedefItem(..)
32             | clean::StaticItem(..)
33             | clean::StructItem(..)
34             | clean::EnumItem(..)
35             | clean::TraitItem(..)
36             | clean::FunctionItem(..)
37             | clean::VariantItem(..)
38             | clean::MethodItem(..)
39             | clean::ForeignFunctionItem(..)
40             | clean::ForeignStaticItem(..)
41             | clean::ConstantItem(..)
42             | clean::UnionItem(..)
43             | clean::AssocConstItem(..)
44             | clean::TraitAliasItem(..)
45             | clean::MacroItem(..)
46             | clean::ForeignTypeItem => {
47                 if i.def_id.is_local() && !self.access_levels.is_exported(i.def_id.expect_def_id())
48                 {
49                     debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
50                     return None;
51                 }
52             }
53
54             clean::StructFieldItem(..) => {
55                 if !i.visibility.is_public() {
56                     return Some(strip_item(i));
57                 }
58             }
59
60             clean::ModuleItem(..) => {
61                 if i.def_id.is_local() && !i.visibility.is_public() {
62                     debug!("Stripper: stripping module {:?}", i.name);
63                     let old = mem::replace(&mut self.update_retained, false);
64                     let ret = strip_item(self.fold_item_recur(i));
65                     self.update_retained = old;
66                     return Some(ret);
67                 }
68             }
69
70             // handled in the `strip-priv-imports` pass
71             clean::ExternCrateItem { .. } | clean::ImportItem(..) => {}
72
73             clean::ImplItem(..) => {}
74
75             // tymethods have no control over privacy
76             clean::TyMethodItem(..) => {}
77
78             // Proc-macros are always public
79             clean::ProcMacroItem(..) => {}
80
81             // Primitives are never stripped
82             clean::PrimitiveItem(..) => {}
83
84             // Associated types are never stripped
85             clean::AssocTypeItem(..) => {}
86
87             // Keywords are never stripped
88             clean::KeywordItem(..) => {}
89         }
90
91         let fastreturn = match *i.kind {
92             // nothing left to do for traits (don't want to filter their
93             // methods out, visibility controlled by the trait)
94             clean::TraitItem(..) => true,
95
96             // implementations of traits are always public.
97             clean::ImplItem(ref imp) if imp.trait_.is_some() => true,
98             // Variant fields have inherited visibility
99             clean::VariantItem(clean::Variant::Struct(..) | clean::Variant::Tuple(..)) => true,
100             _ => false,
101         };
102
103         let i = if fastreturn {
104             if self.update_retained {
105                 self.retained.insert(i.def_id);
106             }
107             return Some(i);
108         } else {
109             self.fold_item_recur(i)
110         };
111
112         if self.update_retained {
113             self.retained.insert(i.def_id);
114         }
115         Some(i)
116     }
117 }
118
119 /// This stripper discards all impls which reference stripped items
120 crate struct ImplStripper<'a> {
121     crate retained: &'a ItemIdSet,
122     crate cache: &'a Cache,
123 }
124
125 impl<'a> DocFolder for ImplStripper<'a> {
126     fn fold_item(&mut self, i: Item) -> Option<Item> {
127         if let clean::ImplItem(ref imp) = *i.kind {
128             // emptied none trait impls can be stripped
129             if imp.trait_.is_none() && imp.items.is_empty() {
130                 return None;
131             }
132             if let Some(did) = imp.for_.def_id(self.cache) {
133                 if did.is_local() && !imp.for_.is_assoc_ty() && !self.retained.contains(&did.into())
134                 {
135                     debug!("ImplStripper: impl item for stripped type; removing");
136                     return None;
137                 }
138             }
139             if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) {
140                 if did.is_local() && !self.retained.contains(&did.into()) {
141                     debug!("ImplStripper: impl item for stripped trait; removing");
142                     return None;
143                 }
144             }
145             if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
146                 for typaram in generics {
147                     if let Some(did) = typaram.def_id(self.cache) {
148                         if did.is_local() && !self.retained.contains(&did.into()) {
149                             debug!(
150                                 "ImplStripper: stripped item in trait's generics; removing impl"
151                             );
152                             return None;
153                         }
154                     }
155                 }
156             }
157         }
158         Some(self.fold_item_recur(i))
159     }
160 }
161
162 /// This stripper discards all private import statements (`use`, `extern crate`)
163 crate struct ImportStripper;
164
165 impl DocFolder for ImportStripper {
166     fn fold_item(&mut self, i: Item) -> Option<Item> {
167         match *i.kind {
168             clean::ExternCrateItem { .. } | clean::ImportItem(..) if !i.visibility.is_public() => {
169                 None
170             }
171             _ => Some(self.fold_item_recur(i)),
172         }
173     }
174 }