Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #include "rust-name-resolver.h"
20 : : #include "rust-ast-full.h"
21 : :
22 : : // for flag_name_resolution_2_0
23 : : #include "options.h"
24 : :
25 : : namespace Rust {
26 : : namespace Resolver {
27 : :
28 : 207364 : Rib::Rib (CrateNum crateNum, NodeId node_id)
29 : 207364 : : crate_num (crateNum), node_id (node_id)
30 : 207364 : {}
31 : :
32 : : void
33 : 166565 : Rib::insert_name (
34 : : const CanonicalPath &path, NodeId id, location_t locus, bool shadow,
35 : : ItemType type,
36 : : std::function<void (const CanonicalPath &, NodeId, location_t)> dup_cb)
37 : : {
38 : 166565 : auto it = path_mappings.find (path);
39 : 166565 : bool path_already_exists = it != path_mappings.end ();
40 : 166565 : if (path_already_exists && !shadow)
41 : : {
42 : 12 : const auto &decl = decls_within_rib.find (it->second);
43 : 12 : if (decl != decls_within_rib.end ())
44 : 12 : dup_cb (path, it->second, decl->second);
45 : : else
46 : 0 : dup_cb (path, it->second, locus);
47 : :
48 : 12 : return;
49 : : }
50 : :
51 : 166553 : path_mappings[path] = id;
52 : 166553 : reverse_path_mappings.insert ({id, path});
53 : 166553 : decls_within_rib.insert ({id, locus});
54 : 166553 : references[id] = {};
55 : 166553 : decl_type_mappings.insert ({id, type});
56 : : }
57 : :
58 : : bool
59 : 272290 : Rib::lookup_name (const CanonicalPath &ident, NodeId *id)
60 : : {
61 : 272290 : auto it = path_mappings.find (ident);
62 : 272290 : if (it == path_mappings.end ())
63 : : return false;
64 : :
65 : 93674 : *id = it->second;
66 : 93674 : return true;
67 : : }
68 : :
69 : : void
70 : 4977 : Rib::clear_name (const CanonicalPath &ident, NodeId id)
71 : : {
72 : 4977 : auto ii = path_mappings.find (ident);
73 : 4977 : if (ii != path_mappings.end ())
74 : 4977 : path_mappings.erase (ii);
75 : :
76 : 4977 : auto ij = reverse_path_mappings.find (id);
77 : 4977 : if (ij != reverse_path_mappings.end ())
78 : 4977 : reverse_path_mappings.erase (ij);
79 : :
80 : 4977 : auto ik = decls_within_rib.find (id);
81 : 4977 : if (ik != decls_within_rib.end ())
82 : 4977 : decls_within_rib.erase (ik);
83 : 4977 : }
84 : :
85 : : void
86 : 174025 : Rib::append_reference_for_def (NodeId def, NodeId ref)
87 : : {
88 : 174025 : references[def].insert (ref);
89 : 174025 : }
90 : :
91 : : bool
92 : 0 : Rib::have_references_for_node (NodeId def) const
93 : : {
94 : 0 : auto it = references.find (def);
95 : 0 : if (it == references.end ())
96 : : return false;
97 : :
98 : 0 : return !it->second.empty ();
99 : : }
100 : :
101 : : bool
102 : 1051102 : Rib::decl_was_declared_here (NodeId def) const
103 : : {
104 : 10427153 : for (auto &it : decls_within_rib)
105 : : {
106 : 9627101 : if (it.first == def)
107 : 1051102 : return true;
108 : : }
109 : : return false;
110 : : }
111 : :
112 : : bool
113 : 89 : Rib::lookup_decl_type (NodeId def, ItemType *type) const
114 : : {
115 : 89 : auto it = decl_type_mappings.find (def);
116 : 89 : if (it == decl_type_mappings.end ())
117 : : return false;
118 : :
119 : 89 : *type = it->second;
120 : 89 : return true;
121 : : }
122 : :
123 : : void
124 : 0 : Rib::debug () const
125 : : {
126 : 0 : fprintf (stderr, "%s\n", debug_str ().c_str ());
127 : 0 : }
128 : :
129 : : std::string
130 : 0 : Rib::debug_str () const
131 : : {
132 : 0 : std::string buffer;
133 : 0 : for (const auto &it : path_mappings)
134 : : {
135 : 0 : buffer += it.first.get () + "=" + std::to_string (it.second);
136 : 0 : buffer += ",";
137 : : }
138 : 0 : return "{" + buffer + "}";
139 : 0 : }
140 : :
141 : 21536 : Scope::Scope (CrateNum crate_num) : crate_num (crate_num) {}
142 : :
143 : : void
144 : 43125 : Scope::insert (
145 : : const CanonicalPath &ident, NodeId id, location_t locus, bool shadow,
146 : : Rib::ItemType type,
147 : : std::function<void (const CanonicalPath &, NodeId, location_t)> dup_cb)
148 : : {
149 : 43125 : peek ()->insert_name (ident, id, locus, shadow, type, dup_cb);
150 : 43125 : }
151 : :
152 : : void
153 : 38586 : Scope::insert (const CanonicalPath &ident, NodeId id, location_t locus,
154 : : Rib::ItemType type)
155 : : {
156 : 38586 : peek ()->insert_name (ident, id, locus, true, type,
157 : : [] (const CanonicalPath &, NodeId, location_t) -> void {
158 : : });
159 : 38586 : }
160 : :
161 : : bool
162 : 102293 : Scope::lookup (const CanonicalPath &ident, NodeId *id)
163 : : {
164 : 102293 : NodeId lookup = UNKNOWN_NODEID;
165 : 102293 : iterate ([&] (Rib *r) mutable -> bool {
166 : 272290 : if (r->lookup_name (ident, &lookup))
167 : 93674 : return false;
168 : : return true;
169 : : });
170 : :
171 : 102293 : *id = lookup;
172 : 102293 : return lookup != UNKNOWN_NODEID;
173 : : }
174 : :
175 : : bool
176 : 89 : Scope::lookup_decl_type (NodeId id, Rib::ItemType *type)
177 : : {
178 : 89 : bool found = false;
179 : 89 : iterate ([&] (const Rib *r) -> bool {
180 : 172 : if (r->decl_was_declared_here (id))
181 : : {
182 : 89 : bool ok = r->lookup_decl_type (id, type);
183 : 89 : rust_assert (ok);
184 : 89 : found = true;
185 : 89 : return false;
186 : : }
187 : : return true;
188 : : });
189 : 89 : return found;
190 : : }
191 : :
192 : : bool
193 : 89 : Scope::lookup_rib_for_decl (NodeId id, const Rib **rib)
194 : : {
195 : 89 : bool found = false;
196 : 89 : iterate ([&] (const Rib *r) -> bool {
197 : 172 : if (r->decl_was_declared_here (id))
198 : : {
199 : 89 : *rib = r;
200 : 89 : found = true;
201 : 89 : return false;
202 : : }
203 : : return true;
204 : : });
205 : 89 : return found;
206 : : }
207 : :
208 : : void
209 : 271396 : Scope::iterate (std::function<bool (Rib *)> cb)
210 : : {
211 : 1109301 : for (auto it = stack.rbegin (); it != stack.rend (); ++it)
212 : : {
213 : 931757 : if (!cb (*it))
214 : 271396 : return;
215 : : }
216 : : }
217 : :
218 : : void
219 : 135263 : Scope::iterate (std::function<bool (const Rib *)> cb) const
220 : : {
221 : 450051 : for (auto it = stack.rbegin (); it != stack.rend (); ++it)
222 : : {
223 : 391635 : if (!cb (*it))
224 : 135263 : return;
225 : : }
226 : : }
227 : :
228 : : Rib *
229 : 484165 : Scope::peek ()
230 : : {
231 : 484165 : return stack.back ();
232 : : }
233 : :
234 : : void
235 : 207364 : Scope::push (NodeId id)
236 : : {
237 : 207364 : stack.push_back (new Rib (get_crate_num (), id));
238 : 207364 : }
239 : :
240 : : Rib *
241 : 189424 : Scope::pop ()
242 : : {
243 : 189424 : Rib *r = peek ();
244 : 189424 : stack.pop_back ();
245 : 189424 : return r;
246 : : }
247 : :
248 : : void
249 : 168925 : Scope::append_reference_for_def (NodeId refId, NodeId defId)
250 : : {
251 : 168925 : bool ok = false;
252 : 168925 : iterate ([&] (Rib *r) mutable -> bool {
253 : 659123 : if (r->decl_was_declared_here (defId))
254 : : {
255 : 174025 : ok = true;
256 : 174025 : r->append_reference_for_def (defId, refId);
257 : : }
258 : 659123 : return true;
259 : : });
260 : 168925 : rust_assert (ok);
261 : 168925 : }
262 : :
263 : : bool
264 : 135263 : Scope::decl_was_declared_here (NodeId def) const
265 : : {
266 : 135263 : bool found = false;
267 : 135263 : iterate ([&] (const Rib *r) -> bool {
268 : 391635 : if (r->decl_was_declared_here (def))
269 : : {
270 : 76847 : found = true;
271 : 76847 : return false;
272 : : }
273 : : return true;
274 : : });
275 : 135263 : return found;
276 : : }
277 : :
278 : 5384 : Resolver::Resolver ()
279 : 5384 : : mappings (Analysis::Mappings::get ()), tyctx (TypeCheckContext::get ()),
280 : 5384 : name_scope (Scope (mappings.get_current_crate ())),
281 : 5384 : type_scope (Scope (mappings.get_current_crate ())),
282 : 5384 : label_scope (Scope (mappings.get_current_crate ())),
283 : 5384 : macro_scope (Scope (mappings.get_current_crate ())),
284 : 10768 : global_type_node_id (UNKNOWN_NODEID), unit_ty_node_id (UNKNOWN_NODEID)
285 : : {
286 : 5384 : generate_builtins ();
287 : 5384 : }
288 : :
289 : : Resolver *
290 : 2341425 : Resolver::get ()
291 : : {
292 : 2341425 : static Resolver *instance;
293 : 2341425 : if (instance == nullptr)
294 : 5384 : instance = new Resolver ();
295 : :
296 : 2341425 : return instance;
297 : : }
298 : :
299 : : void
300 : 49095 : Resolver::push_new_name_rib (Rib *r)
301 : : {
302 : 49095 : rust_assert (name_ribs.find (r->get_node_id ()) == name_ribs.end ());
303 : 49095 : name_ribs[r->get_node_id ()] = r;
304 : 49095 : }
305 : :
306 : : void
307 : 53561 : Resolver::push_new_type_rib (Rib *r)
308 : : {
309 : 53561 : if (type_ribs.size () == 0)
310 : 4466 : global_type_node_id = r->get_node_id ();
311 : :
312 : 53561 : rust_assert (type_ribs.find (r->get_node_id ()) == type_ribs.end ());
313 : 53561 : type_ribs[r->get_node_id ()] = r;
314 : 53561 : }
315 : :
316 : : void
317 : 45047 : Resolver::push_new_label_rib (Rib *r)
318 : : {
319 : 45047 : rust_assert (label_ribs.find (r->get_node_id ()) == label_ribs.end ());
320 : 45047 : label_ribs[r->get_node_id ()] = r;
321 : 45047 : }
322 : :
323 : : void
324 : 55884 : Resolver::push_new_macro_rib (Rib *r)
325 : : {
326 : 55884 : rust_assert (label_ribs.find (r->get_node_id ()) == label_ribs.end ());
327 : 55884 : macro_ribs[r->get_node_id ()] = r;
328 : 55884 : }
329 : :
330 : : bool
331 : 51 : Resolver::find_name_rib (NodeId id, Rib **rib)
332 : : {
333 : 51 : auto it = name_ribs.find (id);
334 : 51 : if (it == name_ribs.end ())
335 : : return false;
336 : :
337 : 51 : *rib = it->second;
338 : 51 : return true;
339 : : }
340 : :
341 : : bool
342 : 0 : Resolver::find_type_rib (NodeId id, Rib **rib)
343 : : {
344 : 0 : auto it = type_ribs.find (id);
345 : 0 : if (it == type_ribs.end ())
346 : : return false;
347 : :
348 : 0 : *rib = it->second;
349 : 0 : return true;
350 : : }
351 : :
352 : : bool
353 : 0 : Resolver::find_macro_rib (NodeId id, Rib **rib)
354 : : {
355 : 0 : auto it = macro_ribs.find (id);
356 : 0 : if (it == macro_ribs.end ())
357 : : return false;
358 : :
359 : 0 : *rib = it->second;
360 : 0 : return true;
361 : : }
362 : :
363 : : void
364 : 4466 : Resolver::insert_builtin_types (Rib *r)
365 : : {
366 : 4466 : auto builtins = get_builtin_types ();
367 : 89320 : for (auto &builtin : builtins)
368 : : {
369 : 84854 : CanonicalPath builtin_path
370 : : = CanonicalPath::new_seg (builtin->get_node_id (),
371 : 84854 : builtin->as_string ());
372 : 84854 : r->insert_name (builtin_path, builtin->get_node_id (), BUILTINS_LOCATION,
373 : : false, Rib::ItemType::Type,
374 : : [] (const CanonicalPath &, NodeId, location_t) -> void {
375 : : });
376 : 84854 : }
377 : 4466 : }
378 : :
379 : : std::vector<AST::Type *> &
380 : 4466 : Resolver::get_builtin_types ()
381 : : {
382 : 4466 : return builtins;
383 : : }
384 : :
385 : : void
386 : 5384 : Resolver::generate_builtins ()
387 : : {
388 : 5384 : auto u8
389 : 5384 : = new TyTy::UintType (mappings.get_next_hir_id (), TyTy::UintType::U8);
390 : 5384 : auto u16
391 : 5384 : = new TyTy::UintType (mappings.get_next_hir_id (), TyTy::UintType::U16);
392 : 5384 : auto u32
393 : 5384 : = new TyTy::UintType (mappings.get_next_hir_id (), TyTy::UintType::U32);
394 : 5384 : auto u64
395 : 5384 : = new TyTy::UintType (mappings.get_next_hir_id (), TyTy::UintType::U64);
396 : 5384 : auto u128
397 : 5384 : = new TyTy::UintType (mappings.get_next_hir_id (), TyTy::UintType::U128);
398 : 5384 : auto i8 = new TyTy::IntType (mappings.get_next_hir_id (), TyTy::IntType::I8);
399 : 5384 : auto i16
400 : 5384 : = new TyTy::IntType (mappings.get_next_hir_id (), TyTy::IntType::I16);
401 : 5384 : auto i32
402 : 5384 : = new TyTy::IntType (mappings.get_next_hir_id (), TyTy::IntType::I32);
403 : 5384 : auto i64
404 : 5384 : = new TyTy::IntType (mappings.get_next_hir_id (), TyTy::IntType::I64);
405 : 5384 : auto i128
406 : 5384 : = new TyTy::IntType (mappings.get_next_hir_id (), TyTy::IntType::I128);
407 : 5384 : auto rbool = new TyTy::BoolType (mappings.get_next_hir_id ());
408 : 5384 : auto f32
409 : 5384 : = new TyTy::FloatType (mappings.get_next_hir_id (), TyTy::FloatType::F32);
410 : 5384 : auto f64
411 : 5384 : = new TyTy::FloatType (mappings.get_next_hir_id (), TyTy::FloatType::F64);
412 : 5384 : auto usize = new TyTy::USizeType (mappings.get_next_hir_id ());
413 : 5384 : auto isize = new TyTy::ISizeType (mappings.get_next_hir_id ());
414 : 5384 : auto char_tyty = new TyTy::CharType (mappings.get_next_hir_id ());
415 : 5384 : auto str = new TyTy::StrType (mappings.get_next_hir_id ());
416 : 5384 : auto never = new TyTy::NeverType (mappings.get_next_hir_id ());
417 : :
418 : 5384 : setup_builtin ("u8", u8);
419 : 5384 : setup_builtin ("u16", u16);
420 : 5384 : setup_builtin ("u32", u32);
421 : 5384 : setup_builtin ("u64", u64);
422 : 5384 : setup_builtin ("u128", u128);
423 : 5384 : setup_builtin ("i8", i8);
424 : 5384 : setup_builtin ("i16", i16);
425 : 5384 : setup_builtin ("i32", i32);
426 : 5384 : setup_builtin ("i64", i64);
427 : 5384 : setup_builtin ("i128", i128);
428 : 5384 : setup_builtin ("bool", rbool);
429 : 5384 : setup_builtin ("f32", f32);
430 : 5384 : setup_builtin ("f64", f64);
431 : 5384 : setup_builtin ("usize", usize);
432 : 5384 : setup_builtin ("isize", isize);
433 : 5384 : setup_builtin ("char", char_tyty);
434 : 5384 : setup_builtin ("str", str);
435 : :
436 : : // never type
437 : 5384 : NodeId never_node_id = setup_builtin ("!", never);
438 : 5384 : set_never_type_node_id (never_node_id);
439 : :
440 : : // unit type ()
441 : 5384 : TyTy::TupleType *unit_tyty = TyTy::TupleType::get_unit_type ();
442 : 5384 : std::vector<std::unique_ptr<AST::Type> > elems;
443 : 5384 : AST::TupleType *unit_type
444 : 5384 : = new AST::TupleType (std::move (elems), BUILTINS_LOCATION);
445 : 5384 : builtins.push_back (unit_type);
446 : 5384 : tyctx->insert_builtin (unit_tyty->get_ref (), unit_type->get_node_id (),
447 : : unit_tyty);
448 : 5384 : set_unit_type_node_id (unit_type->get_node_id ());
449 : 5384 : }
450 : :
451 : : NodeId
452 : 96912 : Resolver::setup_builtin (const std::string &name, TyTy::BaseType *tyty)
453 : : {
454 : 96912 : AST::PathIdentSegment seg (name, BUILTINS_LOCATION);
455 : 96912 : auto typePath = ::std::unique_ptr<AST::TypePathSegment> (
456 : 96912 : new AST::TypePathSegment (::std::move (seg), false, BUILTINS_LOCATION));
457 : 96912 : ::std::vector< ::std::unique_ptr<AST::TypePathSegment> > segs;
458 : 96912 : segs.push_back (::std::move (typePath));
459 : 96912 : auto builtin_type
460 : 96912 : = new AST::TypePath (::std::move (segs), BUILTINS_LOCATION, false);
461 : 96912 : builtins.push_back (builtin_type);
462 : 96912 : tyctx->insert_builtin (tyty->get_ref (), builtin_type->get_node_id (), tyty);
463 : 96912 : mappings.insert_node_to_hir (builtin_type->get_node_id (), tyty->get_ref ());
464 : 96912 : mappings.insert_canonical_path (
465 : : builtin_type->get_node_id (),
466 : 96912 : CanonicalPath::new_seg (builtin_type->get_node_id (), name));
467 : :
468 : 96912 : return builtin_type->get_node_id ();
469 : 96912 : }
470 : :
471 : : void
472 : 51733 : Resolver::insert_resolved_name (NodeId refId, NodeId defId)
473 : : {
474 : 51733 : rust_assert (!flag_name_resolution_2_0);
475 : 51733 : rust_assert (resolved_names.find (refId) == resolved_names.end ());
476 : :
477 : 51733 : resolved_names[refId] = defId;
478 : 51733 : get_name_scope ().append_reference_for_def (refId, defId);
479 : 51733 : insert_captured_item (defId);
480 : 51733 : }
481 : :
482 : : bool
483 : 329104 : Resolver::lookup_resolved_name (NodeId refId, NodeId *defId)
484 : : {
485 : 329104 : rust_assert (!flag_name_resolution_2_0);
486 : 329104 : auto it = resolved_names.find (refId);
487 : 329104 : if (it == resolved_names.end ())
488 : : return false;
489 : :
490 : 222111 : *defId = it->second;
491 : 222111 : return true;
492 : : }
493 : :
494 : : void
495 : 112884 : Resolver::insert_resolved_type (NodeId refId, NodeId defId)
496 : : {
497 : 112884 : rust_assert (!flag_name_resolution_2_0);
498 : 112884 : rust_assert (resolved_types.find (refId) == resolved_types.end ());
499 : :
500 : 112884 : resolved_types[refId] = defId;
501 : 112884 : get_type_scope ().append_reference_for_def (refId, defId);
502 : 112884 : }
503 : :
504 : : bool
505 : 855069 : Resolver::lookup_resolved_type (NodeId refId, NodeId *defId)
506 : : {
507 : 855069 : rust_assert (!flag_name_resolution_2_0);
508 : 855069 : auto it = resolved_types.find (refId);
509 : 855069 : if (it == resolved_types.end ())
510 : : return false;
511 : :
512 : 737896 : *defId = it->second;
513 : 737896 : return true;
514 : : }
515 : :
516 : : void
517 : 30 : Resolver::insert_resolved_label (NodeId refId, NodeId defId)
518 : : {
519 : 30 : rust_assert (!flag_name_resolution_2_0);
520 : 30 : auto it = resolved_labels.find (refId);
521 : 30 : rust_assert (it == resolved_labels.end ());
522 : :
523 : 30 : resolved_labels[refId] = defId;
524 : 30 : get_label_scope ().append_reference_for_def (refId, defId);
525 : 30 : }
526 : :
527 : : bool
528 : 30 : Resolver::lookup_resolved_label (NodeId refId, NodeId *defId)
529 : : {
530 : 30 : rust_assert (!flag_name_resolution_2_0);
531 : 30 : auto it = resolved_labels.find (refId);
532 : 30 : if (it == resolved_labels.end ())
533 : : return false;
534 : :
535 : 30 : *defId = it->second;
536 : 30 : return true;
537 : : }
538 : :
539 : : void
540 : 0 : Resolver::insert_resolved_macro (NodeId refId, NodeId defId)
541 : : {
542 : 0 : rust_assert (!flag_name_resolution_2_0);
543 : 0 : auto it = resolved_macros.find (refId);
544 : 0 : rust_assert (it == resolved_macros.end ());
545 : :
546 : 0 : resolved_labels[refId] = defId;
547 : 0 : get_label_scope ().append_reference_for_def (refId, defId);
548 : 0 : }
549 : :
550 : : bool
551 : 0 : Resolver::lookup_resolved_macro (NodeId refId, NodeId *defId)
552 : : {
553 : 0 : rust_assert (!flag_name_resolution_2_0);
554 : 0 : auto it = resolved_macros.find (refId);
555 : 0 : if (it == resolved_macros.end ())
556 : : return false;
557 : :
558 : 0 : *defId = it->second;
559 : 0 : return true;
560 : : }
561 : :
562 : : void
563 : 7 : Resolver::insert_resolved_misc (NodeId refId, NodeId defId)
564 : : {
565 : 7 : rust_assert (!flag_name_resolution_2_0);
566 : 7 : auto it = misc_resolved_items.find (refId);
567 : 7 : rust_assert (it == misc_resolved_items.end ());
568 : :
569 : 7 : misc_resolved_items[refId] = defId;
570 : 7 : }
571 : :
572 : : bool
573 : 2 : Resolver::lookup_resolved_misc (NodeId refId, NodeId *defId)
574 : : {
575 : 2 : rust_assert (!flag_name_resolution_2_0);
576 : 2 : auto it = misc_resolved_items.find (refId);
577 : 2 : if (it == misc_resolved_items.end ())
578 : : return false;
579 : :
580 : 2 : *defId = it->second;
581 : 2 : return true;
582 : : }
583 : :
584 : : void
585 : 62 : Resolver::push_closure_context (NodeId closure_expr_id)
586 : : {
587 : 62 : auto it = closures_capture_mappings.find (closure_expr_id);
588 : 62 : rust_assert (it == closures_capture_mappings.end ());
589 : :
590 : 62 : closures_capture_mappings.insert ({closure_expr_id, {}});
591 : 62 : closure_context.push_back (closure_expr_id);
592 : 62 : }
593 : :
594 : : void
595 : 62 : Resolver::pop_closure_context ()
596 : : {
597 : 62 : rust_assert (!closure_context.empty ());
598 : 62 : closure_context.pop_back ();
599 : 62 : }
600 : :
601 : : void
602 : 51733 : Resolver::insert_captured_item (NodeId id)
603 : : {
604 : : // nothing to do unless we are in a closure context
605 : 51733 : if (closure_context.empty ())
606 : 51646 : return;
607 : :
608 : : // check that this is a VAR_DECL?
609 : 89 : Scope &name_scope = get_name_scope ();
610 : 89 : Rib::ItemType type = Rib::ItemType::Unknown;
611 : 89 : bool found = name_scope.lookup_decl_type (id, &type);
612 : 89 : if (!found)
613 : : return;
614 : :
615 : : // RIB Function { let a, let b } id = 1;
616 : : // RIB Closure { let c } id = 2;
617 : : // RIB IfStmt { <bind a>} id = 3;
618 : : // RIB ... { ... } id = 4
619 : : //
620 : : // if we have a resolved_node_id of 'a' and the current rib is '3' we know
621 : : // this is binding exists in a rib with id < the closure rib id, other wise
622 : : // its just a normal binding and we don't care
623 : : //
624 : : // Problem the node id's dont work like this because the inner most items are
625 : : // created first so this means the root will have a larger id and a simple
626 : : // less than or greater than check wont work for more complex scoping cases
627 : : // but we can use our current rib context to figure this out by checking if
628 : : // the rib id the decl we care about exists prior to the rib for the closure
629 : : // id
630 : :
631 : 89 : const Rib *r = nullptr;
632 : 89 : bool ok = name_scope.lookup_rib_for_decl (id, &r);
633 : 89 : rust_assert (ok);
634 : 89 : NodeId decl_rib_node_id = r->get_node_id ();
635 : :
636 : : // iterate the closure context and add in the mapping for all to handle the
637 : : // case of nested closures
638 : 176 : for (auto &closure_expr_id : closure_context)
639 : : {
640 : 89 : if (!decl_needs_capture (decl_rib_node_id, closure_expr_id, name_scope))
641 : 80 : continue;
642 : :
643 : : // is this a valid binding to take
644 : 9 : bool is_var_decl_p = type == Rib::ItemType::Var;
645 : 9 : if (!is_var_decl_p)
646 : : {
647 : : // FIXME is this an error case?
648 : 51646 : return;
649 : : }
650 : :
651 : : // append it to the context info
652 : 7 : auto it = closures_capture_mappings.find (closure_expr_id);
653 : 7 : rust_assert (it != closures_capture_mappings.end ());
654 : :
655 : 7 : it->second.insert (id);
656 : : }
657 : : }
658 : :
659 : : bool
660 : 89 : Resolver::decl_needs_capture (NodeId decl_rib_node_id,
661 : : NodeId closure_rib_node_id, const Scope &scope)
662 : : {
663 : 347 : for (const auto &rib : scope.get_context ())
664 : : {
665 : 347 : bool rib_is_closure = rib->get_node_id () == closure_rib_node_id;
666 : 347 : bool rib_is_decl = rib->get_node_id () == decl_rib_node_id;
667 : 347 : if (rib_is_closure)
668 : : return false;
669 : 267 : else if (rib_is_decl)
670 : : return true;
671 : : }
672 : : return false;
673 : : }
674 : :
675 : : const std::set<NodeId> &
676 : 61 : Resolver::get_captures (NodeId id) const
677 : : {
678 : 61 : rust_assert (!flag_name_resolution_2_0);
679 : :
680 : 61 : auto it = closures_capture_mappings.find (id);
681 : 61 : rust_assert (it != closures_capture_mappings.end ());
682 : 61 : return it->second;
683 : : }
684 : :
685 : : } // namespace Resolver
686 : : } // namespace Rust
|