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-early-name-resolver-2.0.h"
20 : #include "optional.h"
21 : #include "options.h"
22 : #include "rust-ast.h"
23 : #include "rust-diagnostics.h"
24 : #include "rust-hir-map.h"
25 : #include "rust-item.h"
26 : #include "rust-name-resolution-context.h"
27 : #include "rust-rib.h"
28 : #include "rust-toplevel-name-resolver-2.0.h"
29 : #include "rust-attributes.h"
30 : #include "rust-finalize-imports-2.0.h"
31 : #include "rust-attribute-values.h"
32 : #include "rust-identifier-path.h"
33 :
34 : namespace Rust {
35 : namespace Resolver2_0 {
36 :
37 10956 : Early::Early (NameResolutionContext &ctx)
38 10956 : : DefaultResolver (ctx), toplevel (TopLevel (ctx)), dirty (false)
39 10956 : {}
40 :
41 : void
42 2821 : Early::try_insert_once (AST::MacroInvocation &invocation, NodeId resolved)
43 : {
44 2821 : auto leaf_macro = ctx.macros.find_leaf_definition (resolved);
45 :
46 : // Sometimes the import itself isn't resolved yet this turn of the fixed-point
47 2821 : if (!leaf_macro)
48 2821 : return;
49 :
50 : // TODO: Should we use `ctx.map_usage()`?
51 :
52 0 : auto definition = ctx.mappings.lookup_macro_def (leaf_macro->id);
53 :
54 0 : if (!ctx.mappings.lookup_macro_invocation (invocation))
55 0 : ctx.mappings.insert_macro_invocation (invocation, definition.value ());
56 : }
57 :
58 : void
59 3808 : Early::insert_once (AST::MacroRulesDefinition &def)
60 : {
61 3808 : if (!ctx.mappings.lookup_macro_def (def.get_node_id ()))
62 1 : ctx.mappings.insert_macro_def (&def);
63 3808 : }
64 :
65 : void
66 10956 : Early::go (AST::Crate &crate)
67 : {
68 : // First we go through TopLevel resolution to get all our declared items
69 10956 : toplevel.go (crate);
70 :
71 : // We start with resolving the list of imports that `TopLevel` has built for
72 : // us
73 :
74 10956 : dirty = toplevel.is_dirty ();
75 :
76 : // We now proceed with resolving macros, which can be nested in almost any
77 : // items
78 10956 : textual_scope.push ();
79 :
80 10956 : visit (crate);
81 :
82 10956 : textual_scope.pop ();
83 :
84 : // handle IdentifierPattern vs PathInExpression disambiguation
85 10956 : IdentifierPathPass::go (crate, ctx, std::move (ident_path_to_convert));
86 10956 : }
87 :
88 : bool
89 30 : Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
90 : {
91 30 : auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types);
92 30 : if (!resolved.has_value ())
93 : return false;
94 :
95 56 : auto result = Analysis::Mappings::get ().lookup_glob_container (
96 28 : resolved->definition.get_node_id ());
97 :
98 28 : if (!result)
99 : return false;
100 :
101 : // here, we insert the module's NodeId into the import_mappings and will look
102 : // up the module proper in `FinalizeImports`
103 : // The namespace does not matter here since we are dealing with a glob
104 : // FIXME: Does the namespace not matter? Is that valid?
105 : // TODO: Ugly
106 56 : import_mappings.insert (use_dec_id,
107 28 : ImportPair (std::move (glob),
108 84 : ImportData::Glob (resolved->definition)));
109 :
110 28 : return true;
111 30 : }
112 :
113 : bool
114 0 : Early::resolve_simple_import (NodeId use_dec_id, TopLevel::ImportKind &&import)
115 : {
116 0 : auto definitions = resolve_path_in_all_ns (import.to_resolve);
117 :
118 : // if we've found at least one definition, then we're good
119 0 : if (definitions.empty ())
120 : return false;
121 :
122 0 : auto &imports = import_mappings.new_or_access (use_dec_id);
123 :
124 0 : imports.emplace_back (
125 0 : ImportPair (std::move (import),
126 0 : ImportData::Simple (std::move (definitions))));
127 :
128 0 : return true;
129 0 : }
130 :
131 : bool
132 3082 : Early::resolve_rebind_import (NodeId use_dec_id,
133 : TopLevel::ImportKind &&rebind_import)
134 : {
135 3082 : NodeId import_id = UNKNOWN_NODEID;
136 3082 : auto &path = rebind_import.to_resolve;
137 3082 : auto &rebind = rebind_import.rebind.value ();
138 :
139 3082 : switch (rebind.get_new_bind_type ())
140 : {
141 8 : case AST::UseTreeRebind::NewBindType::IDENTIFIER:
142 8 : import_id = rebind.get_node_id ();
143 8 : break;
144 3070 : case AST::UseTreeRebind::NewBindType::NONE:
145 3070 : {
146 3070 : const auto &segments = path.get_segments ();
147 : // We don't want to insert `self` with `use module::self`
148 3070 : if (path.get_final_segment ().is_lower_self_seg ())
149 : {
150 : // Erroneous `self` or `{self}` use declaration
151 211 : if (segments.size () == 1)
152 : break;
153 206 : import_id = segments[segments.size () - 2].get_node_id ();
154 : }
155 : else
156 : {
157 2859 : import_id = path.get_final_segment ().get_node_id ();
158 : }
159 : break;
160 : }
161 : case AST::UseTreeRebind::NewBindType::WILDCARD:
162 : // nothing
163 : break;
164 : }
165 :
166 3082 : if (ctx.lookup (import_id, Namespace::Types))
167 : return true;
168 :
169 1146 : auto definitions = resolve_path_in_all_ns (rebind_import.to_resolve);
170 :
171 : // if we've found at least one definition, then we're good
172 1146 : if (definitions.empty ())
173 : return false;
174 2402 : for (const auto &def : definitions)
175 : {
176 1271 : if (def.definition.is_ambiguous ())
177 : {
178 1 : rich_location rich_locus (line_table,
179 1 : rebind_import.to_resolve.get_locus ());
180 1 : rust_error_at (rich_locus, ErrorCode::E0659, "%qs is ambiguous",
181 1 : rebind_import.to_resolve.as_string ().c_str ());
182 1 : return true;
183 1 : }
184 : }
185 :
186 1131 : auto &imports = import_mappings.new_or_access (use_dec_id);
187 :
188 1131 : imports.emplace_back (
189 1131 : ImportPair (std::move (rebind_import),
190 2262 : ImportData::Rebind (std::move (definitions))));
191 :
192 1131 : return true;
193 1146 : }
194 :
195 : void
196 1878 : Early::build_import_mapping (
197 : std::pair<NodeId, std::vector<TopLevel::ImportKind>> &&use_import)
198 : {
199 1878 : auto found = false;
200 1878 : auto use_dec_id = use_import.first;
201 :
202 4990 : for (auto &&import : use_import.second)
203 : {
204 : // We create a copy of the path in case of errors, since the `import` will
205 : // be moved into the newly created import mappings
206 3112 : auto path = import.to_resolve;
207 :
208 : // used to skip the "unresolved import" error
209 : // if we output other errors during resolution
210 3112 : size_t old_error_count = macro_resolve_errors.size ();
211 :
212 3112 : switch (import.kind)
213 : {
214 30 : case TopLevel::ImportKind::Kind::Glob:
215 30 : found = resolve_glob_import (use_dec_id, std::move (import));
216 30 : break;
217 0 : case TopLevel::ImportKind::Kind::Simple:
218 0 : found = resolve_simple_import (use_dec_id, std::move (import));
219 0 : break;
220 3082 : case TopLevel::ImportKind::Kind::Rebind:
221 3082 : found = resolve_rebind_import (use_dec_id, std::move (import));
222 3082 : break;
223 : }
224 :
225 3112 : if (!found && old_error_count == macro_resolve_errors.size ())
226 28 : collect_error (Error (path.get_final_segment ().get_locus (),
227 : ErrorCode::E0433, "unresolved import %qs",
228 28 : path.as_string ().c_str ()));
229 3112 : }
230 1878 : }
231 :
232 : void
233 69657 : Early::TextualScope::push ()
234 : {
235 : // push a new empty scope
236 69657 : scopes.emplace_back ();
237 69657 : }
238 :
239 : void
240 69657 : Early::TextualScope::pop ()
241 : {
242 69657 : rust_assert (!scopes.empty ());
243 :
244 69657 : scopes.pop_back ();
245 69657 : }
246 :
247 : void
248 3808 : Early::TextualScope::insert (std::string name, NodeId id)
249 : {
250 3808 : rust_assert (!scopes.empty ());
251 :
252 : // we can ignore the return value as we always want the latest defined macro
253 : // to shadow a previous one - so if two macros have the same name and get
254 : // inserted with the same key, it's not a bug
255 7616 : scopes.back ().insert ({name, id});
256 3808 : }
257 :
258 : tl::optional<NodeId>
259 2855 : Early::TextualScope::get (const std::string &name)
260 : {
261 5605 : for (auto iterator = scopes.rbegin (); iterator != scopes.rend (); iterator++)
262 : {
263 5557 : auto scope = *iterator;
264 5557 : auto found = scope.find (name);
265 5557 : if (found != scope.end ())
266 2807 : return found->second;
267 5557 : }
268 :
269 48 : return tl::nullopt;
270 : }
271 :
272 : void
273 3808 : Early::visit (AST::MacroRulesDefinition &def)
274 : {
275 3808 : DefaultResolver::visit (def);
276 :
277 7616 : textual_scope.insert (def.get_rule_name ().as_string (), def.get_node_id ());
278 3808 : insert_once (def);
279 3808 : }
280 :
281 : void
282 55427 : Early::visit (AST::BlockExpr &block)
283 : {
284 55427 : textual_scope.push ();
285 :
286 55427 : DefaultResolver::visit (block);
287 :
288 55427 : textual_scope.pop ();
289 55427 : }
290 :
291 : void
292 3306 : Early::visit (AST::Module &module)
293 : {
294 3306 : bool is_macro_use = false;
295 :
296 3549 : for (const auto &attr : module.get_outer_attrs ())
297 : {
298 275 : if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE)
299 : {
300 : is_macro_use = true;
301 : break;
302 : }
303 : }
304 :
305 3306 : if (!is_macro_use)
306 3274 : textual_scope.push ();
307 :
308 3306 : DefaultResolver::visit (module);
309 :
310 3306 : if (!is_macro_use)
311 3274 : textual_scope.pop ();
312 3306 : }
313 :
314 : void
315 2869 : Early::visit (AST::MacroInvocation &invoc)
316 : {
317 2869 : auto &path = invoc.get_invoc_data ().get_path ();
318 :
319 : // We special case the `offset_of!()` macro if the flag is here, otherwise
320 : // we accept whatever `offset_of!()` definition we resolved to.
321 2869 : auto resolve_offset_of
322 2869 : = flag_assume_builtin_offset_of && (path.as_string () == "offset_of");
323 :
324 2869 : if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
325 98 : for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
326 52 : pending_invoc->accept_vis (*this);
327 :
328 : // When a macro is invoked by an unqualified identifier (not part of a
329 : // multi-part path), it is first looked up in textual scoping. If this does
330 : // not yield any results, then it is looked up in path-based scoping. If the
331 : // macro's name is qualified with a path, then it is only looked up in
332 : // path-based scoping.
333 :
334 : // https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope
335 :
336 2869 : tl::optional<NameResolutionContext::NamespacedDefinition> ns_def
337 : = tl::nullopt;
338 2869 : if (path.get_segments ().size () == 1)
339 2855 : ns_def = textual_scope.get (path.get_final_segment ().as_string ())
340 5710 : .map ([] (NodeId id) {
341 2807 : return NameResolutionContext::NamespacedDefinition (
342 2807 : Rib::Definition::NonShadowable (id), Namespace::Macros);
343 2855 : });
344 :
345 : // we won't have changed `definition` from `nullopt` if there are more
346 : // than one segments in our path
347 2869 : if (!ns_def.has_value ())
348 76 : ns_def = ctx.resolve_path (path, Namespace::Macros);
349 :
350 : // if the definition still does not have a value, then it's an error - unless
351 : // we should automatically resolve offset_of!() calls
352 2869 : if (!ns_def.has_value ())
353 : {
354 48 : if (!resolve_offset_of)
355 30 : collect_error (Error (invoc.get_locus (), ErrorCode::E0433,
356 : "could not resolve macro invocation %qs",
357 60 : path.as_string ().c_str ()));
358 48 : return;
359 : }
360 :
361 2821 : try_insert_once (invoc, ns_def->definition.get_node_id ());
362 :
363 : // now do we need to keep mappings or something? or insert "uses" into our
364 : // ForeverStack? can we do that? are mappings simpler?
365 2821 : auto &mappings = Analysis::Mappings::get ();
366 2821 : auto rules_def
367 2821 : = mappings.lookup_macro_def (ns_def->definition.get_node_id ());
368 :
369 : // Macro definition not found, maybe it is not expanded yet.
370 2821 : if (!rules_def)
371 : return;
372 :
373 2821 : if (mappings.lookup_macro_invocation (invoc))
374 : return;
375 :
376 2821 : mappings.insert_macro_invocation (invoc, rules_def.value ());
377 2869 : }
378 :
379 : void
380 170 : Early::visit_derive_attribute (AST::Attribute &attr,
381 : Analysis::Mappings &mappings)
382 : {
383 170 : auto traits = attr.get_traits_to_derive ();
384 476 : for (auto &trait : traits)
385 : {
386 306 : auto ns_def = ctx.resolve_path (trait.get (), Namespace::Macros);
387 306 : if (!ns_def.has_value ())
388 : {
389 : // FIXME: Change to proper error message
390 612 : collect_error (Error (trait.get ().get_locus (),
391 : "could not resolve trait %qs",
392 306 : trait.get ().as_string ().c_str ()));
393 306 : continue;
394 : }
395 :
396 0 : auto pm_def = mappings.lookup_derive_proc_macro_def (
397 0 : ns_def->definition.get_node_id ());
398 :
399 0 : if (pm_def.has_value ())
400 0 : mappings.insert_derive_proc_macro_invocation (trait, pm_def.value ());
401 306 : }
402 170 : }
403 :
404 : void
405 1 : Early::visit_non_builtin_attribute (AST::Attribute &attr,
406 : Analysis::Mappings &mappings,
407 : std::string &name)
408 : {
409 1 : auto ns_def = ctx.resolve_path (attr.get_path (), Namespace::Macros);
410 1 : if (!ns_def.has_value ())
411 : {
412 : // FIXME: Change to proper error message
413 0 : collect_error (Error (attr.get_locus (),
414 : "could not resolve attribute macro invocation %qs",
415 0 : name.c_str ()));
416 0 : return;
417 : }
418 1 : auto pm_def = mappings.lookup_attribute_proc_macro_def (
419 1 : ns_def->definition.get_node_id ());
420 :
421 1 : if (!pm_def.has_value ())
422 : return;
423 :
424 0 : mappings.insert_attribute_proc_macro_invocation (attr.get_path (),
425 0 : pm_def.value ());
426 1 : }
427 :
428 : void
429 71684 : Early::visit (AST::Attribute &attr)
430 : {
431 71684 : auto &mappings = Analysis::Mappings::get ();
432 :
433 71684 : auto name = attr.get_path ().get_segments ().at (0).get_segment_name ();
434 143198 : auto is_not_builtin = [&name] (AST::Attribute &attr) {
435 71514 : return Analysis::BuiltinAttributeMappings::get ()
436 71514 : ->lookup_builtin (name)
437 71514 : .is_error ();
438 71684 : };
439 :
440 71684 : if (attr.is_derive ())
441 : {
442 170 : visit_derive_attribute (attr, mappings);
443 : }
444 71514 : else if (is_not_builtin (attr)) // Do not resolve builtins
445 : {
446 1 : visit_non_builtin_attribute (attr, mappings, name);
447 : }
448 :
449 71684 : DefaultResolver::visit (attr);
450 71684 : }
451 :
452 : void
453 0 : Early::finalize_simple_import (const Early::ImportPair &mapping)
454 : {
455 : // FIXME: We probably need to store namespace information
456 :
457 0 : auto import = mapping.import_kind.to_resolve;
458 0 : auto import_id = import.get_final_segment ().get_node_id ();
459 0 : auto data = mapping.data;
460 0 : auto identifier = import.get_final_segment ().get_segment_name ();
461 :
462 0 : for (auto &&definition : data.definitions ())
463 : {
464 0 : ctx.map_usage (Usage (import_id),
465 0 : Definition (definition.definition.get_node_id ()),
466 : definition.ns);
467 :
468 0 : toplevel.insert_or_error_out (identifier, import.get_locus (),
469 0 : definition.definition.get_node_id (),
470 : definition.ns);
471 :
472 0 : dirty = dirty || toplevel.is_dirty ();
473 0 : }
474 0 : }
475 :
476 : void
477 28 : Early::finalize_glob_import (NameResolutionContext &ctx,
478 : const Early::ImportPair &mapping)
479 : {
480 56 : auto container = Analysis::Mappings::get ().lookup_glob_container (
481 56 : mapping.data.container ().get_node_id ());
482 :
483 28 : rust_assert (container);
484 :
485 28 : if (mapping.import_kind.is_prelude)
486 : {
487 2 : rust_assert (container.value ()->get_glob_container_kind ()
488 : == AST::GlobContainer::Kind::Module);
489 :
490 2 : ctx.prelude = mapping.data.container ().get_node_id ();
491 : }
492 :
493 28 : GlobbingVisitor (ctx).go (container.value ());
494 28 : }
495 :
496 : void
497 1131 : Early::finalize_rebind_import (const Early::ImportPair &mapping)
498 : {
499 : // We can fetch the value here as `resolve_rebind` will only be called on
500 : // imports of the right kind
501 1131 : auto &path = mapping.import_kind.to_resolve;
502 1131 : auto &rebind = mapping.import_kind.rebind.value ();
503 1131 : auto data = mapping.data;
504 :
505 1131 : NodeId import_id = UNKNOWN_NODEID;
506 1131 : std::string declared_name;
507 :
508 : // FIXME: This needs to be done in `FinalizeImports`
509 1131 : switch (rebind.get_new_bind_type ())
510 : {
511 3 : case AST::UseTreeRebind::NewBindType::IDENTIFIER:
512 3 : declared_name = rebind.get_identifier ().as_string ();
513 3 : import_id = rebind.get_node_id ();
514 3 : break;
515 1124 : case AST::UseTreeRebind::NewBindType::NONE:
516 1124 : {
517 1124 : const auto &segments = path.get_segments ();
518 : // We don't want to insert `self` with `use module::self`
519 1124 : if (path.get_final_segment ().is_lower_self_seg ())
520 : {
521 : // Erroneous `self` or `{self}` use declaration
522 59 : if (segments.size () == 1)
523 : return;
524 54 : declared_name = segments[segments.size () - 2].as_string ();
525 54 : import_id = segments[segments.size () - 2].get_node_id ();
526 : }
527 : else
528 : {
529 1065 : declared_name = path.get_final_segment ().as_string ();
530 1065 : import_id = path.get_final_segment ().get_node_id ();
531 : }
532 : break;
533 : }
534 : case AST::UseTreeRebind::NewBindType::WILDCARD:
535 : // We don't want to insert it into the trie
536 : return;
537 : }
538 :
539 2383 : for (auto &&definition : data.definitions ())
540 : {
541 1261 : ctx.map_usage (Usage (import_id),
542 1261 : Definition (definition.definition.get_node_id ()),
543 : definition.ns);
544 :
545 3783 : toplevel.insert_or_error_out (declared_name, path.get_locus (),
546 1261 : definition.definition.get_node_id (),
547 : definition.ns);
548 :
549 1261 : dirty = dirty || toplevel.is_dirty ();
550 :
551 : // Map the import to the glob container if it exists - this is important
552 : // for 2-stepped glob imports which refer to glob containers, e.g.
553 : //
554 : // enum Foo { ... }
555 : // pub use Foo;
556 : // use self::Foo::*;
557 1261 : auto &mappings = Analysis::Mappings::get ();
558 1261 : if (auto container = mappings.lookup_glob_container (
559 1261 : definition.definition.get_node_id ()))
560 309 : mappings.insert_glob_container (import_id, container.value ());
561 1122 : }
562 2262 : }
563 :
564 : void
565 1878 : Early::visit (AST::UseDeclaration &decl)
566 : {
567 : // We do not want to visit the use trees, we're only looking for top level
568 : // rebind. eg. `use something;` or `use something::other;`
569 1878 : if (decl.get_tree ()->get_kind () == AST::UseTree::Kind::Rebind)
570 : {
571 1387 : auto &rebind = static_cast<AST::UseTreeRebind &> (*decl.get_tree ());
572 1387 : if (rebind.get_path ().get_final_segment ().is_lower_self_seg ())
573 : {
574 2 : collect_error (
575 1 : Error (decl.get_locus (), ErrorCode::E0429,
576 1 : "%<self%> imports are only allowed within a { } list"));
577 : }
578 : }
579 :
580 1878 : auto &imports = toplevel.get_imports_to_resolve ();
581 1878 : auto current_import = imports.find (decl.get_node_id ());
582 1878 : if (current_import != imports.end ())
583 : {
584 1878 : build_import_mapping (*current_import);
585 : }
586 :
587 : // Once this is done, we finalize their resolution
588 3037 : for (const auto &mapping : import_mappings.get (decl.get_node_id ()))
589 1159 : switch (mapping.import_kind.kind)
590 : {
591 28 : case TopLevel::ImportKind::Kind::Glob:
592 28 : finalize_glob_import (ctx, mapping);
593 28 : break;
594 0 : case TopLevel::ImportKind::Kind::Simple:
595 0 : finalize_simple_import (mapping);
596 0 : break;
597 1131 : case TopLevel::ImportKind::Kind::Rebind:
598 1131 : finalize_rebind_import (mapping);
599 1131 : break;
600 : }
601 :
602 1878 : DefaultResolver::visit (decl);
603 1878 : }
604 :
605 : void
606 461 : Early::visit (AST::UseTreeList &use_list)
607 : {
608 461 : if (!use_list.has_path ())
609 : {
610 10 : for (auto &&tree : use_list.get_trees ())
611 : {
612 6 : if (tree->get_kind () == AST::UseTree::Kind::Rebind)
613 : {
614 6 : auto &rebind = static_cast<AST::UseTreeRebind &> (*tree);
615 6 : auto path_size = rebind.get_path ().get_segments ().size ();
616 6 : if (path_size == 1
617 6 : && rebind.get_path ()
618 6 : .get_final_segment ()
619 6 : .is_lower_self_seg ())
620 : {
621 4 : collect_error (Error (rebind.get_locus (), ErrorCode::E0431,
622 : "%<self%> import can only appear in an "
623 4 : "import list with a non-empty prefix"));
624 : }
625 : }
626 : }
627 : }
628 461 : DefaultResolver::visit (use_list);
629 461 : }
630 :
631 : void
632 57183 : Early::visit (AST::IdentifierPattern &identifier)
633 : {
634 : // check if this is *really* a path pattern
635 57183 : if (!identifier.get_is_ref () && !identifier.get_is_mut ()
636 112113 : && !identifier.has_subpattern ())
637 : {
638 54896 : auto res = ctx.values.get (identifier.get_ident ());
639 54896 : if (res)
640 : {
641 140 : if (res->is_ambiguous ())
642 0 : rust_error_at (identifier.get_locus (), ErrorCode::E0659,
643 : "%qs is ambiguous",
644 0 : identifier.get_ident ().as_string ().c_str ());
645 : else
646 : {
647 : // HACK: bail out if the definition is a function
648 140 : if (!ctx.mappings.is_function_node (res->get_node_id ()))
649 22 : ident_path_to_convert.insert (identifier.get_node_id ());
650 : }
651 : }
652 54896 : }
653 57183 : }
654 :
655 : } // namespace Resolver2_0
656 : } // namespace Rust
|