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