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