]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/rust/resolve/rust-early-name-resolver.cc
testsuite: Rename a test
[thirdparty/gcc.git] / gcc / rust / resolve / rust-early-name-resolver.cc
CommitLineData
6441eb6d 1// Copyright (C) 2020-2025 Free Software Foundation, Inc.
52219746
AC
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"
9c50565e 20#include "rust-pattern.h"
52219746 21#include "rust-name-resolver.h"
cf1287ee 22#include "rust-macro-builtins.h"
fc024ea7 23#include "rust-attribute-values.h"
52219746
AC
24
25namespace Rust {
26namespace Resolver {
27
12dd77c1
AC
28// Check if a module contains the `#[macro_use]` attribute
29static bool
30is_macro_use_module (const AST::Module &mod)
31{
32 for (const auto &attr : mod.get_outer_attrs ())
fc024ea7 33 if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE)
12dd77c1
AC
34 return true;
35
36 return false;
37}
38
39std::vector<std::unique_ptr<AST::Item>>
40EarlyNameResolver::accumulate_escaped_macros (AST::Module &module)
41{
42 if (!is_macro_use_module (module))
43 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 if (module.get_kind () == AST::Module::UNLOADED)
49 module.load_items ();
50
51 std::vector<std::unique_ptr<AST::Item>> escaped_macros;
52
53 scoped (module.get_node_id (), [&module, &escaped_macros, this] {
54 for (auto &item : module.get_items ())
55 {
9c50565e 56 if (item->get_item_kind () == AST::Item::Kind::Module)
12dd77c1
AC
57 {
58 auto &module = *static_cast<AST::Module *> (item.get ());
59 auto new_macros = accumulate_escaped_macros (module);
60
61 std::move (new_macros.begin (), new_macros.end (),
62 std::back_inserter (escaped_macros));
63
64 continue;
65 }
66
9c50565e 67 if (item->get_item_kind () == AST::Item::Kind::MacroRulesDefinition)
12dd77c1
AC
68 escaped_macros.emplace_back (item->clone_item ());
69 }
70 });
71
72 return escaped_macros;
73}
74
52219746 75EarlyNameResolver::EarlyNameResolver ()
38216691 76 : current_scope (UNKNOWN_NODEID), resolver (*Resolver::get ()),
fd788dd5 77 mappings (Analysis::Mappings::get ())
52219746
AC
78{}
79
80void
81EarlyNameResolver::go (AST::Crate &crate)
4cd0315a
PEP
82{
83 visit (crate);
84}
85
86void
87EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args)
88{
89 for (auto &arg : generic_args.get_generic_args ())
90 arg.accept_vis (*this);
91
92 for (auto &arg : generic_args.get_binding_args ())
e01c9f40 93 arg.get_type ().accept_vis (*this);
4cd0315a
PEP
94}
95
96void
97EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path)
98{
e01c9f40 99 path.get_type ().accept_vis (*this);
4cd0315a
PEP
100
101 if (path.has_as_clause ())
102 path.get_as_type_path ().accept_vis (*this);
103}
104
105void
106EarlyNameResolver::visit (AST::Crate &crate)
52219746 107{
12dd77c1
AC
108 std::vector<std::unique_ptr<AST::Item>> new_items;
109 auto items = crate.take_items ();
110
111 scoped (crate.get_node_id (), [&items, &new_items, this] {
112 for (auto &&item : items)
113 {
91791450
AC
114 auto new_macros = std::vector<std::unique_ptr<AST::Item>> ();
115
9c50565e 116 if (item->get_item_kind () == AST::Item::Kind::Module)
91791450
AC
117 new_macros = accumulate_escaped_macros (
118 *static_cast<AST::Module *> (item.get ()));
119
120 new_items.emplace_back (std::move (item));
121 std::move (new_macros.begin (), new_macros.end (),
122 std::back_inserter (new_items));
12dd77c1
AC
123 }
124 });
125
126 crate.set_items (std::move (new_items));
127
38216691
AC
128 scoped (crate.get_node_id (), [&crate, this] () {
129 for (auto &item : crate.items)
130 item->accept_vis (*this);
131 });
52219746
AC
132}
133
52219746 134void
9f455ed8 135EarlyNameResolver::visit (AST::DelimTokenTree &)
52219746
AC
136{}
137
138void
9f455ed8 139EarlyNameResolver::visit (AST::AttrInputMetaItemContainer &)
52219746
AC
140{}
141
142void
9f455ed8 143EarlyNameResolver::visit (AST::IdentifierExpr &)
52219746
AC
144{}
145
52219746 146void
9f455ed8 147EarlyNameResolver::visit (AST::LifetimeParam &)
52219746
AC
148{}
149
150void
9f455ed8 151EarlyNameResolver::visit (AST::ConstGenericParam &)
52219746
AC
152{}
153
154// FIXME: ARTHUR: Do we need to perform macro resolution for paths as well?
155// std::arch::asm!()?
156void
157EarlyNameResolver::visit (AST::PathInExpression &path)
158{
379b69c1
AC
159 if (!path.is_lang_item ())
160 for (auto &segment : path.get_segments ())
161 if (segment.has_generic_args ())
162 resolve_generic_args (segment.get_generic_args ());
52219746
AC
163}
164
52219746
AC
165void
166EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment)
167{
168 if (segment.has_generic_args ())
169 resolve_generic_args (segment.get_generic_args ());
170}
171
52219746
AC
172void
173EarlyNameResolver::visit (AST::QualifiedPathInExpression &path)
174{
175 resolve_qualified_path_type (path.get_qualified_path_type ());
176
177 for (auto &segment : path.get_segments ())
178 if (segment.has_generic_args ())
179 resolve_generic_args (segment.get_generic_args ());
180}
181
182void
183EarlyNameResolver::visit (AST::QualifiedPathInType &path)
184{
185 resolve_qualified_path_type (path.get_qualified_path_type ());
186
187 for (auto &segment : path.get_segments ())
188 segment->accept_vis (*this);
189}
190
191void
9f455ed8 192EarlyNameResolver::visit (AST::LiteralExpr &)
52219746
AC
193{}
194
195void
9f455ed8 196EarlyNameResolver::visit (AST::AttrInputLiteral &)
52219746
AC
197{}
198
842a8307
OA
199void
200EarlyNameResolver::visit (AST::AttrInputMacro &)
201{}
202
52219746 203void
9f455ed8 204EarlyNameResolver::visit (AST::MetaItemLitExpr &)
52219746
AC
205{}
206
207void
9f455ed8 208EarlyNameResolver::visit (AST::MetaItemPathLit &)
52219746
AC
209{}
210
52219746 211void
9f455ed8 212EarlyNameResolver::visit (AST::StructExprStruct &)
52219746
AC
213{}
214
215void
9f455ed8 216EarlyNameResolver::visit (AST::StructExprFieldIdentifier &)
52219746
AC
217{}
218
52219746 219void
9f455ed8 220EarlyNameResolver::visit (AST::StructExprStructBase &)
52219746
AC
221{}
222
52219746
AC
223void
224EarlyNameResolver::visit (AST::BlockExpr &expr)
225{
38216691
AC
226 scoped (expr.get_node_id (), [&expr, this] () {
227 for (auto &stmt : expr.get_statements ())
228 stmt->accept_vis (*this);
52219746 229
38216691 230 if (expr.has_tail_expr ())
e01c9f40 231 expr.get_tail_expr ().accept_vis (*this);
38216691 232 });
52219746
AC
233}
234
52219746 235void
9f455ed8 236EarlyNameResolver::visit (AST::ContinueExpr &)
52219746
AC
237{}
238
52219746 239void
9f455ed8 240EarlyNameResolver::visit (AST::RangeFullExpr &)
52219746
AC
241{}
242
52219746
AC
243void
244EarlyNameResolver::visit (AST::ForLoopExpr &expr)
245{
38216691 246 scoped (expr.get_node_id (), [&expr, this] () {
e01c9f40
PEP
247 expr.get_pattern ().accept_vis (*this);
248 expr.get_iterator_expr ().accept_vis (*this);
249 expr.get_loop_block ().accept_vis (*this);
38216691 250 });
52219746
AC
251}
252
52219746
AC
253void
254EarlyNameResolver::visit (AST::IfLetExpr &expr)
255{
e01c9f40 256 expr.get_value_expr ().accept_vis (*this);
38216691
AC
257
258 scoped (expr.get_node_id (),
e01c9f40 259 [&expr, this] () { expr.get_if_block ().accept_vis (*this); });
52219746
AC
260}
261
52219746
AC
262void
263EarlyNameResolver::visit (AST::MatchExpr &expr)
264{
e01c9f40 265 expr.get_scrutinee_expr ().accept_vis (*this);
52219746 266
38216691
AC
267 scoped (expr.get_node_id (), [&expr, this] () {
268 for (auto &arm : expr.get_match_cases ())
269 {
270 scoped (arm.get_node_id (), [&arm, this] () {
271 if (arm.get_arm ().has_match_arm_guard ())
e01c9f40 272 arm.get_arm ().get_guard_expr ().accept_vis (*this);
52219746 273
38216691
AC
274 for (auto &pattern : arm.get_arm ().get_patterns ())
275 pattern->accept_vis (*this);
276
e01c9f40 277 arm.get_expr ().accept_vis (*this);
38216691
AC
278 });
279 }
280 });
52219746
AC
281}
282
52219746 283void
9f455ed8 284EarlyNameResolver::visit (AST::LifetimeWhereClauseItem &)
52219746
AC
285{}
286
52219746
AC
287void
288EarlyNameResolver::visit (AST::Module &module)
289{
eba55786
AC
290 if (module.get_kind () == AST::Module::UNLOADED)
291 module.load_items ();
292
12dd77c1
AC
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 std::vector<std::unique_ptr<AST::Item>> new_items;
297 auto items = module.take_items ();
298
299 scoped (module.get_node_id (), [&items, &new_items, this] {
300 for (auto &&item : items)
301 {
91791450
AC
302 auto new_macros = std::vector<std::unique_ptr<AST::Item>> ();
303
9c50565e 304 if (item->get_item_kind () == AST::Item::Kind::Module)
91791450
AC
305 new_macros = accumulate_escaped_macros (
306 *static_cast<AST::Module *> (item.get ()));
307
308 new_items.emplace_back (std::move (item));
309 std::move (new_macros.begin (), new_macros.end (),
310 std::back_inserter (new_items));
12dd77c1
AC
311 }
312 });
313
314 module.set_items (std::move (new_items));
315
38216691
AC
316 scoped (module.get_node_id (), [&module, this] () {
317 for (auto &item : module.get_items ())
318 item->accept_vis (*this);
319 });
52219746
AC
320}
321
322void
9f455ed8 323EarlyNameResolver::visit (AST::ExternCrate &)
52219746
AC
324{}
325
326void
9f455ed8 327EarlyNameResolver::visit (AST::UseTreeGlob &)
52219746
AC
328{}
329
330void
9f455ed8 331EarlyNameResolver::visit (AST::UseTreeList &)
52219746
AC
332{}
333
334void
9f455ed8 335EarlyNameResolver::visit (AST::UseTreeRebind &)
52219746
AC
336{}
337
338void
9f455ed8 339EarlyNameResolver::visit (AST::UseDeclaration &)
52219746
AC
340{}
341
52219746 342void
9f455ed8 343EarlyNameResolver::visit (AST::EnumItem &)
52219746
AC
344{}
345
52219746 346void
9f455ed8 347EarlyNameResolver::visit (AST::Union &)
52219746
AC
348{}
349
52219746 350void
9f455ed8 351EarlyNameResolver::visit (AST::TraitItemType &)
52219746
AC
352{}
353
354void
355EarlyNameResolver::visit (AST::Trait &trait)
356{
c92c217c
OA
357 // shouldn't need to visit trait.get_implicit_self ()
358
38216691
AC
359 for (auto &generic : trait.get_generic_params ())
360 generic->accept_vis (*this);
361
362 scoped (trait.get_node_id (), [&trait, this] () {
363 for (auto &item : trait.get_trait_items ())
364 item->accept_vis (*this);
365 });
52219746
AC
366}
367
368void
369EarlyNameResolver::visit (AST::InherentImpl &impl)
370{
e01c9f40 371 impl.get_type ().accept_vis (*this);
52219746
AC
372
373 for (auto &generic : impl.get_generic_params ())
374 generic->accept_vis (*this);
375
38216691
AC
376 scoped (impl.get_node_id (), [&impl, this] () {
377 for (auto &item : impl.get_impl_items ())
378 item->accept_vis (*this);
379 });
52219746
AC
380}
381
382void
383EarlyNameResolver::visit (AST::TraitImpl &impl)
384{
e01c9f40 385 impl.get_type ().accept_vis (*this);
52219746
AC
386
387 for (auto &generic : impl.get_generic_params ())
388 generic->accept_vis (*this);
389
38216691
AC
390 scoped (impl.get_node_id (), [&impl, this] () {
391 for (auto &item : impl.get_impl_items ())
392 item->accept_vis (*this);
393 });
52219746
AC
394}
395
a8a27b07
AC
396void
397EarlyNameResolver::visit (AST::ExternalTypeItem &item)
398{
399 // nothing to do?
400}
401
52219746
AC
402void
403EarlyNameResolver::visit (AST::ExternBlock &block)
404{
38216691
AC
405 scoped (block.get_node_id (), [&block, this] () {
406 for (auto &item : block.get_extern_items ())
407 item->accept_vis (*this);
408 });
52219746
AC
409}
410
52219746 411void
9f455ed8 412EarlyNameResolver::visit (AST::MacroMatchRepetition &)
52219746
AC
413{}
414
415void
9f455ed8 416EarlyNameResolver::visit (AST::MacroMatcher &)
52219746
AC
417{}
418
419void
420EarlyNameResolver::visit (AST::MacroRulesDefinition &rules_def)
421{
422 auto path = CanonicalPath::new_seg (rules_def.get_node_id (),
fcb228d1 423 rules_def.get_rule_name ().as_string ());
52219746
AC
424 resolver.get_macro_scope ().insert (path, rules_def.get_node_id (),
425 rules_def.get_locus ());
38216691
AC
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
e4778ece 431 if (mappings.lookup_macro_def (rules_def.get_node_id ()))
38216691
AC
432 return;
433
52219746
AC
434 mappings.insert_macro_def (&rules_def);
435 rust_debug_loc (rules_def.get_locus (), "inserting macro def: [%s]",
436 path.get ().c_str ());
437}
438
439void
440EarlyNameResolver::visit (AST::MacroInvocation &invoc)
441{
442 auto &invoc_data = invoc.get_invoc_data ();
443 auto has_semicolon = invoc.has_semicolon ();
444
38216691
AC
445 if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
446 for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
447 pending_invoc->accept_vis (*this);
448
52219746
AC
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 NodeId resolved_node = UNKNOWN_NODEID;
469 NodeId source_node = UNKNOWN_NODEID;
470 if (has_semicolon)
471 source_node = invoc.get_macro_node_id ();
472 else
292aec08 473 source_node = invoc.get_node_id ();
52219746
AC
474 auto seg
475 = CanonicalPath::new_seg (source_node, invoc_data.get_path ().as_string ());
476
477 bool found = resolver.get_macro_scope ().lookup (seg, &resolved_node);
478 if (!found)
479 {
f60b2106
OA
480 rust_error_at (invoc.get_locus (), ErrorCode::E0433,
481 "could not resolve macro invocation %qs",
52219746
AC
482 seg.get ().c_str ());
483 return;
484 }
485
486 // lookup the rules
e4778ece 487 auto rules_def = mappings.lookup_macro_def (resolved_node);
52219746 488
e4778ece 489 auto &outer_attrs = rules_def.value ()->get_outer_attrs ();
38216691
AC
490 bool is_builtin
491 = std::any_of (outer_attrs.begin (), outer_attrs.end (),
492 [] (AST::Attribute attr) {
fc024ea7
PEP
493 return attr.get_path ()
494 == Values::Attributes::RUSTC_BUILTIN_MACRO;
38216691
AC
495 });
496
497 if (is_builtin)
498 {
e4778ece
PEP
499 auto builtin_kind = builtin_macro_from_string (
500 rules_def.value ()->get_rule_name ().as_string ());
5d30562d 501 invoc.map_to_builtin (builtin_kind.value ());
38216691
AC
502 }
503
e4778ece 504 auto attributes = rules_def.value ()->get_outer_attrs ();
38216691
AC
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
1d7d56aa 510 if (mappings.lookup_macro_invocation (invoc))
38216691
AC
511 return;
512
e4778ece 513 mappings.insert_macro_invocation (invoc, *rules_def);
52219746
AC
514}
515
516// FIXME: ARTHUR: Do we need to resolve these as well here?
517
518void
9f455ed8 519EarlyNameResolver::visit (AST::MetaItemPath &)
52219746
AC
520{}
521
522void
9f455ed8 523EarlyNameResolver::visit (AST::MetaItemSeq &)
52219746
AC
524{}
525
52219746 526void
9f455ed8 527EarlyNameResolver::visit (AST::MetaNameValueStr &)
52219746
AC
528{}
529
530void
9f455ed8 531EarlyNameResolver::visit (AST::MetaListPaths &)
52219746
AC
532{}
533
534void
9f455ed8 535EarlyNameResolver::visit (AST::MetaListNameValueStr &)
52219746
AC
536{}
537
52219746 538void
9f455ed8 539EarlyNameResolver::visit (AST::RangePatternBoundLiteral &)
52219746
AC
540{}
541
542void
9f455ed8 543EarlyNameResolver::visit (AST::RangePatternBoundPath &)
52219746
AC
544{}
545
546void
9f455ed8 547EarlyNameResolver::visit (AST::RangePatternBoundQualPath &)
52219746
AC
548{}
549
52219746 550void
9f455ed8 551EarlyNameResolver::visit (AST::StructPatternFieldIdent &)
52219746
AC
552{}
553
554void
9f455ed8 555EarlyNameResolver::visit (AST::StructPattern &)
52219746
AC
556{}
557
52219746
AC
558void
559EarlyNameResolver::visit (AST::TupleStructPattern &pattern)
560{
e01c9f40 561 pattern.get_items ().accept_vis (*this);
52219746
AC
562}
563
52219746 564void
9f455ed8 565EarlyNameResolver::visit (AST::TupleType &)
52219746
AC
566{}
567
52219746 568void
9f455ed8 569EarlyNameResolver::visit (AST::RawPointerType &)
52219746
AC
570{}
571
572void
9f455ed8 573EarlyNameResolver::visit (AST::ReferenceType &)
52219746
AC
574{}
575
576void
9f455ed8 577EarlyNameResolver::visit (AST::ArrayType &)
52219746
AC
578{}
579
580void
9f455ed8 581EarlyNameResolver::visit (AST::SliceType &)
52219746
AC
582{}
583
584void
9f455ed8 585EarlyNameResolver::visit (AST::InferredType &)
52219746
AC
586{}
587
52219746
AC
588} // namespace Resolver
589} // namespace Rust