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-early-name-resolver.h"
20 : : #include "rust-pattern.h"
21 : : #include "rust-name-resolver.h"
22 : : #include "rust-macro-builtins.h"
23 : : #include "rust-attribute-values.h"
24 : :
25 : : namespace Rust {
26 : : namespace Resolver {
27 : :
28 : : // Check if a module contains the `#[macro_use]` attribute
29 : : static bool
30 : 1412 : is_macro_use_module (const AST::Module &mod)
31 : : {
32 : 1547 : for (const auto &attr : mod.get_outer_attrs ())
33 : 193 : if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE)
34 : 1412 : return true;
35 : :
36 : : return false;
37 : : }
38 : :
39 : : std::vector<std::unique_ptr<AST::Item>>
40 : 1412 : EarlyNameResolver::accumulate_escaped_macros (AST::Module &module)
41 : : {
42 : 1412 : if (!is_macro_use_module (module))
43 : 1354 : return {};
44 : :
45 : : // Parse the module's items if they haven't been expanded and the file
46 : : // should be parsed (i.e isn't hidden behind an untrue or impossible cfg
47 : : // directive)
48 : 58 : if (module.get_kind () == AST::Module::UNLOADED)
49 : 0 : module.load_items ();
50 : :
51 : 58 : std::vector<std::unique_ptr<AST::Item>> escaped_macros;
52 : :
53 : 58 : scoped (module.get_node_id (), [&module, &escaped_macros, this] {
54 : 153 : for (auto &item : module.get_items ())
55 : : {
56 : 95 : if (item->get_item_kind () == AST::Item::Kind::Module)
57 : : {
58 : 14 : auto &module = *static_cast<AST::Module *> (item.get ());
59 : 14 : auto new_macros = accumulate_escaped_macros (module);
60 : :
61 : 14 : std::move (new_macros.begin (), new_macros.end (),
62 : : std::back_inserter (escaped_macros));
63 : :
64 : 14 : continue;
65 : 14 : }
66 : :
67 : 81 : if (item->get_item_kind () == AST::Item::Kind::MacroRulesDefinition)
68 : 79 : escaped_macros.emplace_back (item->clone_item ());
69 : : }
70 : 58 : });
71 : :
72 : 58 : return escaped_macros;
73 : 58 : }
74 : :
75 : 6509 : EarlyNameResolver::EarlyNameResolver ()
76 : 6509 : : current_scope (UNKNOWN_NODEID), resolver (*Resolver::get ()),
77 : 6509 : mappings (Analysis::Mappings::get ())
78 : 6509 : {}
79 : :
80 : : void
81 : 6509 : EarlyNameResolver::go (AST::Crate &crate)
82 : : {
83 : 6509 : visit (crate);
84 : 6509 : }
85 : :
86 : : void
87 : 2762 : EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args)
88 : : {
89 : 5828 : for (auto &arg : generic_args.get_generic_args ())
90 : 3066 : arg.accept_vis (*this);
91 : :
92 : 2801 : for (auto &arg : generic_args.get_binding_args ())
93 : 39 : arg.get_type ().accept_vis (*this);
94 : 2762 : }
95 : :
96 : : void
97 : 355 : EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path)
98 : : {
99 : 355 : path.get_type ().accept_vis (*this);
100 : :
101 : 355 : if (path.has_as_clause ())
102 : 296 : path.get_as_type_path ().accept_vis (*this);
103 : 355 : }
104 : :
105 : : void
106 : 6509 : EarlyNameResolver::visit (AST::Crate &crate)
107 : : {
108 : 6509 : std::vector<std::unique_ptr<AST::Item>> new_items;
109 : 6509 : auto items = crate.take_items ();
110 : :
111 : 6509 : scoped (crate.get_node_id (), [&items, &new_items, this] {
112 : 31572 : for (auto &&item : items)
113 : : {
114 : 25063 : auto new_macros = std::vector<std::unique_ptr<AST::Item>> ();
115 : :
116 : 25063 : if (item->get_item_kind () == AST::Item::Kind::Module)
117 : 2340 : new_macros = accumulate_escaped_macros (
118 : 2340 : *static_cast<AST::Module *> (item.get ()));
119 : :
120 : 25063 : new_items.emplace_back (std::move (item));
121 : 25063 : std::move (new_macros.begin (), new_macros.end (),
122 : : std::back_inserter (new_items));
123 : 25063 : }
124 : 6509 : });
125 : :
126 : 6509 : crate.set_items (std::move (new_items));
127 : :
128 : 6509 : scoped (crate.get_node_id (), [&crate, this] () {
129 : 31640 : for (auto &item : crate.items)
130 : 25131 : item->accept_vis (*this);
131 : 6509 : });
132 : 6509 : }
133 : :
134 : : void
135 : 0 : EarlyNameResolver::visit (AST::DelimTokenTree &)
136 : 0 : {}
137 : :
138 : : void
139 : 0 : EarlyNameResolver::visit (AST::AttrInputMetaItemContainer &)
140 : 0 : {}
141 : :
142 : : void
143 : 26404 : EarlyNameResolver::visit (AST::IdentifierExpr &)
144 : 26404 : {}
145 : :
146 : : void
147 : 266 : EarlyNameResolver::visit (AST::LifetimeParam &)
148 : 266 : {}
149 : :
150 : : void
151 : 25 : EarlyNameResolver::visit (AST::ConstGenericParam &)
152 : 25 : {}
153 : :
154 : : // FIXME: ARTHUR: Do we need to perform macro resolution for paths as well?
155 : : // std::arch::asm!()?
156 : : void
157 : 22721 : EarlyNameResolver::visit (AST::PathInExpression &path)
158 : : {
159 : 22721 : if (!path.is_lang_item ())
160 : 52497 : for (auto &segment : path.get_segments ())
161 : 59598 : if (segment.has_generic_args ())
162 : 639 : resolve_generic_args (segment.get_generic_args ());
163 : 22721 : }
164 : :
165 : : void
166 : 2123 : EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment)
167 : : {
168 : 2123 : if (segment.has_generic_args ())
169 : 2123 : resolve_generic_args (segment.get_generic_args ());
170 : 2123 : }
171 : :
172 : : void
173 : 121 : EarlyNameResolver::visit (AST::QualifiedPathInExpression &path)
174 : : {
175 : 121 : resolve_qualified_path_type (path.get_qualified_path_type ());
176 : :
177 : 242 : for (auto &segment : path.get_segments ())
178 : 242 : if (segment.has_generic_args ())
179 : 0 : resolve_generic_args (segment.get_generic_args ());
180 : 121 : }
181 : :
182 : : void
183 : 234 : EarlyNameResolver::visit (AST::QualifiedPathInType &path)
184 : : {
185 : 234 : resolve_qualified_path_type (path.get_qualified_path_type ());
186 : :
187 : 234 : for (auto &segment : path.get_segments ())
188 : 0 : segment->accept_vis (*this);
189 : 234 : }
190 : :
191 : : void
192 : 542681 : EarlyNameResolver::visit (AST::LiteralExpr &)
193 : 542681 : {}
194 : :
195 : : void
196 : 0 : EarlyNameResolver::visit (AST::AttrInputLiteral &)
197 : 0 : {}
198 : :
199 : : void
200 : 0 : EarlyNameResolver::visit (AST::AttrInputMacro &)
201 : 0 : {}
202 : :
203 : : void
204 : 0 : EarlyNameResolver::visit (AST::MetaItemLitExpr &)
205 : 0 : {}
206 : :
207 : : void
208 : 0 : EarlyNameResolver::visit (AST::MetaItemPathLit &)
209 : 0 : {}
210 : :
211 : : void
212 : 50 : EarlyNameResolver::visit (AST::StructExprStruct &)
213 : 50 : {}
214 : :
215 : : void
216 : 243 : EarlyNameResolver::visit (AST::StructExprFieldIdentifier &)
217 : 243 : {}
218 : :
219 : : void
220 : 0 : EarlyNameResolver::visit (AST::StructExprStructBase &)
221 : 0 : {}
222 : :
223 : : void
224 : 26066 : EarlyNameResolver::visit (AST::BlockExpr &expr)
225 : : {
226 : 26066 : scoped (expr.get_node_id (), [&expr, this] () {
227 : 52455 : for (auto &stmt : expr.get_statements ())
228 : 26389 : stmt->accept_vis (*this);
229 : :
230 : 26066 : if (expr.has_tail_expr ())
231 : 19461 : expr.get_tail_expr ().accept_vis (*this);
232 : 26066 : });
233 : 26066 : }
234 : :
235 : : void
236 : 17 : EarlyNameResolver::visit (AST::ContinueExpr &)
237 : 17 : {}
238 : :
239 : : void
240 : 0 : EarlyNameResolver::visit (AST::RangeFullExpr &)
241 : 0 : {}
242 : :
243 : : void
244 : 48 : EarlyNameResolver::visit (AST::ForLoopExpr &expr)
245 : : {
246 : 48 : scoped (expr.get_node_id (), [&expr, this] () {
247 : 48 : expr.get_pattern ().accept_vis (*this);
248 : 48 : expr.get_iterator_expr ().accept_vis (*this);
249 : 48 : expr.get_loop_block ().accept_vis (*this);
250 : 48 : });
251 : 48 : }
252 : :
253 : : void
254 : 30 : EarlyNameResolver::visit (AST::IfLetExpr &expr)
255 : : {
256 : 30 : expr.get_value_expr ().accept_vis (*this);
257 : :
258 : 30 : scoped (expr.get_node_id (),
259 : 60 : [&expr, this] () { expr.get_if_block ().accept_vis (*this); });
260 : 30 : }
261 : :
262 : : void
263 : 535 : EarlyNameResolver::visit (AST::MatchExpr &expr)
264 : : {
265 : 535 : expr.get_scrutinee_expr ().accept_vis (*this);
266 : :
267 : 535 : scoped (expr.get_node_id (), [&expr, this] () {
268 : 1722 : for (auto &arm : expr.get_match_cases ())
269 : : {
270 : 1187 : scoped (arm.get_node_id (), [&arm, this] () {
271 : 1187 : if (arm.get_arm ().has_match_arm_guard ())
272 : 2 : arm.get_arm ().get_guard_expr ().accept_vis (*this);
273 : :
274 : 2374 : for (auto &pattern : arm.get_arm ().get_patterns ())
275 : 1187 : pattern->accept_vis (*this);
276 : :
277 : 1187 : arm.get_expr ().accept_vis (*this);
278 : 1187 : });
279 : : }
280 : 535 : });
281 : 535 : }
282 : :
283 : : void
284 : 2 : EarlyNameResolver::visit (AST::LifetimeWhereClauseItem &)
285 : 2 : {}
286 : :
287 : : void
288 : 1398 : EarlyNameResolver::visit (AST::Module &module)
289 : : {
290 : 1398 : if (module.get_kind () == AST::Module::UNLOADED)
291 : 63 : module.load_items ();
292 : :
293 : : // so we need to only go "one scope down" for fetching macros. Macros within
294 : : // functions are still scoped only within that function. But we have to be
295 : : // careful because nested modules with #[macro_use] actually works!
296 : 1398 : std::vector<std::unique_ptr<AST::Item>> new_items;
297 : 1398 : auto items = module.take_items ();
298 : :
299 : 1398 : scoped (module.get_node_id (), [&items, &new_items, this] {
300 : 6854 : for (auto &&item : items)
301 : : {
302 : 5456 : auto new_macros = std::vector<std::unique_ptr<AST::Item>> ();
303 : :
304 : 5456 : if (item->get_item_kind () == AST::Item::Kind::Module)
305 : 456 : new_macros = accumulate_escaped_macros (
306 : 456 : *static_cast<AST::Module *> (item.get ()));
307 : :
308 : 5456 : new_items.emplace_back (std::move (item));
309 : 5456 : std::move (new_macros.begin (), new_macros.end (),
310 : : std::back_inserter (new_items));
311 : 5456 : }
312 : 1398 : });
313 : :
314 : 1398 : module.set_items (std::move (new_items));
315 : :
316 : 1398 : scoped (module.get_node_id (), [&module, this] () {
317 : 6865 : for (auto &item : module.get_items ())
318 : 5467 : item->accept_vis (*this);
319 : 1398 : });
320 : 1398 : }
321 : :
322 : : void
323 : 27 : EarlyNameResolver::visit (AST::ExternCrate &)
324 : 27 : {}
325 : :
326 : : void
327 : 0 : EarlyNameResolver::visit (AST::UseTreeGlob &)
328 : 0 : {}
329 : :
330 : : void
331 : 0 : EarlyNameResolver::visit (AST::UseTreeList &)
332 : 0 : {}
333 : :
334 : : void
335 : 0 : EarlyNameResolver::visit (AST::UseTreeRebind &)
336 : 0 : {}
337 : :
338 : : void
339 : 565 : EarlyNameResolver::visit (AST::UseDeclaration &)
340 : 565 : {}
341 : :
342 : : void
343 : 1023 : EarlyNameResolver::visit (AST::EnumItem &)
344 : 1023 : {}
345 : :
346 : : void
347 : 106 : EarlyNameResolver::visit (AST::Union &)
348 : 106 : {}
349 : :
350 : : void
351 : 1007 : EarlyNameResolver::visit (AST::TraitItemType &)
352 : 1007 : {}
353 : :
354 : : void
355 : 3862 : EarlyNameResolver::visit (AST::Trait &trait)
356 : : {
357 : : // shouldn't need to visit trait.get_implicit_self ()
358 : :
359 : 4548 : for (auto &generic : trait.get_generic_params ())
360 : 686 : generic->accept_vis (*this);
361 : :
362 : 3862 : scoped (trait.get_node_id (), [&trait, this] () {
363 : 7468 : for (auto &item : trait.get_trait_items ())
364 : 3606 : item->accept_vis (*this);
365 : 3862 : });
366 : 3862 : }
367 : :
368 : : void
369 : 1158 : EarlyNameResolver::visit (AST::InherentImpl &impl)
370 : : {
371 : 1158 : impl.get_type ().accept_vis (*this);
372 : :
373 : 1579 : for (auto &generic : impl.get_generic_params ())
374 : 421 : generic->accept_vis (*this);
375 : :
376 : 1158 : scoped (impl.get_node_id (), [&impl, this] () {
377 : 5099 : for (auto &item : impl.get_impl_items ())
378 : 3941 : item->accept_vis (*this);
379 : 1158 : });
380 : 1158 : }
381 : :
382 : : void
383 : 5262 : EarlyNameResolver::visit (AST::TraitImpl &impl)
384 : : {
385 : 5262 : impl.get_type ().accept_vis (*this);
386 : :
387 : 6352 : for (auto &generic : impl.get_generic_params ())
388 : 1090 : generic->accept_vis (*this);
389 : :
390 : 5262 : scoped (impl.get_node_id (), [&impl, this] () {
391 : 11113 : for (auto &item : impl.get_impl_items ())
392 : 5851 : item->accept_vis (*this);
393 : 5262 : });
394 : 5262 : }
395 : :
396 : : void
397 : 1 : EarlyNameResolver::visit (AST::ExternalTypeItem &item)
398 : : {
399 : : // nothing to do?
400 : 1 : }
401 : :
402 : : void
403 : 1864 : EarlyNameResolver::visit (AST::ExternBlock &block)
404 : : {
405 : 1864 : scoped (block.get_node_id (), [&block, this] () {
406 : 5109 : for (auto &item : block.get_extern_items ())
407 : 3245 : item->accept_vis (*this);
408 : 1864 : });
409 : 1864 : }
410 : :
411 : : void
412 : 0 : EarlyNameResolver::visit (AST::MacroMatchRepetition &)
413 : 0 : {}
414 : :
415 : : void
416 : 0 : EarlyNameResolver::visit (AST::MacroMatcher &)
417 : 0 : {}
418 : :
419 : : void
420 : 3803 : EarlyNameResolver::visit (AST::MacroRulesDefinition &rules_def)
421 : : {
422 : 3803 : auto path = CanonicalPath::new_seg (rules_def.get_node_id (),
423 : 3803 : rules_def.get_rule_name ().as_string ());
424 : 3803 : resolver.get_macro_scope ().insert (path, rules_def.get_node_id (),
425 : : rules_def.get_locus ());
426 : :
427 : : /* Since the EarlyNameResolver runs multiple time (fixed point algorithm)
428 : : * we could be inserting the same macro def over and over again until we
429 : : * implement some optimizations */
430 : : // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead
431 : 3803 : if (mappings.lookup_macro_def (rules_def.get_node_id ()))
432 : 2670 : return;
433 : :
434 : 1133 : mappings.insert_macro_def (&rules_def);
435 : 1133 : rust_debug_loc (rules_def.get_locus (), "inserting macro def: [%s]",
436 : 2266 : path.get ().c_str ());
437 : 3803 : }
438 : :
439 : : void
440 : 2954 : EarlyNameResolver::visit (AST::MacroInvocation &invoc)
441 : : {
442 : 2954 : auto &invoc_data = invoc.get_invoc_data ();
443 : 2954 : auto has_semicolon = invoc.has_semicolon ();
444 : :
445 : 2954 : if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
446 : 87 : for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
447 : 45 : pending_invoc->accept_vis (*this);
448 : :
449 : : // ??
450 : : // switch on type of macro:
451 : : // - '!' syntax macro (inner switch)
452 : : // - procedural macro - "A token-based function-like macro"
453 : : // - 'macro_rules' (by example/pattern-match) macro? or not? "an
454 : : // AST-based function-like macro"
455 : : // - else is unreachable
456 : : // - attribute syntax macro (inner switch)
457 : : // - procedural macro attribute syntax - "A token-based attribute
458 : : // macro"
459 : : // - legacy macro attribute syntax? - "an AST-based attribute macro"
460 : : // - non-macro attribute: mark known
461 : : // - else is unreachable
462 : : // - derive macro (inner switch)
463 : : // - derive or legacy derive - "token-based" vs "AST-based"
464 : : // - else is unreachable
465 : : // - derive container macro - unreachable
466 : :
467 : : // lookup the rules for this macro
468 : 2954 : NodeId resolved_node = UNKNOWN_NODEID;
469 : 2954 : NodeId source_node = UNKNOWN_NODEID;
470 : 2954 : if (has_semicolon)
471 : 787 : source_node = invoc.get_macro_node_id ();
472 : : else
473 : 2167 : source_node = invoc.get_node_id ();
474 : 2954 : auto seg
475 : 2954 : = CanonicalPath::new_seg (source_node, invoc_data.get_path ().as_string ());
476 : :
477 : 2954 : bool found = resolver.get_macro_scope ().lookup (seg, &resolved_node);
478 : 2954 : if (!found)
479 : : {
480 : 8 : rust_error_at (invoc.get_locus (), ErrorCode::E0433,
481 : : "could not resolve macro invocation %qs",
482 : 8 : seg.get ().c_str ());
483 : 8 : return;
484 : : }
485 : :
486 : : // lookup the rules
487 : 2946 : auto rules_def = mappings.lookup_macro_def (resolved_node);
488 : :
489 : 2946 : auto &outer_attrs = rules_def.value ()->get_outer_attrs ();
490 : 2946 : bool is_builtin
491 : 2946 : = std::any_of (outer_attrs.begin (), outer_attrs.end (),
492 : 397 : [] (AST::Attribute attr) {
493 : 397 : return attr.get_path ()
494 : 397 : == Values::Attributes::RUSTC_BUILTIN_MACRO;
495 : : });
496 : :
497 : 2946 : if (is_builtin)
498 : : {
499 : 397 : auto builtin_kind = builtin_macro_from_string (
500 : 397 : rules_def.value ()->get_rule_name ().as_string ());
501 : 397 : invoc.map_to_builtin (builtin_kind.value ());
502 : : }
503 : :
504 : 2946 : auto attributes = rules_def.value ()->get_outer_attrs ();
505 : :
506 : : /* Since the EarlyNameResolver runs multiple time (fixed point algorithm)
507 : : * we could be inserting the same macro def over and over again until we
508 : : * implement some optimizations */
509 : : // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead
510 : 2946 : if (mappings.lookup_macro_invocation (invoc))
511 : 0 : return;
512 : :
513 : 2946 : mappings.insert_macro_invocation (invoc, *rules_def);
514 : 2954 : }
515 : :
516 : : // FIXME: ARTHUR: Do we need to resolve these as well here?
517 : :
518 : : void
519 : 0 : EarlyNameResolver::visit (AST::MetaItemPath &)
520 : 0 : {}
521 : :
522 : : void
523 : 0 : EarlyNameResolver::visit (AST::MetaItemSeq &)
524 : 0 : {}
525 : :
526 : : void
527 : 0 : EarlyNameResolver::visit (AST::MetaNameValueStr &)
528 : 0 : {}
529 : :
530 : : void
531 : 0 : EarlyNameResolver::visit (AST::MetaListPaths &)
532 : 0 : {}
533 : :
534 : : void
535 : 0 : EarlyNameResolver::visit (AST::MetaListNameValueStr &)
536 : 0 : {}
537 : :
538 : : void
539 : 23 : EarlyNameResolver::visit (AST::RangePatternBoundLiteral &)
540 : 23 : {}
541 : :
542 : : void
543 : 21 : EarlyNameResolver::visit (AST::RangePatternBoundPath &)
544 : 21 : {}
545 : :
546 : : void
547 : 0 : EarlyNameResolver::visit (AST::RangePatternBoundQualPath &)
548 : 0 : {}
549 : :
550 : : void
551 : 0 : EarlyNameResolver::visit (AST::StructPatternFieldIdent &)
552 : 0 : {}
553 : :
554 : : void
555 : 85 : EarlyNameResolver::visit (AST::StructPattern &)
556 : 85 : {}
557 : :
558 : : void
559 : 478 : EarlyNameResolver::visit (AST::TupleStructPattern &pattern)
560 : : {
561 : 478 : pattern.get_items ().accept_vis (*this);
562 : 478 : }
563 : :
564 : : void
565 : 555 : EarlyNameResolver::visit (AST::TupleType &)
566 : 555 : {}
567 : :
568 : : void
569 : 8792 : EarlyNameResolver::visit (AST::RawPointerType &)
570 : 8792 : {}
571 : :
572 : : void
573 : 3057 : EarlyNameResolver::visit (AST::ReferenceType &)
574 : 3057 : {}
575 : :
576 : : void
577 : 801 : EarlyNameResolver::visit (AST::ArrayType &)
578 : 801 : {}
579 : :
580 : : void
581 : 118 : EarlyNameResolver::visit (AST::SliceType &)
582 : 118 : {}
583 : :
584 : : void
585 : 73 : EarlyNameResolver::visit (AST::InferredType &)
586 : 73 : {}
587 : :
588 : : } // namespace Resolver
589 : : } // namespace Rust
|