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-toplevel-name-resolver-2.0.h"
20 : #include "input.h"
21 : #include "optional.h"
22 : #include "rust-ast-full.h"
23 : #include "rust-hir-map.h"
24 : #include "rust-attribute-values.h"
25 :
26 : namespace Rust {
27 : namespace Resolver2_0 {
28 :
29 15370 : TopLevel::TopLevel (NameResolutionContext &resolver)
30 15370 : : DefaultResolver (resolver), dirty (false)
31 15370 : {}
32 :
33 : template <typename T>
34 : void
35 4324 : TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
36 : const T &node, bool is_also_value)
37 : {
38 4324 : insert_enum_variant_or_error_out (identifier, node.get_locus (),
39 4324 : node.get_node_id (), is_also_value);
40 4324 : }
41 :
42 : void
43 156716 : TopLevel::check_multiple_insertion_error (
44 : tl::expected<NodeId, DuplicateNameError> result, const Identifier &identifier,
45 : const location_t &locus, const NodeId node_id)
46 : {
47 156716 : if (result)
48 47056 : dirty = true;
49 109660 : else if (result.error ().existing != node_id)
50 : {
51 15 : rich_location rich_loc (line_table, locus);
52 15 : rich_loc.add_range (node_locations[result.error ().existing]);
53 :
54 15 : rust_error_at (rich_loc, ErrorCode::E0428, "%qs defined multiple times",
55 15 : identifier.as_string ().c_str ());
56 15 : }
57 156716 : }
58 : void
59 4324 : TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
60 : const location_t &locus,
61 : const NodeId node_id,
62 : bool is_also_value)
63 : {
64 : // keep track of each node's location to provide useful errors
65 4324 : node_locations.emplace (node_id, locus);
66 :
67 4324 : auto result = ctx.insert_variant (identifier, node_id, is_also_value);
68 7369 : check_multiple_insertion_error (result, identifier, locus, node_id);
69 4324 : }
70 :
71 : template <typename T>
72 : void
73 148839 : TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
74 : Namespace ns)
75 : {
76 148839 : insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns);
77 148839 : }
78 :
79 : void
80 152392 : TopLevel::insert_or_error_out (const Identifier &identifier,
81 : const location_t &locus, const NodeId &node_id,
82 : Namespace ns)
83 : {
84 : // keep track of each node's location to provide useful errors
85 152392 : node_locations.emplace (node_id, locus);
86 :
87 152392 : auto result = ctx.insert (identifier, node_id, ns);
88 259007 : check_multiple_insertion_error (result, identifier, locus, node_id);
89 152392 : }
90 :
91 : void
92 15370 : TopLevel::go (AST::Crate &crate)
93 : {
94 : // we do not include builtin types in the top-level definition collector, as
95 : // they are not used until `Late`. furthermore, we run this visitor multiple
96 : // times in a row in a fixed-point fashion, so it would make the code
97 : // responsible for this ugly and perfom a lot of error checking.
98 :
99 15370 : visit (crate);
100 :
101 15370 : if (Analysis::Mappings::get ().lookup_glob_container (crate.get_node_id ())
102 15370 : == tl::nullopt)
103 4684 : Analysis::Mappings::get ().insert_glob_container (crate.get_node_id (),
104 : &crate);
105 15370 : }
106 :
107 : void
108 4479 : TopLevel::visit (AST::Module &module)
109 : {
110 4479 : DefaultResolver::visit (module);
111 :
112 4479 : if (Analysis::Mappings::get ().lookup_glob_container (module.get_node_id ())
113 4479 : == tl::nullopt)
114 1309 : Analysis::Mappings::get ().insert_glob_container (module.get_node_id (),
115 : &module);
116 4479 : }
117 :
118 : void
119 12928 : TopLevel::visit (AST::Trait &trait)
120 : {
121 12928 : insert_or_error_out (trait.get_identifier (), trait, Namespace::Types);
122 :
123 12928 : DefaultResolver::visit (trait);
124 12928 : }
125 :
126 : void
127 19046 : TopLevel::maybe_insert_big_self (AST::Impl &impl)
128 : {
129 38092 : insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()),
130 19046 : impl.get_type (), Namespace::Types);
131 19046 : }
132 :
133 : void
134 2597 : TopLevel::visit (AST::TraitItemType &trait_item)
135 : {
136 7791 : insert_or_error_out (trait_item.get_identifier ().as_string (), trait_item,
137 : Namespace::Types);
138 :
139 2597 : DefaultResolver::visit (trait_item);
140 2597 : }
141 :
142 : template <typename PROC_MACRO>
143 : static void
144 216 : insert_macros (std::vector<PROC_MACRO> ¯os, NameResolutionContext &ctx)
145 : {
146 216 : for (auto ¯o : macros)
147 : {
148 0 : auto res = ctx.macros.insert (macro.get_name (), macro.get_node_id ());
149 :
150 0 : if (!res && res.error ().existing != macro.get_node_id ())
151 : {
152 0 : rust_error_at (UNKNOWN_LOCATION, ErrorCode::E0428,
153 : "macro %qs defined multiple times",
154 0 : macro.get_name ().c_str ());
155 : }
156 : }
157 216 : }
158 :
159 : void
160 72 : TopLevel::visit_extern_crate (AST::ExternCrate &extern_crate, AST::Crate &crate,
161 : CrateNum num)
162 : {
163 72 : auto &mappings = Analysis::Mappings::get ();
164 :
165 72 : auto attribute_macros = mappings.lookup_attribute_proc_macros (num);
166 :
167 72 : auto bang_macros = mappings.lookup_bang_proc_macros (num);
168 :
169 72 : auto derive_macros = mappings.lookup_derive_proc_macros (num);
170 :
171 : // TODO: Find a way to keep this part clean without the double dispatch.
172 72 : if (derive_macros.has_value ())
173 : {
174 72 : insert_macros (derive_macros.value (), ctx);
175 72 : for (auto ¯o : derive_macros.value ())
176 0 : mappings.insert_derive_proc_macro_def (macro);
177 : }
178 72 : if (attribute_macros.has_value ())
179 : {
180 72 : insert_macros (attribute_macros.value (), ctx);
181 72 : for (auto ¯o : attribute_macros.value ())
182 0 : mappings.insert_attribute_proc_macro_def (macro);
183 : }
184 72 : if (bang_macros.has_value ())
185 : {
186 72 : insert_macros (bang_macros.value (), ctx);
187 72 : for (auto ¯o : bang_macros.value ())
188 0 : mappings.insert_bang_proc_macro_def (macro);
189 : }
190 :
191 72 : visit (crate);
192 72 : }
193 :
194 : static bool
195 4721 : is_macro_export (AST::MacroRulesDefinition &def)
196 : {
197 5202 : for (const auto &attr : def.get_outer_attrs ())
198 494 : if (attr.get_path ().as_string () == Values::Attributes::MACRO_EXPORT)
199 4721 : return true;
200 :
201 : return false;
202 : }
203 :
204 : void
205 4721 : TopLevel::visit (AST::MacroRulesDefinition ¯o)
206 : {
207 : // we do not insert macros in the current rib as that needs to be done in the
208 : // textual scope of the Early pass. we only insert them in the root of the
209 : // crate if they are marked with #[macro_export]. The execption to this is
210 : // macros 2.0, which get resolved and inserted like regular items.
211 :
212 4721 : if (is_macro_export (macro))
213 : {
214 39 : auto res = ctx.macros.insert_at_root (macro.get_rule_name (),
215 13 : macro.get_node_id ());
216 13 : if (!res && res.error ().existing != macro.get_node_id ())
217 : {
218 : // TODO: Factor this
219 0 : rich_location rich_loc (line_table, macro.get_locus ());
220 0 : rich_loc.add_range (node_locations[res.error ().existing]);
221 :
222 0 : rust_error_at (rich_loc, ErrorCode::E0428,
223 : "macro %qs defined multiple times",
224 0 : macro.get_rule_name ().as_string ().c_str ());
225 0 : }
226 13 : }
227 :
228 4721 : if (macro.get_kind () == AST::MacroRulesDefinition::MacroKind::DeclMacro)
229 153 : insert_or_error_out (macro.get_rule_name (), macro, Namespace::Macros);
230 :
231 4721 : auto &mappings = Analysis::Mappings::get ();
232 4721 : if (mappings.lookup_macro_def (macro.get_node_id ()))
233 : return;
234 :
235 976 : mappings.insert_macro_def (¯o);
236 : }
237 :
238 : void
239 63440 : TopLevel::visit (AST::Function &function)
240 : {
241 63440 : insert_or_error_out (function.get_function_name (), function,
242 : Namespace::Values);
243 :
244 63440 : Analysis::Mappings::get ().add_function_node (function.get_node_id ());
245 :
246 63440 : DefaultResolver::visit (function);
247 63440 : }
248 :
249 : void
250 183 : TopLevel::visit (AST::StaticItem &static_item)
251 : {
252 183 : insert_or_error_out (static_item.get_identifier (), static_item,
253 : Namespace::Values);
254 :
255 183 : DefaultResolver::visit (static_item);
256 183 : }
257 :
258 : void
259 3 : TopLevel::visit (AST::ExternalStaticItem &static_item)
260 : {
261 9 : insert_or_error_out (static_item.get_identifier ().as_string (), static_item,
262 : Namespace::Values);
263 :
264 3 : DefaultResolver::visit (static_item);
265 3 : }
266 :
267 : void
268 5107 : TopLevel::visit (AST::StructStruct &struct_item)
269 : {
270 5107 : DefaultResolver::visit (struct_item);
271 :
272 5107 : insert_or_error_out (struct_item.get_struct_name (), struct_item,
273 : Namespace::Types);
274 :
275 : // Do we need to insert the constructor in the value namespace as well?
276 :
277 : // Do we need to do anything if the struct is a unit struct?
278 5107 : if (struct_item.is_unit_struct ())
279 1977 : insert_or_error_out (struct_item.get_struct_name (), struct_item,
280 : Namespace::Values);
281 5107 : }
282 :
283 : void
284 28587 : TopLevel::visit (AST::TypeParam &type_param)
285 : {
286 28587 : insert_or_error_out (type_param.get_type_representation (), type_param,
287 : Namespace::Types);
288 :
289 28587 : DefaultResolver::visit (type_param);
290 28587 : }
291 :
292 : void
293 300 : TopLevel::visit (AST::ConstGenericParam &const_param)
294 : {
295 300 : insert_or_error_out (const_param.get_name (), const_param, Namespace::Values);
296 :
297 300 : DefaultResolver::visit (const_param);
298 300 : }
299 :
300 : void
301 3053 : TopLevel::visit (AST::TupleStruct &tuple_struct)
302 : {
303 3053 : insert_or_error_out (tuple_struct.get_struct_name (), tuple_struct,
304 : Namespace::Types);
305 :
306 3053 : insert_or_error_out (tuple_struct.get_struct_name (), tuple_struct,
307 : Namespace::Values);
308 :
309 3053 : DefaultResolver::visit (tuple_struct);
310 3053 : }
311 :
312 : void
313 1500 : TopLevel::visit (AST::EnumItem &variant)
314 : {
315 1500 : insert_enum_variant_or_error_out (variant.get_identifier (), variant, true);
316 :
317 1500 : DefaultResolver::visit (variant);
318 1500 : }
319 :
320 : void
321 1553 : TopLevel::visit (AST::EnumItemTuple &variant)
322 : {
323 1553 : insert_enum_variant_or_error_out (variant.get_identifier (), variant, true);
324 :
325 1553 : DefaultResolver::visit (variant);
326 1553 : }
327 :
328 : void
329 303 : TopLevel::visit (AST::EnumItemStruct &variant)
330 : {
331 303 : insert_enum_variant_or_error_out (variant.get_identifier (), variant, false);
332 :
333 303 : DefaultResolver::visit (variant);
334 303 : }
335 :
336 : void
337 968 : TopLevel::visit (AST::EnumItemDiscriminant &variant)
338 : {
339 968 : insert_enum_variant_or_error_out (variant.get_identifier (), variant, true);
340 :
341 968 : DefaultResolver::visit (variant);
342 968 : }
343 :
344 : void
345 1863 : TopLevel::visit (AST::Enum &enum_item)
346 : {
347 1863 : insert_or_error_out (enum_item.get_identifier (), enum_item,
348 : Namespace::Types);
349 :
350 1863 : DefaultResolver::visit (enum_item);
351 :
352 : // Since enums can be containers for imports, we need to insert them like we
353 : // do for modules
354 3726 : if (Analysis::Mappings::get ().lookup_glob_container (
355 1863 : enum_item.get_node_id ())
356 1863 : == tl::nullopt)
357 553 : Analysis::Mappings::get ().insert_glob_container (enum_item.get_node_id (),
358 : &enum_item);
359 1863 : }
360 :
361 : void
362 336 : TopLevel::visit (AST::Union &union_item)
363 : {
364 336 : insert_or_error_out (union_item.get_identifier (), union_item,
365 : Namespace::Types);
366 :
367 336 : DefaultResolver::visit (union_item);
368 336 : }
369 :
370 : void
371 1750 : TopLevel::visit (AST::ConstantItem &const_item)
372 : {
373 1750 : if (const_item.get_identifier ().as_string () != Values::Keywords::UNDERSCORE)
374 1741 : insert_or_error_out (const_item.get_identifier (), const_item,
375 : Namespace::Values);
376 :
377 1750 : DefaultResolver::visit (const_item);
378 1750 : }
379 :
380 : void
381 4472 : TopLevel::visit (AST::TypeAlias &type_item)
382 : {
383 4472 : insert_or_error_out (type_item.get_new_type_name (), type_item,
384 : Namespace::Types);
385 :
386 4472 : DefaultResolver::visit (type_item);
387 4472 : }
388 :
389 : static void flatten_rebind (
390 : const AST::UseTreeRebind &glob,
391 : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths);
392 :
393 : static void flatten_list (
394 : const AST::UseTreeList &glob, std::vector<AST::SimplePath> &paths,
395 : std::vector<AST::SimplePath> &glob_paths,
396 : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
397 : NameResolutionContext &ctx);
398 : static void flatten_glob (const AST::UseTreeGlob &glob,
399 : std::vector<AST::SimplePath> &glob_paths,
400 : NameResolutionContext &ctx);
401 :
402 : static void
403 4762 : flatten (
404 : const AST::UseTree *tree, std::vector<AST::SimplePath> &paths,
405 : std::vector<AST::SimplePath> &glob_paths,
406 : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
407 : NameResolutionContext &ctx)
408 : {
409 4762 : switch (tree->get_kind ())
410 : {
411 4125 : case AST::UseTree::Rebind:
412 4125 : {
413 4125 : auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
414 4125 : flatten_rebind (*rebind, rebind_paths);
415 4125 : break;
416 : }
417 605 : case AST::UseTree::List:
418 605 : {
419 605 : auto list = static_cast<const AST::UseTreeList *> (tree);
420 605 : flatten_list (*list, paths, glob_paths, rebind_paths, ctx);
421 605 : break;
422 : }
423 32 : case AST::UseTree::Glob:
424 32 : {
425 32 : auto glob = static_cast<const AST::UseTreeGlob *> (tree);
426 32 : flatten_glob (*glob, glob_paths, ctx);
427 32 : break;
428 : }
429 : break;
430 : }
431 4762 : }
432 :
433 : static void
434 4125 : flatten_rebind (
435 : const AST::UseTreeRebind &rebind,
436 : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths)
437 : {
438 4125 : rebind_paths.emplace_back (rebind.get_path (), rebind);
439 4125 : }
440 :
441 : /** Prefix a list of subpath
442 : * @param prefix A prefix for all subpath
443 : * @param subs List of subpath to prefix
444 : * @param size List where results should be stored
445 : */
446 : static void
447 4508 : prefix_subpaths (AST::SimplePath prefix, std::vector<AST::SimplePath> subs,
448 : std::vector<AST::SimplePath> &results)
449 : {
450 4508 : for (auto &sub : subs)
451 : {
452 0 : auto new_path = prefix;
453 0 : std::copy (sub.get_segments ().begin (), sub.get_segments ().end (),
454 : std::back_inserter (new_path.get_segments ()));
455 0 : results.emplace_back (new_path);
456 0 : }
457 4508 : }
458 :
459 : static void
460 2254 : prefix_rebinds (
461 : AST::SimplePath prefix,
462 : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> subs,
463 : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &results)
464 : {
465 4508 : for (auto &sub : subs)
466 : {
467 2254 : auto new_path = prefix;
468 2254 : std::copy (sub.first.get_segments ().begin (),
469 2254 : sub.first.get_segments ().end (),
470 : std::back_inserter (new_path.get_segments ()));
471 4508 : results.emplace_back (std::make_pair (new_path, sub.second));
472 2254 : }
473 2254 : }
474 :
475 : static void
476 605 : flatten_list (
477 : const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths,
478 : std::vector<AST::SimplePath> &glob_paths,
479 : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
480 : NameResolutionContext &ctx)
481 : {
482 605 : auto prefix = AST::SimplePath::create_empty ();
483 605 : if (list.has_path ())
484 601 : prefix = list.get_path ();
485 :
486 2859 : for (const auto &tree : list.get_trees ())
487 : {
488 2254 : auto sub_paths = std::vector<AST::SimplePath> ();
489 2254 : auto sub_globs = std::vector<AST::SimplePath> ();
490 2254 : auto sub_rebinds
491 2254 : = std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> ();
492 2254 : flatten (tree.get (), sub_paths, sub_globs, sub_rebinds, ctx);
493 :
494 2254 : prefix_subpaths (prefix, sub_paths, paths);
495 2254 : prefix_subpaths (prefix, sub_globs, glob_paths);
496 2254 : prefix_rebinds (prefix, sub_rebinds, rebind_paths);
497 2254 : }
498 605 : }
499 :
500 : static void
501 32 : flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths,
502 : NameResolutionContext &ctx)
503 : {
504 32 : if (glob.has_path ())
505 30 : paths.emplace_back (glob.get_path ());
506 : else
507 2 : paths.emplace_back (AST::SimplePath (
508 2 : {}, glob.get_glob_type () == AST::UseTreeGlob::PathType::GLOBAL,
509 4 : glob.get_locus ()));
510 32 : }
511 :
512 : static bool
513 32 : has_prelude_import (const std::vector<AST::Attribute> &attributes)
514 : {
515 34 : for (const auto &attr : attributes)
516 4 : if (attr.get_path ().as_string () == "prelude_import")
517 32 : return true;
518 :
519 : return false;
520 : }
521 :
522 : void
523 2508 : TopLevel::visit (AST::UseDeclaration &use)
524 : {
525 2508 : auto paths = std::vector<AST::SimplePath> ();
526 2508 : auto glob_path = std::vector<AST::SimplePath> ();
527 2508 : auto rebind_path
528 2508 : = std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> ();
529 :
530 2508 : auto &values_rib = ctx.values.peek ();
531 2508 : auto &types_rib = ctx.types.peek ();
532 2508 : auto ¯os_rib = ctx.macros.peek ();
533 :
534 : // FIXME: How do we handle `use foo::{self}` imports? Some beforehand cleanup?
535 : // How do we handle module imports in general? Should they get added to all
536 : // namespaces?
537 :
538 2508 : const auto &tree = use.get_tree ();
539 2508 : flatten (tree.get (), paths, glob_path, rebind_path, this->ctx);
540 :
541 2508 : auto imports = std::vector<ImportKind> ();
542 :
543 2508 : for (auto &&path : paths)
544 0 : imports.emplace_back (
545 0 : ImportKind::Simple (std::move (path), values_rib, types_rib, macros_rib));
546 :
547 2540 : for (auto &&glob : glob_path)
548 64 : imports.emplace_back (
549 32 : ImportKind::Glob (std::move (glob), values_rib, types_rib, macros_rib,
550 32 : has_prelude_import (use.get_outer_attrs ())));
551 :
552 6633 : for (auto &&rebind : rebind_path)
553 4125 : imports.emplace_back (
554 8250 : ImportKind::Rebind (std::move (rebind.first), std::move (rebind.second),
555 : values_rib, types_rib, macros_rib));
556 :
557 2508 : imports_to_resolve.insert ({use.get_node_id (), std::move (imports)});
558 2508 : }
559 :
560 : } // namespace Resolver2_0
561 : } // namespace Rust
|