]>
Commit | Line | Data |
---|---|---|
970d7e83 LB |
1 | // Finds items that are externally reachable, to determine which items |
2 | // need to have their metadata (and possibly their AST) serialized. | |
3 | // All items that can be referred to through an exported name are | |
4 | // reachable, and when a reachable thing is inline or generic, it | |
5 | // makes all other generics or inline functions that it references | |
6 | // reachable as well. | |
7 | ||
dfeec247 | 8 | use rustc_data_structures::fx::FxHashSet; |
dfeec247 XL |
9 | use rustc_hir as hir; |
10 | use rustc_hir::def::{DefKind, Res}; | |
11 | use rustc_hir::def_id::LOCAL_CRATE; | |
ba9703b0 XL |
12 | use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; |
13 | use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; | |
dfeec247 | 14 | use rustc_hir::itemlikevisit::ItemLikeVisitor; |
3dfed10e | 15 | use rustc_hir::Node; |
ba9703b0 XL |
16 | use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; |
17 | use rustc_middle::middle::privacy; | |
18 | use rustc_middle::ty::query::Providers; | |
3dfed10e | 19 | use rustc_middle::ty::{self, DefIdTree, TyCtxt}; |
f9f354fc | 20 | use rustc_session::config::CrateType; |
83c7162d | 21 | use rustc_target::spec::abi::Abi; |
970d7e83 | 22 | |
970d7e83 LB |
23 | // Returns true if the given item must be inlined because it may be |
24 | // monomorphized or it was marked with `#[inline]`. This will only return | |
25 | // true for functions. | |
f9f354fc | 26 | fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>, attrs: &CodegenFnAttrs) -> bool { |
0531ce1d | 27 | if attrs.requests_inline() { |
dfeec247 | 28 | return true; |
970d7e83 LB |
29 | } |
30 | ||
e74abb32 | 31 | match item.kind { |
ba9703b0 | 32 | hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => true, |
dfeec247 | 33 | hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => { |
6a06907d | 34 | let generics = tcx.generics_of(item.def_id); |
b7449926 | 35 | generics.requires_monomorphization(tcx) |
970d7e83 LB |
36 | } |
37 | _ => false, | |
38 | } | |
39 | } | |
40 | ||
416331ca XL |
41 | fn method_might_be_inlined( |
42 | tcx: TyCtxt<'_>, | |
dfeec247 | 43 | impl_item: &hir::ImplItem<'_>, |
ba9703b0 | 44 | impl_src: LocalDefId, |
dc9dc135 | 45 | ) -> bool { |
6a06907d XL |
46 | let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id().owner.to_def_id()); |
47 | let generics = tcx.generics_of(impl_item.def_id); | |
b7449926 | 48 | if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { |
dfeec247 | 49 | return true; |
1a4d82fc | 50 | } |
ba9703b0 | 51 | if let hir::ImplItemKind::Fn(method_sig, _) = &impl_item.kind { |
e1599b0c | 52 | if method_sig.header.is_const() { |
dfeec247 | 53 | return true; |
e1599b0c XL |
54 | } |
55 | } | |
3dfed10e | 56 | match tcx.hir().find(tcx.hir().local_def_id_to_hir_id(impl_src)) { |
f9f354fc XL |
57 | Some(Node::Item(item)) => item_might_be_inlined(tcx, &item, codegen_fn_attrs), |
58 | Some(..) | None => span_bug!(impl_item.span, "impl did is not an item"), | |
970d7e83 | 59 | } |
970d7e83 LB |
60 | } |
61 | ||
62 | // Information needed while computing reachability. | |
f035d41b | 63 | struct ReachableContext<'tcx> { |
970d7e83 | 64 | // The type context. |
dc9dc135 | 65 | tcx: TyCtxt<'tcx>, |
3dfed10e | 66 | maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, |
970d7e83 | 67 | // The set of items which must be exported in the linkage sense. |
3dfed10e | 68 | reachable_symbols: FxHashSet<LocalDefId>, |
970d7e83 LB |
69 | // A worklist of item IDs. Each item ID in this worklist will be inlined |
70 | // and will be scanned for further references. | |
3dfed10e XL |
71 | // FIXME(eddyb) benchmark if this would be faster as a `VecDeque`. |
72 | worklist: Vec<LocalDefId>, | |
1a4d82fc JJ |
73 | // Whether any output of this compilation is a library |
74 | any_library: bool, | |
970d7e83 LB |
75 | } |
76 | ||
f035d41b | 77 | impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> { |
ba9703b0 | 78 | type Map = intravisit::ErasedMap<'tcx>; |
dfeec247 | 79 | |
ba9703b0 | 80 | fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { |
32a655c1 SL |
81 | NestedVisitorMap::None |
82 | } | |
83 | ||
84 | fn visit_nested_body(&mut self, body: hir::BodyId) { | |
3dfed10e XL |
85 | let old_maybe_typeck_results = |
86 | self.maybe_typeck_results.replace(self.tcx.typeck_body(body)); | |
0731742a | 87 | let body = self.tcx.hir().body(body); |
32a655c1 | 88 | self.visit_body(body); |
3dfed10e | 89 | self.maybe_typeck_results = old_maybe_typeck_results; |
476ff2be | 90 | } |
970d7e83 | 91 | |
dfeec247 | 92 | fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { |
e74abb32 | 93 | let res = match expr.kind { |
3dfed10e XL |
94 | hir::ExprKind::Path(ref qpath) => { |
95 | Some(self.typeck_results().qpath_res(qpath, expr.hir_id)) | |
96 | } | |
dfeec247 | 97 | hir::ExprKind::MethodCall(..) => self |
3dfed10e | 98 | .typeck_results() |
dfeec247 XL |
99 | .type_dependent_def(expr.hir_id) |
100 | .map(|(kind, def_id)| Res::Def(kind, def_id)), | |
101 | _ => None, | |
476ff2be SL |
102 | }; |
103 | ||
3dfed10e XL |
104 | if let Some(res) = res { |
105 | if let Some(def_id) = res.opt_def_id().and_then(|def_id| def_id.as_local()) { | |
106 | if self.def_id_represents_local_inlined_item(def_id.to_def_id()) { | |
107 | self.worklist.push(def_id); | |
108 | } else { | |
109 | match res { | |
110 | // If this path leads to a constant, then we need to | |
111 | // recurse into the constant to continue finding | |
112 | // items that are reachable. | |
113 | Res::Def(DefKind::Const | DefKind::AssocConst, _) => { | |
114 | self.worklist.push(def_id); | |
115 | } | |
92a42be0 | 116 | |
3dfed10e XL |
117 | // If this wasn't a static, then the destination is |
118 | // surely reachable. | |
119 | _ => { | |
120 | self.reachable_symbols.insert(def_id); | |
476ff2be | 121 | } |
970d7e83 | 122 | } |
970d7e83 | 123 | } |
1a4d82fc | 124 | } |
1a4d82fc | 125 | } |
970d7e83 | 126 | |
92a42be0 | 127 | intravisit::walk_expr(self, expr) |
1a4d82fc JJ |
128 | } |
129 | } | |
970d7e83 | 130 | |
f035d41b | 131 | impl<'tcx> ReachableContext<'tcx> { |
3dfed10e | 132 | /// Gets the type-checking results for the current body. |
f035d41b XL |
133 | /// As this will ICE if called outside bodies, only call when working with |
134 | /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). | |
135 | #[track_caller] | |
3dfed10e XL |
136 | fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> { |
137 | self.maybe_typeck_results | |
138 | .expect("`ReachableContext::typeck_results` called outside of body") | |
f035d41b XL |
139 | } |
140 | ||
970d7e83 LB |
141 | // Returns true if the given def ID represents a local item that is |
142 | // eligible for inlining and false otherwise. | |
e9174d1e | 143 | fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool { |
f9f354fc | 144 | let hir_id = match def_id.as_local() { |
3dfed10e | 145 | Some(def_id) => self.tcx.hir().local_def_id_to_hir_id(def_id), |
dfeec247 XL |
146 | None => { |
147 | return false; | |
148 | } | |
b039eaaf | 149 | }; |
970d7e83 | 150 | |
dc9dc135 | 151 | match self.tcx.hir().find(hir_id) { |
dfeec247 XL |
152 | Some(Node::Item(item)) => match item.kind { |
153 | hir::ItemKind::Fn(..) => { | |
154 | item_might_be_inlined(self.tcx, &item, self.tcx.codegen_fn_attrs(def_id)) | |
970d7e83 | 155 | } |
dfeec247 XL |
156 | _ => false, |
157 | }, | |
158 | Some(Node::TraitItem(trait_method)) => match trait_method.kind { | |
159 | hir::TraitItemKind::Const(_, ref default) => default.is_some(), | |
ba9703b0 XL |
160 | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true, |
161 | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) | |
dfeec247 XL |
162 | | hir::TraitItemKind::Type(..) => false, |
163 | }, | |
b7449926 | 164 | Some(Node::ImplItem(impl_item)) => { |
e74abb32 | 165 | match impl_item.kind { |
92a42be0 | 166 | hir::ImplItemKind::Const(..) => true, |
ba9703b0 | 167 | hir::ImplItemKind::Fn(..) => { |
94b46f34 | 168 | let attrs = self.tcx.codegen_fn_attrs(def_id); |
8faf50e0 | 169 | let generics = self.tcx.generics_of(def_id); |
b7449926 | 170 | if generics.requires_monomorphization(self.tcx) || attrs.requests_inline() { |
1a4d82fc JJ |
171 | true |
172 | } else { | |
f9f354fc | 173 | let impl_did = self.tcx.hir().get_parent_did(hir_id); |
1a4d82fc JJ |
174 | // Check the impl. If the generics on the self |
175 | // type of the impl require inlining, this method | |
176 | // does too. | |
3dfed10e | 177 | let impl_hir_id = self.tcx.hir().local_def_id_to_hir_id(impl_did); |
e74abb32 | 178 | match self.tcx.hir().expect_item(impl_hir_id).kind { |
dfeec247 | 179 | hir::ItemKind::Impl { .. } => { |
8faf50e0 | 180 | let generics = self.tcx.generics_of(impl_did); |
b7449926 | 181 | generics.requires_monomorphization(self.tcx) |
970d7e83 | 182 | } |
dfeec247 | 183 | _ => false, |
970d7e83 LB |
184 | } |
185 | } | |
970d7e83 | 186 | } |
f035d41b | 187 | hir::ImplItemKind::TyAlias(_) => false, |
970d7e83 LB |
188 | } |
189 | } | |
190 | Some(_) => false, | |
dfeec247 | 191 | None => false, // This will happen for default methods. |
970d7e83 LB |
192 | } |
193 | } | |
194 | ||
1a4d82fc JJ |
195 | // Step 2: Mark all symbols that the symbols on the worklist touch. |
196 | fn propagate(&mut self) { | |
0bf4aa26 | 197 | let mut scanned = FxHashSet::default(); |
0531ce1d | 198 | while let Some(search_item) = self.worklist.pop() { |
1a4d82fc | 199 | if !scanned.insert(search_item) { |
dfeec247 | 200 | continue; |
1a4d82fc | 201 | } |
970d7e83 | 202 | |
3dfed10e XL |
203 | if let Some(ref item) = |
204 | self.tcx.hir().find(self.tcx.hir().local_def_id_to_hir_id(search_item)) | |
205 | { | |
92a42be0 | 206 | self.propagate_node(item, search_item); |
1a4d82fc JJ |
207 | } |
208 | } | |
970d7e83 LB |
209 | } |
210 | ||
3dfed10e | 211 | fn propagate_node(&mut self, node: &Node<'tcx>, search_item: LocalDefId) { |
1a4d82fc | 212 | if !self.any_library { |
7453a54e SL |
213 | // If we are building an executable, only explicitly extern |
214 | // types need to be exported. | |
b7449926 | 215 | if let Node::Item(item) = *node { |
60c5eb7d XL |
216 | let reachable = if let hir::ItemKind::Fn(ref sig, ..) = item.kind { |
217 | sig.header.abi != Abi::Rust | |
7453a54e SL |
218 | } else { |
219 | false | |
220 | }; | |
6a06907d | 221 | let codegen_attrs = self.tcx.codegen_fn_attrs(item.def_id); |
b7449926 | 222 | let is_extern = codegen_attrs.contains_extern_indicator(); |
dfeec247 XL |
223 | let std_internal = |
224 | codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL); | |
b7449926 | 225 | if reachable || is_extern || std_internal { |
7453a54e | 226 | self.reachable_symbols.insert(search_item); |
1a4d82fc | 227 | } |
970d7e83 | 228 | } |
1a4d82fc JJ |
229 | } else { |
230 | // If we are building a library, then reachable symbols will | |
231 | // continue to participate in linkage after this product is | |
232 | // produced. In this case, we traverse the ast node, recursing on | |
233 | // all reachable nodes from this one. | |
970d7e83 | 234 | self.reachable_symbols.insert(search_item); |
1a4d82fc | 235 | } |
970d7e83 | 236 | |
1a4d82fc | 237 | match *node { |
b7449926 | 238 | Node::Item(item) => { |
e74abb32 | 239 | match item.kind { |
8faf50e0 | 240 | hir::ItemKind::Fn(.., body) => { |
6a06907d XL |
241 | if item_might_be_inlined( |
242 | self.tcx, | |
243 | &item, | |
244 | self.tcx.codegen_fn_attrs(item.def_id), | |
245 | ) { | |
32a655c1 | 246 | self.visit_nested_body(body); |
970d7e83 LB |
247 | } |
248 | } | |
1a4d82fc JJ |
249 | |
250 | // Reachable constants will be inlined into other crates | |
251 | // unconditionally, so we need to make sure that their | |
252 | // contents are also reachable. | |
8faf50e0 | 253 | hir::ItemKind::Const(_, init) => { |
32a655c1 | 254 | self.visit_nested_body(init); |
1a4d82fc JJ |
255 | } |
256 | ||
257 | // These are normal, nothing reachable about these | |
258 | // inherently and their children are already in the | |
259 | // worklist, as determined by the privacy pass | |
dfeec247 XL |
260 | hir::ItemKind::ExternCrate(_) |
261 | | hir::ItemKind::Use(..) | |
262 | | hir::ItemKind::OpaqueTy(..) | |
263 | | hir::ItemKind::TyAlias(..) | |
264 | | hir::ItemKind::Static(..) | |
265 | | hir::ItemKind::Mod(..) | |
fc512014 | 266 | | hir::ItemKind::ForeignMod { .. } |
dfeec247 XL |
267 | | hir::ItemKind::Impl { .. } |
268 | | hir::ItemKind::Trait(..) | |
269 | | hir::ItemKind::TraitAlias(..) | |
270 | | hir::ItemKind::Struct(..) | |
271 | | hir::ItemKind::Enum(..) | |
272 | | hir::ItemKind::Union(..) | |
273 | | hir::ItemKind::GlobalAsm(..) => {} | |
970d7e83 | 274 | } |
1a4d82fc | 275 | } |
b7449926 | 276 | Node::TraitItem(trait_method) => { |
e74abb32 | 277 | match trait_method.kind { |
dfeec247 | 278 | hir::TraitItemKind::Const(_, None) |
ba9703b0 | 279 | | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { |
1a4d82fc JJ |
280 | // Keep going, nothing to get exported |
281 | } | |
dfeec247 | 282 | hir::TraitItemKind::Const(_, Some(body_id)) |
ba9703b0 | 283 | | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => { |
32a655c1 | 284 | self.visit_nested_body(body_id); |
d9579d0f | 285 | } |
32a655c1 | 286 | hir::TraitItemKind::Type(..) => {} |
970d7e83 | 287 | } |
1a4d82fc | 288 | } |
dfeec247 XL |
289 | Node::ImplItem(impl_item) => match impl_item.kind { |
290 | hir::ImplItemKind::Const(_, body) => { | |
291 | self.visit_nested_body(body); | |
292 | } | |
ba9703b0 | 293 | hir::ImplItemKind::Fn(_, body) => { |
3dfed10e XL |
294 | let impl_def_id = |
295 | self.tcx.parent(search_item.to_def_id()).unwrap().expect_local(); | |
296 | if method_might_be_inlined(self.tcx, impl_item, impl_def_id) { | |
dfeec247 | 297 | self.visit_nested_body(body) |
1a4d82fc | 298 | } |
970d7e83 | 299 | } |
f035d41b | 300 | hir::ImplItemKind::TyAlias(_) => {} |
dfeec247 | 301 | }, |
e74abb32 | 302 | Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., body, _, _), .. }) => { |
3b2f2976 XL |
303 | self.visit_nested_body(body); |
304 | } | |
1a4d82fc | 305 | // Nothing to recurse on for these |
dfeec247 XL |
306 | Node::ForeignItem(_) |
307 | | Node::Variant(_) | |
308 | | Node::Ctor(..) | |
309 | | Node::Field(_) | |
310 | | Node::Ty(_) | |
5869c6ff | 311 | | Node::Crate(_) |
dfeec247 | 312 | | Node::MacroDef(_) => {} |
1a4d82fc | 313 | _ => { |
9fa01778 XL |
314 | bug!( |
315 | "found unexpected node kind in worklist: {} ({:?})", | |
3dfed10e XL |
316 | self.tcx |
317 | .hir() | |
318 | .node_to_string(self.tcx.hir().local_def_id_to_hir_id(search_item)), | |
9fa01778 XL |
319 | node, |
320 | ); | |
1a4d82fc | 321 | } |
970d7e83 LB |
322 | } |
323 | } | |
92a42be0 | 324 | } |
970d7e83 | 325 | |
92a42be0 SL |
326 | // Some methods from non-exported (completely private) trait impls still have to be |
327 | // reachable if they are called from inlinable code. Generally, it's not known until | |
328 | // monomorphization if a specific trait impl item can be reachable or not. So, we | |
329 | // conservatively mark all of them as reachable. | |
330 | // FIXME: One possible strategy for pruning the reachable set is to avoid marking impl | |
331 | // items of non-exported traits (or maybe all local traits?) unless their respective | |
332 | // trait items are used from inlinable code through method call syntax or UFCS, or their | |
333 | // trait is a lang item. | |
dc9dc135 XL |
334 | struct CollectPrivateImplItemsVisitor<'a, 'tcx> { |
335 | tcx: TyCtxt<'tcx>, | |
92a42be0 | 336 | access_levels: &'a privacy::AccessLevels, |
3dfed10e | 337 | worklist: &'a mut Vec<LocalDefId>, |
92a42be0 SL |
338 | } |
339 | ||
dc9dc135 | 340 | impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx> { |
dfeec247 | 341 | fn visit_item(&mut self, item: &hir::Item<'_>) { |
abe05a73 | 342 | // Anything which has custom linkage gets thrown on the worklist no |
b7449926 XL |
343 | // matter where it is in the crate, along with "special std symbols" |
344 | // which are currently akin to allocator symbols. | |
6a06907d | 345 | let codegen_attrs = self.tcx.codegen_fn_attrs(item.def_id); |
dfeec247 XL |
346 | if codegen_attrs.contains_extern_indicator() |
347 | || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) | |
348 | { | |
6a06907d | 349 | self.worklist.push(item.def_id); |
abe05a73 XL |
350 | } |
351 | ||
92a42be0 | 352 | // We need only trait impls here, not inherent impls, and only non-exported ones |
5869c6ff XL |
353 | if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) = |
354 | item.kind | |
355 | { | |
6a06907d | 356 | if !self.access_levels.is_reachable(item.hir_id()) { |
3dfed10e XL |
357 | // FIXME(#53488) remove `let` |
358 | let tcx = self.tcx; | |
6a06907d | 359 | self.worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id)); |
476ff2be | 360 | |
48663c56 XL |
361 | let trait_def_id = match trait_ref.path.res { |
362 | Res::Def(DefKind::Trait, def_id) => def_id, | |
dfeec247 | 363 | _ => unreachable!(), |
476ff2be SL |
364 | }; |
365 | ||
366 | if !trait_def_id.is_local() { | |
dfeec247 | 367 | return; |
476ff2be SL |
368 | } |
369 | ||
74b04a01 XL |
370 | self.worklist.extend( |
371 | tcx.provided_trait_methods(trait_def_id) | |
3dfed10e | 372 | .map(|assoc| assoc.def_id.expect_local()), |
74b04a01 | 373 | ); |
970d7e83 | 374 | } |
92a42be0 | 375 | } |
970d7e83 | 376 | } |
476ff2be | 377 | |
dfeec247 | 378 | fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {} |
32a655c1 | 379 | |
dfeec247 | 380 | fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) { |
476ff2be SL |
381 | // processed in visit_item above |
382 | } | |
fc512014 XL |
383 | |
384 | fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) { | |
385 | // We never export foreign functions as they have no body to export. | |
386 | } | |
970d7e83 LB |
387 | } |
388 | ||
3dfed10e | 389 | fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> FxHashSet<LocalDefId> { |
cc61c64b XL |
390 | debug_assert!(crate_num == LOCAL_CRATE); |
391 | ||
7cac9316 | 392 | let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); |
92a42be0 | 393 | |
f9f354fc XL |
394 | let any_library = |
395 | tcx.sess.crate_types().iter().any(|ty| { | |
396 | *ty == CrateType::Rlib || *ty == CrateType::Dylib || *ty == CrateType::ProcMacro | |
397 | }); | |
32a655c1 | 398 | let mut reachable_context = ReachableContext { |
041b39d2 | 399 | tcx, |
3dfed10e | 400 | maybe_typeck_results: None, |
a1dfa0c6 | 401 | reachable_symbols: Default::default(), |
32a655c1 | 402 | worklist: Vec::new(), |
041b39d2 | 403 | any_library, |
32a655c1 | 404 | }; |
1a4d82fc JJ |
405 | |
406 | // Step 1: Seed the worklist with all nodes which were found to be public as | |
92a42be0 SL |
407 | // a result of the privacy pass along with all local lang items and impl items. |
408 | // If other crates link to us, they're going to expect to be able to | |
1a4d82fc JJ |
409 | // use the lang items, so we need to be sure to mark them as |
410 | // exported. | |
3dfed10e XL |
411 | reachable_context |
412 | .worklist | |
413 | .extend(access_levels.map.iter().map(|(id, _)| tcx.hir().local_def_id(*id))); | |
ea8adc8c | 414 | for item in tcx.lang_items().items().iter() { |
3dfed10e XL |
415 | if let Some(def_id) = *item { |
416 | if let Some(def_id) = def_id.as_local() { | |
417 | reachable_context.worklist.push(def_id); | |
1a4d82fc | 418 | } |
1a4d82fc JJ |
419 | } |
420 | } | |
92a42be0 SL |
421 | { |
422 | let mut collect_private_impl_items = CollectPrivateImplItemsVisitor { | |
041b39d2 XL |
423 | tcx, |
424 | access_levels, | |
92a42be0 SL |
425 | worklist: &mut reachable_context.worklist, |
426 | }; | |
0731742a | 427 | tcx.hir().krate().visit_all_item_likes(&mut collect_private_impl_items); |
92a42be0 | 428 | } |
970d7e83 LB |
429 | |
430 | // Step 2: Mark all symbols that the symbols on the worklist touch. | |
431 | reachable_context.propagate(); | |
432 | ||
b7449926 XL |
433 | debug!("Inline reachability shows: {:?}", reachable_context.reachable_symbols); |
434 | ||
970d7e83 | 435 | // Return the set of reachable symbols. |
3dfed10e | 436 | reachable_context.reachable_symbols |
cc61c64b XL |
437 | } |
438 | ||
f035d41b | 439 | pub fn provide(providers: &mut Providers) { |
dfeec247 | 440 | *providers = Providers { reachable_set, ..*providers }; |
970d7e83 | 441 | } |