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