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