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