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-early-name-resolver-2.0.h"
20 : #include "optional.h"
21 : #include "options.h"
22 : #include "rust-ast.h"
23 : #include "rust-diagnostics.h"
24 : #include "rust-hir-map.h"
25 : #include "rust-item.h"
26 : #include "rust-toplevel-name-resolver-2.0.h"
27 : #include "rust-attributes.h"
28 : #include "rust-finalize-imports-2.0.h"
29 : #include "rust-attribute-values.h"
30 :
31 : namespace Rust {
32 : namespace Resolver2_0 {
33 :
34 10431 : Early::Early (NameResolutionContext &ctx)
35 10431 : : DefaultResolver (ctx), toplevel (TopLevel (ctx)), dirty (false)
36 10431 : {}
37 :
38 : void
39 2805 : Early::insert_once (AST::MacroInvocation &invocation, NodeId resolved)
40 : {
41 : // TODO: Should we use `ctx.mark_resolved()`?
42 2805 : auto definition = ctx.mappings.lookup_macro_def (resolved);
43 :
44 2805 : if (!ctx.mappings.lookup_macro_invocation (invocation))
45 2805 : ctx.mappings.insert_macro_invocation (invocation, definition.value ());
46 2805 : }
47 :
48 : void
49 3785 : Early::insert_once (AST::MacroRulesDefinition &def)
50 : {
51 : // TODO: Should we use `ctx.mark_resolved()`?
52 3785 : if (!ctx.mappings.lookup_macro_def (def.get_node_id ()))
53 1 : ctx.mappings.insert_macro_def (&def);
54 3785 : }
55 :
56 : void
57 10431 : Early::go (AST::Crate &crate)
58 : {
59 : // First we go through TopLevel resolution to get all our declared items
60 10431 : toplevel.go (crate);
61 :
62 : // We start with resolving the list of imports that `TopLevel` has built for
63 : // us
64 :
65 10431 : dirty = toplevel.is_dirty ();
66 : // We now proceed with resolving macros, which can be nested in almost any
67 : // items
68 10431 : textual_scope.push ();
69 :
70 10431 : visit (crate);
71 :
72 10431 : textual_scope.pop ();
73 10431 : }
74 :
75 : bool
76 19 : Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
77 : {
78 19 : auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types);
79 19 : if (!resolved.has_value ())
80 : return false;
81 :
82 18 : auto result = Analysis::Mappings::get ().lookup_glob_container (
83 : resolved->get_node_id ());
84 :
85 18 : if (!result)
86 : return false;
87 :
88 : // here, we insert the module's NodeId into the import_mappings and will look
89 : // up the module proper in `FinalizeImports`
90 : // The namespace does not matter here since we are dealing with a glob
91 : // TODO: Ugly
92 36 : import_mappings.insert (use_dec_id,
93 18 : ImportPair (std::move (glob),
94 54 : ImportData::Glob (*resolved)));
95 :
96 18 : return true;
97 19 : }
98 :
99 : bool
100 0 : Early::resolve_simple_import (NodeId use_dec_id, TopLevel::ImportKind &&import)
101 : {
102 0 : auto definitions = resolve_path_in_all_ns (import.to_resolve);
103 :
104 : // if we've found at least one definition, then we're good
105 0 : if (definitions.empty ())
106 : return false;
107 :
108 0 : auto &imports = import_mappings.new_or_access (use_dec_id);
109 :
110 0 : imports.emplace_back (
111 0 : ImportPair (std::move (import),
112 0 : ImportData::Simple (std::move (definitions))));
113 :
114 0 : return true;
115 0 : }
116 :
117 : bool
118 3053 : Early::resolve_rebind_import (NodeId use_dec_id,
119 : TopLevel::ImportKind &&rebind_import)
120 : {
121 3053 : auto definitions = resolve_path_in_all_ns (rebind_import.to_resolve);
122 :
123 : // if we've found at least one definition, then we're good
124 3053 : if (definitions.empty ())
125 : return false;
126 6147 : for (const auto &def : definitions)
127 : {
128 3106 : if (def.first.is_ambiguous ())
129 : {
130 1 : rich_location rich_locus (line_table,
131 1 : rebind_import.to_resolve.get_locus ());
132 1 : rust_error_at (rich_locus, ErrorCode::E0659, "%qs is ambiguous",
133 1 : rebind_import.to_resolve.as_string ().c_str ());
134 1 : return true;
135 1 : }
136 : }
137 :
138 3041 : auto &imports = import_mappings.new_or_access (use_dec_id);
139 :
140 3041 : imports.emplace_back (
141 3041 : ImportPair (std::move (rebind_import),
142 6082 : ImportData::Rebind (std::move (definitions))));
143 :
144 3041 : return true;
145 3053 : }
146 :
147 : void
148 1845 : Early::build_import_mapping (
149 : std::pair<NodeId, std::vector<TopLevel::ImportKind>> &&use_import)
150 : {
151 1845 : auto found = false;
152 1845 : auto use_dec_id = use_import.first;
153 :
154 4917 : for (auto &&import : use_import.second)
155 : {
156 : // We create a copy of the path in case of errors, since the `import` will
157 : // be moved into the newly created import mappings
158 3072 : auto path = import.to_resolve;
159 :
160 : // used to skip the "unresolved import" error
161 : // if we output other errors during resolution
162 3072 : size_t old_error_count = macro_resolve_errors.size ();
163 :
164 3072 : switch (import.kind)
165 : {
166 19 : case TopLevel::ImportKind::Kind::Glob:
167 19 : found = resolve_glob_import (use_dec_id, std::move (import));
168 19 : break;
169 0 : case TopLevel::ImportKind::Kind::Simple:
170 0 : found = resolve_simple_import (use_dec_id, std::move (import));
171 0 : break;
172 3053 : case TopLevel::ImportKind::Kind::Rebind:
173 3053 : found = resolve_rebind_import (use_dec_id, std::move (import));
174 3053 : break;
175 : }
176 :
177 3072 : if (!found && old_error_count == macro_resolve_errors.size ())
178 20 : collect_error (Error (path.get_final_segment ().get_locus (),
179 : ErrorCode::E0433, "unresolved import %qs",
180 20 : path.as_string ().c_str ()));
181 3072 : }
182 1845 : }
183 :
184 : void
185 66471 : Early::TextualScope::push ()
186 : {
187 : // push a new empty scope
188 66471 : scopes.emplace_back ();
189 66471 : }
190 :
191 : void
192 66471 : Early::TextualScope::pop ()
193 : {
194 66471 : rust_assert (!scopes.empty ());
195 :
196 66471 : scopes.pop_back ();
197 66471 : }
198 :
199 : void
200 3785 : Early::TextualScope::insert (std::string name, NodeId id)
201 : {
202 3785 : rust_assert (!scopes.empty ());
203 :
204 : // we can ignore the return value as we always want the latest defined macro
205 : // to shadow a previous one - so if two macros have the same name and get
206 : // inserted with the same key, it's not a bug
207 7570 : scopes.back ().insert ({name, id});
208 3785 : }
209 :
210 : tl::optional<NodeId>
211 2835 : Early::TextualScope::get (const std::string &name)
212 : {
213 5575 : for (auto iterator = scopes.rbegin (); iterator != scopes.rend (); iterator++)
214 : {
215 5532 : auto scope = *iterator;
216 5532 : auto found = scope.find (name);
217 5532 : if (found != scope.end ())
218 2792 : return found->second;
219 5532 : }
220 :
221 43 : return tl::nullopt;
222 : }
223 :
224 : void
225 3785 : Early::visit (AST::MacroRulesDefinition &def)
226 : {
227 3785 : DefaultResolver::visit (def);
228 :
229 7570 : textual_scope.insert (def.get_rule_name ().as_string (), def.get_node_id ());
230 3785 : insert_once (def);
231 3785 : }
232 :
233 : void
234 52810 : Early::visit (AST::BlockExpr &block)
235 : {
236 52810 : textual_scope.push ();
237 :
238 52810 : DefaultResolver::visit (block);
239 :
240 52810 : textual_scope.pop ();
241 52810 : }
242 :
243 : void
244 3261 : Early::visit (AST::Module &module)
245 : {
246 3261 : bool is_macro_use = false;
247 :
248 3504 : for (const auto &attr : module.get_outer_attrs ())
249 : {
250 274 : if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE)
251 : {
252 : is_macro_use = true;
253 : break;
254 : }
255 : }
256 :
257 3261 : if (!is_macro_use)
258 3230 : textual_scope.push ();
259 :
260 3261 : DefaultResolver::visit (module);
261 :
262 3261 : if (!is_macro_use)
263 3230 : textual_scope.pop ();
264 3261 : }
265 :
266 : void
267 2847 : Early::visit (AST::MacroInvocation &invoc)
268 : {
269 2847 : auto &path = invoc.get_invoc_data ().get_path ();
270 :
271 : // We special case the `offset_of!()` macro if the flag is here, otherwise
272 : // we accept whatever `offset_of!()` definition we resolved to.
273 2847 : auto resolve_offset_of
274 2847 : = flag_assume_builtin_offset_of && (path.as_string () == "offset_of");
275 :
276 2847 : if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
277 89 : for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
278 46 : pending_invoc->accept_vis (*this);
279 :
280 : // When a macro is invoked by an unqualified identifier (not part of a
281 : // multi-part path), it is first looked up in textual scoping. If this does
282 : // not yield any results, then it is looked up in path-based scoping. If the
283 : // macro's name is qualified with a path, then it is only looked up in
284 : // path-based scoping.
285 :
286 : // https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope
287 :
288 2847 : tl::optional<Rib::Definition> definition = tl::nullopt;
289 2847 : if (path.get_segments ().size () == 1)
290 2835 : definition
291 2835 : = textual_scope.get (path.get_final_segment ().as_string ())
292 8419 : .map ([] (NodeId id) { return Rib::Definition::NonShadowable (id); });
293 :
294 : // we won't have changed `definition` from `nullopt` if there are more
295 : // than one segments in our path
296 2847 : if (!definition.has_value ())
297 68 : definition = ctx.resolve_path (path, Namespace::Macros);
298 :
299 : // if the definition still does not have a value, then it's an error - unless
300 : // we should automatically resolve offset_of!() calls
301 2847 : if (!definition.has_value ())
302 : {
303 42 : if (!resolve_offset_of)
304 24 : collect_error (Error (invoc.get_locus (), ErrorCode::E0433,
305 : "could not resolve macro invocation %qs",
306 48 : path.as_string ().c_str ()));
307 42 : return;
308 : }
309 :
310 2805 : insert_once (invoc, definition->get_node_id ());
311 :
312 : // now do we need to keep mappings or something? or insert "uses" into our
313 : // ForeverStack? can we do that? are mappings simpler?
314 2805 : auto &mappings = Analysis::Mappings::get ();
315 2805 : auto rules_def = mappings.lookup_macro_def (definition->get_node_id ());
316 :
317 : // Macro definition not found, maybe it is not expanded yet.
318 2805 : if (!rules_def)
319 : return;
320 :
321 2805 : if (mappings.lookup_macro_invocation (invoc))
322 : return;
323 :
324 0 : mappings.insert_macro_invocation (invoc, rules_def.value ());
325 2847 : }
326 :
327 : void
328 166 : Early::visit_derive_attribute (AST::Attribute &attr,
329 : Analysis::Mappings &mappings)
330 : {
331 166 : auto traits = attr.get_traits_to_derive ();
332 466 : for (auto &trait : traits)
333 : {
334 300 : auto definition = ctx.resolve_path (trait.get (), Namespace::Macros);
335 300 : if (!definition.has_value ())
336 : {
337 : // FIXME: Change to proper error message
338 600 : collect_error (Error (trait.get ().get_locus (),
339 : "could not resolve trait %qs",
340 300 : trait.get ().as_string ().c_str ()));
341 300 : continue;
342 : }
343 :
344 0 : auto pm_def
345 0 : = mappings.lookup_derive_proc_macro_def (definition->get_node_id ());
346 :
347 0 : if (pm_def.has_value ())
348 0 : mappings.insert_derive_proc_macro_invocation (trait, pm_def.value ());
349 300 : }
350 166 : }
351 :
352 : void
353 1 : Early::visit_non_builtin_attribute (AST::Attribute &attr,
354 : Analysis::Mappings &mappings,
355 : std::string &name)
356 : {
357 1 : auto definition = ctx.resolve_path (attr.get_path (), Namespace::Macros);
358 1 : if (!definition.has_value ())
359 : {
360 : // FIXME: Change to proper error message
361 0 : collect_error (Error (attr.get_locus (),
362 : "could not resolve attribute macro invocation %qs",
363 0 : name.c_str ()));
364 0 : return;
365 : }
366 1 : auto pm_def
367 1 : = mappings.lookup_attribute_proc_macro_def (definition->get_node_id ());
368 :
369 1 : if (!pm_def.has_value ())
370 : return;
371 :
372 0 : mappings.insert_attribute_proc_macro_invocation (attr.get_path (),
373 0 : pm_def.value ());
374 1 : }
375 :
376 : void
377 69406 : Early::visit (AST::Attribute &attr)
378 : {
379 69406 : auto &mappings = Analysis::Mappings::get ();
380 :
381 69406 : auto name = attr.get_path ().get_segments ().at (0).get_segment_name ();
382 138646 : auto is_not_builtin = [&name] (AST::Attribute &attr) {
383 69240 : return Analysis::BuiltinAttributeMappings::get ()
384 69240 : ->lookup_builtin (name)
385 69240 : .is_error ();
386 69406 : };
387 :
388 69406 : if (attr.is_derive ())
389 : {
390 166 : visit_derive_attribute (attr, mappings);
391 : }
392 69240 : else if (is_not_builtin (attr)) // Do not resolve builtins
393 : {
394 1 : visit_non_builtin_attribute (attr, mappings, name);
395 : }
396 69406 : }
397 :
398 : void
399 0 : Early::finalize_simple_import (const Early::ImportPair &mapping)
400 : {
401 : // FIXME: We probably need to store namespace information
402 :
403 0 : auto locus = mapping.import_kind.to_resolve.get_locus ();
404 0 : auto data = mapping.data;
405 0 : auto identifier
406 0 : = mapping.import_kind.to_resolve.get_final_segment ().get_segment_name ();
407 :
408 0 : for (auto &&definition : data.definitions ())
409 0 : toplevel
410 0 : .insert_or_error_out (
411 0 : identifier, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */);
412 0 : }
413 :
414 : void
415 18 : Early::finalize_glob_import (NameResolutionContext &ctx,
416 : const Early::ImportPair &mapping)
417 : {
418 36 : auto container = Analysis::Mappings::get ().lookup_glob_container (
419 36 : mapping.data.container ().get_node_id ());
420 :
421 18 : rust_assert (container);
422 :
423 18 : if (mapping.import_kind.is_prelude)
424 : {
425 1 : rust_assert (container.value ()->get_glob_container_kind ()
426 : == AST::GlobContainer::Kind::Module);
427 :
428 1 : ctx.prelude = mapping.data.container ().get_node_id ();
429 : }
430 :
431 18 : GlobbingVisitor (ctx).go (container.value ());
432 18 : }
433 :
434 : void
435 3041 : Early::finalize_rebind_import (const Early::ImportPair &mapping)
436 : {
437 : // We can fetch the value here as `resolve_rebind` will only be called on
438 : // imports of the right kind
439 3041 : auto &path = mapping.import_kind.to_resolve;
440 3041 : auto &rebind = mapping.import_kind.rebind.value ();
441 3041 : auto data = mapping.data;
442 :
443 3041 : location_t locus = UNKNOWN_LOCATION;
444 3041 : std::string declared_name;
445 :
446 : // FIXME: This needs to be done in `FinalizeImports`
447 3041 : switch (rebind.get_new_bind_type ())
448 : {
449 6 : case AST::UseTreeRebind::NewBindType::IDENTIFIER:
450 6 : declared_name = rebind.get_identifier ().as_string ();
451 6 : locus = rebind.get_identifier ().get_locus ();
452 6 : break;
453 3031 : case AST::UseTreeRebind::NewBindType::NONE:
454 3031 : {
455 3031 : const auto &segments = path.get_segments ();
456 : // We don't want to insert `self` with `use module::self`
457 3031 : if (path.get_final_segment ().is_lower_self_seg ())
458 : {
459 : // Erroneous `self` or `{self}` use declaration
460 209 : if (segments.size () == 1)
461 : break;
462 204 : declared_name = segments[segments.size () - 2].as_string ();
463 : }
464 : else
465 2822 : declared_name = path.get_final_segment ().as_string ();
466 3026 : locus = path.get_final_segment ().get_locus ();
467 3026 : break;
468 : }
469 4 : case AST::UseTreeRebind::NewBindType::WILDCARD:
470 : // We don't want to insert it into the trie
471 4 : return;
472 : }
473 :
474 6138 : for (auto &&definition : data.definitions ())
475 3101 : toplevel.insert_or_error_out (
476 15441 : declared_name, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */);
477 6082 : }
478 :
479 : void
480 1845 : Early::visit (AST::UseDeclaration &decl)
481 : {
482 : // We do not want to visit the use trees, we're only looking for top level
483 : // rebind. eg. `use something;` or `use something::other;`
484 1845 : if (decl.get_tree ()->get_kind () == AST::UseTree::Kind::Rebind)
485 : {
486 1371 : auto &rebind = static_cast<AST::UseTreeRebind &> (*decl.get_tree ());
487 1371 : if (rebind.get_path ().get_final_segment ().is_lower_self_seg ())
488 : {
489 2 : collect_error (
490 1 : Error (decl.get_locus (), ErrorCode::E0429,
491 1 : "%<self%> imports are only allowed within a { } list"));
492 : }
493 : }
494 :
495 1845 : auto &imports = toplevel.get_imports_to_resolve ();
496 1845 : auto current_import = imports.find (decl.get_node_id ());
497 1845 : if (current_import != imports.end ())
498 : {
499 1845 : build_import_mapping (*current_import);
500 : }
501 :
502 : // Once this is done, we finalize their resolution
503 4904 : for (const auto &mapping : import_mappings.get (decl.get_node_id ()))
504 3059 : switch (mapping.import_kind.kind)
505 : {
506 18 : case TopLevel::ImportKind::Kind::Glob:
507 18 : finalize_glob_import (ctx, mapping);
508 18 : break;
509 0 : case TopLevel::ImportKind::Kind::Simple:
510 0 : finalize_simple_import (mapping);
511 0 : break;
512 3041 : case TopLevel::ImportKind::Kind::Rebind:
513 3041 : finalize_rebind_import (mapping);
514 3041 : break;
515 : }
516 :
517 1845 : DefaultResolver::visit (decl);
518 1845 : }
519 :
520 : void
521 455 : Early::visit (AST::UseTreeList &use_list)
522 : {
523 455 : if (!use_list.has_path ())
524 : {
525 10 : for (auto &&tree : use_list.get_trees ())
526 : {
527 6 : if (tree->get_kind () == AST::UseTree::Kind::Rebind)
528 : {
529 6 : auto &rebind = static_cast<AST::UseTreeRebind &> (*tree);
530 6 : auto path_size = rebind.get_path ().get_segments ().size ();
531 6 : if (path_size == 1
532 6 : && rebind.get_path ()
533 6 : .get_final_segment ()
534 6 : .is_lower_self_seg ())
535 : {
536 4 : collect_error (Error (rebind.get_locus (), ErrorCode::E0431,
537 : "%<self%> import can only appear in an "
538 4 : "import list with a non-empty prefix"));
539 : }
540 : }
541 : }
542 : }
543 455 : DefaultResolver::visit (use_list);
544 455 : }
545 :
546 : } // namespace Resolver2_0
547 : } // namespace Rust
|