Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 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 : : void
30 : 3 : GlobbingVisitor::go (AST::Module *module)
31 : : {
32 : 9 : for (auto &i : module->get_items ())
33 : 6 : visit (i);
34 : 3 : }
35 : :
36 : : void
37 : 1 : GlobbingVisitor::visit (AST::Module &module)
38 : : {
39 : 1 : if (module.get_visibility ().is_public ())
40 : 1 : ctx.insert_shadowable (module.get_name (), module.get_node_id (),
41 : : Namespace::Types);
42 : 1 : }
43 : :
44 : : void
45 : 0 : GlobbingVisitor::visit (AST::MacroRulesDefinition ¯o)
46 : : {
47 : 0 : if (macro.get_visibility ().is_public ())
48 : 0 : ctx.insert_shadowable (macro.get_rule_name (), macro.get_node_id (),
49 : : Namespace::Macros);
50 : 0 : }
51 : :
52 : : void
53 : 5 : GlobbingVisitor::visit (AST::Function &function)
54 : : {
55 : 5 : if (function.get_visibility ().is_public ())
56 : 5 : ctx.insert_shadowable (function.get_function_name (),
57 : 5 : function.get_node_id (), Namespace::Values);
58 : 5 : }
59 : :
60 : : void
61 : 0 : GlobbingVisitor::visit (AST::StaticItem &static_item)
62 : : {
63 : 0 : if (static_item.get_visibility ().is_public ())
64 : 0 : ctx.insert_shadowable (static_item.get_identifier (),
65 : : static_item.get_node_id (), Namespace::Values);
66 : 0 : }
67 : :
68 : : void
69 : 0 : GlobbingVisitor::visit (AST::StructStruct &struct_item)
70 : : {
71 : 0 : if (struct_item.get_visibility ().is_public ())
72 : : {
73 : 0 : ctx.insert_shadowable (struct_item.get_identifier (),
74 : : struct_item.get_node_id (), Namespace::Types);
75 : 0 : if (struct_item.is_unit_struct ())
76 : 0 : ctx.insert_shadowable (struct_item.get_identifier (),
77 : : struct_item.get_node_id (), Namespace::Values);
78 : : }
79 : 0 : }
80 : :
81 : : void
82 : 0 : GlobbingVisitor::visit (AST::TupleStruct &tuple_struct)
83 : : {
84 : 0 : if (tuple_struct.get_visibility ().is_public ())
85 : : {
86 : 0 : ctx.insert_shadowable (tuple_struct.get_identifier (),
87 : : tuple_struct.get_node_id (), Namespace::Types);
88 : :
89 : 0 : ctx.insert_shadowable (tuple_struct.get_identifier (),
90 : : tuple_struct.get_node_id (), Namespace::Values);
91 : : }
92 : 0 : }
93 : :
94 : : void
95 : 0 : GlobbingVisitor::visit (AST::Enum &enum_item)
96 : : {
97 : 0 : if (enum_item.get_visibility ().is_public ())
98 : 0 : ctx.insert_shadowable (enum_item.get_identifier (),
99 : : enum_item.get_node_id (), Namespace::Types);
100 : 0 : }
101 : :
102 : : void
103 : 0 : GlobbingVisitor::visit (AST::Union &union_item)
104 : : {
105 : 0 : if (union_item.get_visibility ().is_public ())
106 : 0 : ctx.insert_shadowable (union_item.get_identifier (),
107 : : union_item.get_node_id (), Namespace::Values);
108 : 0 : }
109 : :
110 : : void
111 : 0 : GlobbingVisitor::visit (AST::ConstantItem &const_item)
112 : : {
113 : 0 : if (const_item.get_visibility ().is_public ())
114 : 0 : ctx.insert_shadowable (const_item.get_identifier (),
115 : : const_item.get_node_id (), Namespace::Values);
116 : 0 : }
117 : :
118 : : void
119 : 0 : GlobbingVisitor::visit (AST::ExternCrate &crate)
120 : 0 : {}
121 : :
122 : : void
123 : 0 : GlobbingVisitor::visit (AST::UseDeclaration &use)
124 : : {
125 : : // Handle cycles ?
126 : 0 : }
127 : :
128 : 35 : TopLevel::TopLevel (NameResolutionContext &resolver)
129 : 35 : : DefaultResolver (resolver)
130 : 35 : {}
131 : :
132 : : template <typename T>
133 : : void
134 : 152 : TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
135 : : Namespace ns)
136 : : {
137 : 152 : insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns);
138 : 152 : }
139 : :
140 : : void
141 : 177 : TopLevel::insert_or_error_out (const Identifier &identifier,
142 : : const location_t &locus, const NodeId &node_id,
143 : : Namespace ns)
144 : : {
145 : : // keep track of each node's location to provide useful errors
146 : 177 : node_locations.emplace (node_id, locus);
147 : :
148 : 177 : auto result = ctx.insert (identifier, node_id, ns);
149 : :
150 : 177 : if (!result && result.error ().existing != node_id)
151 : : {
152 : 3 : rich_location rich_loc (line_table, locus);
153 : 3 : rich_loc.add_range (node_locations[result.error ().existing]);
154 : :
155 : 3 : rust_error_at (rich_loc, ErrorCode::E0428, "%qs defined multiple times",
156 : 3 : identifier.as_string ().c_str ());
157 : 3 : }
158 : 177 : }
159 : :
160 : : void
161 : 35 : TopLevel::go (AST::Crate &crate)
162 : : {
163 : : // we do not include builtin types in the top-level definition collector, as
164 : : // they are not used until `Late`. furthermore, we run this visitor multiple
165 : : // times in a row in a fixed-point fashion, so it would make the code
166 : : // responsible for this ugly and perfom a lot of error checking.
167 : :
168 : 139 : for (auto &item : crate.items)
169 : 104 : item->accept_vis (*this);
170 : 35 : }
171 : :
172 : : void
173 : 45 : TopLevel::visit (AST::Module &module)
174 : : {
175 : 45 : insert_or_error_out (module.get_name (), module, Namespace::Types);
176 : :
177 : 90 : auto sub_visitor = [this, &module] () {
178 : 106 : for (auto &item : module.get_items ())
179 : 61 : item->accept_vis (*this);
180 : 90 : };
181 : :
182 : 180 : ctx.scoped (Rib::Kind::Module, module.get_node_id (), sub_visitor,
183 : 45 : module.get_name ());
184 : :
185 : 45 : if (Analysis::Mappings::get ()->lookup_ast_module (module.get_node_id ())
186 : 45 : == tl::nullopt)
187 : 31 : Analysis::Mappings::get ()->insert_ast_module (&module);
188 : 45 : }
189 : :
190 : : void
191 : 0 : TopLevel::visit (AST::Trait &trait)
192 : : {
193 : : // FIXME: This Self injection is dodgy. It even lead to issues with metadata
194 : : // export in the past (#2349). We cannot tell appart injected parameters from
195 : : // regular ones. Dumping generic parameters highlights this Self in metadata,
196 : : // during debug or proc macro collection. This is clearly a hack.
197 : : //
198 : : // For now I'll keep it here in the new name resolver even if it should
199 : : // probably not be there. We need to find another way to solve this.
200 : : // Maybe an additional attribute to Trait ?
201 : : //
202 : : // From old resolver:
203 : : //// we need to inject an implicit self TypeParam here
204 : : //// FIXME: which location should be used for Rust::Identifier `Self`?
205 : 0 : AST::TypeParam *implicit_self
206 : 0 : = new AST::TypeParam ({"Self"}, trait.get_locus ());
207 : 0 : trait.insert_implict_self (
208 : 0 : std::unique_ptr<AST::GenericParam> (implicit_self));
209 : :
210 : 0 : DefaultResolver::visit (trait);
211 : 0 : }
212 : :
213 : : template <typename PROC_MACRO>
214 : : static void
215 : 0 : insert_macros (std::vector<PROC_MACRO> ¯os, NameResolutionContext &ctx)
216 : : {
217 : 0 : for (auto ¯o : macros)
218 : : {
219 : 0 : auto res = ctx.macros.insert (macro.get_name (), macro.get_node_id ());
220 : :
221 : 0 : if (!res && res.error ().existing != macro.get_node_id ())
222 : : {
223 : 0 : rust_error_at (UNKNOWN_LOCATION, ErrorCode::E0428,
224 : : "macro %qs defined multiple times",
225 : 0 : macro.get_name ().c_str ());
226 : : }
227 : : }
228 : 0 : }
229 : :
230 : : void
231 : 0 : TopLevel::visit (AST::ExternCrate &crate)
232 : : {
233 : 0 : CrateNum num;
234 : 0 : rust_assert (Analysis::Mappings::get ()->lookup_crate_name (
235 : : crate.get_referenced_crate (), num));
236 : :
237 : 0 : auto attribute_macros
238 : 0 : = Analysis::Mappings::get ()->lookup_attribute_proc_macros (num);
239 : :
240 : 0 : auto bang_macros = Analysis::Mappings::get ()->lookup_bang_proc_macros (num);
241 : :
242 : 0 : auto derive_macros
243 : 0 : = Analysis::Mappings::get ()->lookup_derive_proc_macros (num);
244 : :
245 : 0 : auto sub_visitor = [&] () {
246 : : // TODO: Find a way to keep this part clean without the double dispatch.
247 : 0 : if (derive_macros.has_value ())
248 : : {
249 : 0 : insert_macros (derive_macros.value (), ctx);
250 : 0 : for (auto ¯o : derive_macros.value ())
251 : 0 : Analysis::Mappings::get ()->insert_derive_proc_macro_def (macro);
252 : : }
253 : 0 : if (attribute_macros.has_value ())
254 : : {
255 : 0 : insert_macros (attribute_macros.value (), ctx);
256 : 0 : for (auto ¯o : attribute_macros.value ())
257 : 0 : Analysis::Mappings::get ()->insert_attribute_proc_macro_def (macro);
258 : : }
259 : 0 : if (bang_macros.has_value ())
260 : : {
261 : 0 : insert_macros (bang_macros.value (), ctx);
262 : 0 : for (auto ¯o : bang_macros.value ())
263 : 0 : Analysis::Mappings::get ()->insert_bang_proc_macro_def (macro);
264 : : }
265 : 0 : };
266 : :
267 : 0 : if (crate.has_as_clause ())
268 : 0 : ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor,
269 : 0 : crate.get_as_clause ());
270 : : else
271 : 0 : ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor,
272 : 0 : crate.get_referenced_crate ());
273 : 0 : }
274 : :
275 : : static bool
276 : 23 : is_macro_export (AST::MacroRulesDefinition &def)
277 : : {
278 : 23 : for (const auto &attr : def.get_outer_attrs ())
279 : 4 : if (attr.get_path ().as_string () == Values::Attributes::MACRO_EXPORT)
280 : 23 : return true;
281 : :
282 : : return false;
283 : : }
284 : :
285 : : void
286 : 23 : TopLevel::visit (AST::MacroRulesDefinition ¯o)
287 : : {
288 : : // we do not insert macros in the current rib as that needs to be done in the
289 : : // textual scope of the Early pass. we only insert them in the root of the
290 : : // crate if they are marked with #[macro_export]. The execption to this is
291 : : // macros 2.0, which get resolved and inserted like regular items.
292 : :
293 : 23 : if (is_macro_export (macro))
294 : : {
295 : 12 : auto res = ctx.macros.insert_at_root (macro.get_rule_name (),
296 : 4 : macro.get_node_id ());
297 : 4 : if (!res && res.error ().existing != macro.get_node_id ())
298 : : {
299 : : // TODO: Factor this
300 : 0 : rich_location rich_loc (line_table, macro.get_locus ());
301 : 0 : rich_loc.add_range (node_locations[res.error ().existing]);
302 : :
303 : 0 : rust_error_at (rich_loc, ErrorCode::E0428,
304 : : "macro %qs defined multiple times",
305 : 0 : macro.get_rule_name ().as_string ().c_str ());
306 : 0 : }
307 : 4 : }
308 : :
309 : 23 : if (macro.get_kind () == AST::MacroRulesDefinition::MacroKind::DeclMacro)
310 : 11 : insert_or_error_out (macro.get_rule_name (), macro, Namespace::Macros);
311 : :
312 : 23 : auto mappings = Analysis::Mappings::get ();
313 : 23 : AST::MacroRulesDefinition *tmp = nullptr;
314 : 23 : if (mappings->lookup_macro_def (macro.get_node_id (), &tmp))
315 : 10 : return;
316 : :
317 : 13 : mappings->insert_macro_def (¯o);
318 : : }
319 : :
320 : : void
321 : 69 : TopLevel::visit (AST::Function &function)
322 : : {
323 : 69 : insert_or_error_out (function.get_function_name (), function,
324 : : Namespace::Values);
325 : :
326 : 69 : DefaultResolver::visit (function);
327 : 69 : }
328 : :
329 : : void
330 : 71 : TopLevel::visit (AST::BlockExpr &expr)
331 : : {
332 : : // extracting the lambda from the `scoped` call otherwise the code looks like
333 : : // a hot turd thanks to our .clang-format
334 : :
335 : 142 : auto sub_vis = [this, &expr] () {
336 : 153 : for (auto &stmt : expr.get_statements ())
337 : 82 : stmt->accept_vis (*this);
338 : :
339 : 71 : if (expr.has_tail_expr ())
340 : 14 : expr.get_tail_expr ().accept_vis (*this);
341 : 142 : };
342 : :
343 : 142 : ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), sub_vis);
344 : 71 : }
345 : :
346 : : void
347 : 0 : TopLevel::visit (AST::StaticItem &static_item)
348 : : {
349 : 0 : auto sub_vis
350 : 0 : = [this, &static_item] () { static_item.get_expr ().accept_vis (*this); };
351 : :
352 : 0 : ctx.scoped (Rib::Kind::Item, static_item.get_node_id (), sub_vis);
353 : 0 : }
354 : :
355 : : void
356 : 12 : TopLevel::visit (AST::StructStruct &struct_item)
357 : : {
358 : 12 : insert_or_error_out (struct_item.get_struct_name (), struct_item,
359 : : Namespace::Types);
360 : :
361 : : // Do we need to insert the constructor in the value namespace as well?
362 : :
363 : : // Do we need to do anything if the struct is a unit struct?
364 : 12 : if (struct_item.is_unit_struct ())
365 : 5 : insert_or_error_out (struct_item.get_struct_name (), struct_item,
366 : : Namespace::Values);
367 : 12 : }
368 : :
369 : : void
370 : 1 : TopLevel::visit (AST::TupleStruct &tuple_struct)
371 : : {
372 : 1 : insert_or_error_out (tuple_struct.get_struct_name (), tuple_struct,
373 : : Namespace::Types);
374 : :
375 : 1 : insert_or_error_out (tuple_struct.get_struct_name (), tuple_struct,
376 : : Namespace::Values);
377 : 1 : }
378 : :
379 : : void
380 : 0 : TopLevel::visit (AST::EnumItem &variant)
381 : : {
382 : 0 : insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
383 : 0 : }
384 : :
385 : : void
386 : 0 : TopLevel::visit (AST::EnumItemTuple &variant)
387 : : {
388 : 0 : insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
389 : 0 : }
390 : :
391 : : void
392 : 0 : TopLevel::visit (AST::EnumItemStruct &variant)
393 : : {
394 : 0 : insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
395 : 0 : }
396 : :
397 : : void
398 : 0 : TopLevel::visit (AST::EnumItemDiscriminant &variant)
399 : : {
400 : 0 : insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
401 : 0 : }
402 : :
403 : : void
404 : 0 : TopLevel::visit (AST::Enum &enum_item)
405 : : {
406 : 0 : insert_or_error_out (enum_item.get_identifier (), enum_item,
407 : : Namespace::Types);
408 : :
409 : 0 : auto field_vis = [this, &enum_item] () {
410 : 0 : for (auto &variant : enum_item.get_variants ())
411 : 0 : variant->accept_vis (*this);
412 : 0 : };
413 : :
414 : 0 : ctx.scoped (Rib::Kind::Item /* FIXME: Is that correct? */,
415 : 0 : enum_item.get_node_id (), field_vis, enum_item.get_identifier ());
416 : 0 : }
417 : :
418 : : void
419 : 0 : TopLevel::visit (AST::Union &union_item)
420 : : {
421 : 0 : insert_or_error_out (union_item.get_identifier (), union_item,
422 : : Namespace::Types);
423 : 0 : }
424 : :
425 : : void
426 : 8 : TopLevel::visit (AST::ConstantItem &const_item)
427 : : {
428 : 8 : insert_or_error_out (const_item.get_identifier (), const_item,
429 : : Namespace::Values);
430 : :
431 : 8 : auto expr_vis
432 : 8 : = [this, &const_item] () { const_item.get_expr ().accept_vis (*this); };
433 : :
434 : 16 : ctx.scoped (Rib::Kind::ConstantItem, const_item.get_node_id (), expr_vis);
435 : 8 : }
436 : :
437 : : bool
438 : 3 : TopLevel::handle_use_glob (AST::SimplePath &glob)
439 : : {
440 : 3 : auto resolved = ctx.types.resolve_path (glob.get_segments ());
441 : 3 : if (!resolved.has_value ())
442 : : return false;
443 : :
444 : 3 : auto result
445 : 3 : = Analysis::Mappings::get ()->lookup_ast_module (resolved->get_node_id ());
446 : :
447 : 3 : if (!result.has_value ())
448 : : return false;
449 : :
450 : 3 : GlobbingVisitor gvisitor (ctx);
451 : 3 : gvisitor.go (result.value ());
452 : :
453 : 3 : return true;
454 : 3 : }
455 : :
456 : : bool
457 : 0 : TopLevel::handle_use_dec (AST::SimplePath &path)
458 : : {
459 : 0 : auto locus = path.get_final_segment ().get_locus ();
460 : 0 : auto declared_name = path.get_final_segment ().as_string ();
461 : :
462 : : // in what namespace do we perform path resolution? All of them? see which one
463 : : // matches? Error out on ambiguities?
464 : : // so, apparently, for each one that matches, add it to the proper namespace
465 : : // :(
466 : :
467 : 0 : auto found = false;
468 : :
469 : 0 : auto resolve_and_insert
470 : 0 : = [this, &found, &declared_name, locus] (Namespace ns,
471 : : const AST::SimplePath &path) {
472 : 0 : tl::optional<Rib::Definition> resolved = tl::nullopt;
473 : :
474 : : // FIXME: resolve_path needs to return an `expected<NodeId, Error>` so
475 : : // that we can improve it with hints or location or w/ever. and maybe
476 : : // only emit it the first time.
477 : 0 : switch (ns)
478 : : {
479 : 0 : case Namespace::Values:
480 : 0 : resolved = ctx.values.resolve_path (path.get_segments ());
481 : 0 : break;
482 : 0 : case Namespace::Types:
483 : 0 : resolved = ctx.types.resolve_path (path.get_segments ());
484 : 0 : break;
485 : 0 : case Namespace::Macros:
486 : 0 : resolved = ctx.macros.resolve_path (path.get_segments ());
487 : 0 : break;
488 : 0 : case Namespace::Labels:
489 : : // TODO: Is that okay?
490 : 0 : rust_unreachable ();
491 : : }
492 : :
493 : : // FIXME: Ugly
494 : 0 : (void) resolved.map ([this, &found, &declared_name, locus, ns,
495 : 0 : path] (Rib::Definition def) {
496 : 0 : found = true;
497 : :
498 : : // what do we do with the id?
499 : 0 : insert_or_error_out (declared_name, locus, def.get_node_id (), ns);
500 : 0 : auto result = node_forwarding.find (def.get_node_id ());
501 : 0 : if (result != node_forwarding.cend ()
502 : 0 : && result->second != path.get_node_id ())
503 : 0 : rust_error_at (path.get_locus (), "%qs defined multiple times",
504 : : declared_name.c_str ());
505 : : else // No previous thing has inserted this into our scope
506 : 0 : node_forwarding.insert ({def.get_node_id (), path.get_node_id ()});
507 : :
508 : 0 : return def.get_node_id ();
509 : : });
510 : 0 : };
511 : :
512 : 0 : resolve_and_insert (Namespace::Values, path);
513 : 0 : resolve_and_insert (Namespace::Types, path);
514 : 0 : resolve_and_insert (Namespace::Macros, path);
515 : :
516 : 0 : return found;
517 : 0 : }
518 : :
519 : : bool
520 : 16 : TopLevel::handle_rebind (std::pair<AST::SimplePath, AST::UseTreeRebind> &rebind)
521 : : {
522 : 16 : auto &path = rebind.first;
523 : :
524 : 16 : location_t locus = UNKNOWN_LOCATION;
525 : 16 : std::string declared_name;
526 : :
527 : 16 : switch (rebind.second.get_new_bind_type ())
528 : : {
529 : 2 : case AST::UseTreeRebind::NewBindType::IDENTIFIER:
530 : 2 : declared_name = rebind.second.get_identifier ().as_string ();
531 : 2 : locus = rebind.second.get_identifier ().get_locus ();
532 : 2 : break;
533 : 14 : case AST::UseTreeRebind::NewBindType::NONE:
534 : 14 : declared_name = path.get_final_segment ().as_string ();
535 : 14 : locus = path.get_final_segment ().get_locus ();
536 : 14 : break;
537 : 0 : case AST::UseTreeRebind::NewBindType::WILDCARD:
538 : 0 : rust_unreachable ();
539 : 16 : break;
540 : : }
541 : :
542 : : // in what namespace do we perform path resolution? All
543 : : // of them? see which one matches? Error out on
544 : : // ambiguities? so, apparently, for each one that
545 : : // matches, add it to the proper namespace
546 : : // :(
547 : 16 : auto found = false;
548 : :
549 : 64 : auto resolve_and_insert = [this, &found, &declared_name,
550 : : locus] (Namespace ns,
551 : : const AST::SimplePath &path) {
552 : 48 : tl::optional<Rib::Definition> resolved = tl::nullopt;
553 : 48 : tl::optional<Rib::Definition> resolved_bind = tl::nullopt;
554 : :
555 : 48 : std::vector<AST::SimplePathSegment> declaration_v
556 : 96 : = {AST::SimplePathSegment (declared_name, locus)};
557 : : // FIXME: resolve_path needs to return an `expected<NodeId, Error>` so
558 : : // that we can improve it with hints or location or w/ever. and maybe
559 : : // only emit it the first time.
560 : 48 : switch (ns)
561 : : {
562 : 16 : case Namespace::Values:
563 : 16 : resolved = ctx.values.resolve_path (path.get_segments ());
564 : 16 : resolved_bind = ctx.values.resolve_path (declaration_v);
565 : 16 : break;
566 : 16 : case Namespace::Types:
567 : 16 : resolved = ctx.types.resolve_path (path.get_segments ());
568 : 16 : resolved_bind = ctx.types.resolve_path (declaration_v);
569 : 16 : break;
570 : 16 : case Namespace::Macros:
571 : 16 : resolved = ctx.macros.resolve_path (path.get_segments ());
572 : 16 : resolved_bind = ctx.macros.resolve_path (declaration_v);
573 : 16 : break;
574 : 0 : case Namespace::Labels:
575 : : // TODO: Is that okay?
576 : 0 : rust_unreachable ();
577 : : }
578 : :
579 : 48 : resolved.map ([this, &found, &declared_name, locus, ns, path,
580 : 48 : &resolved_bind] (Rib::Definition def) {
581 : 25 : found = true;
582 : :
583 : 25 : insert_or_error_out (declared_name, locus, def.get_node_id (), ns);
584 : 25 : if (resolved_bind.has_value ())
585 : : {
586 : 13 : auto bind_def = resolved_bind.value ();
587 : : // what do we do with the id?
588 : 13 : auto result = node_forwarding.find (bind_def.get_node_id ());
589 : 13 : if (result != node_forwarding.cend ()
590 : 13 : && result->second != path.get_node_id ())
591 : 1 : rust_error_at (path.get_locus (), "%qs defined multiple times",
592 : : declared_name.c_str ());
593 : 13 : }
594 : : else
595 : : {
596 : : // No previous thing has inserted this into our scope
597 : 12 : node_forwarding.insert ({def.get_node_id (), path.get_node_id ()});
598 : : }
599 : 25 : return def.get_node_id ();
600 : : });
601 : 61 : };
602 : :
603 : : // do this for all namespaces (even Labels?)
604 : :
605 : 16 : resolve_and_insert (Namespace::Values, path);
606 : 16 : resolve_and_insert (Namespace::Types, path);
607 : 16 : resolve_and_insert (Namespace::Macros, path);
608 : :
609 : : // TODO: No labels? No, right?
610 : :
611 : 16 : return found;
612 : 16 : }
613 : :
614 : : static void
615 : : flatten_rebind (
616 : : const AST::UseTreeRebind &glob,
617 : : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths);
618 : :
619 : : static void
620 : : flatten_list (
621 : : const AST::UseTreeList &glob, std::vector<AST::SimplePath> &paths,
622 : : std::vector<AST::SimplePath> &glob_paths,
623 : : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
624 : : NameResolutionContext &ctx);
625 : : static void
626 : : flatten_glob (const AST::UseTreeGlob &glob,
627 : : std::vector<AST::SimplePath> &glob_paths,
628 : : NameResolutionContext &ctx);
629 : :
630 : : static void
631 : 20 : flatten (
632 : : const AST::UseTree *tree, std::vector<AST::SimplePath> &paths,
633 : : std::vector<AST::SimplePath> &glob_paths,
634 : : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
635 : : NameResolutionContext &ctx)
636 : : {
637 : 20 : switch (tree->get_kind ())
638 : : {
639 : 16 : case AST::UseTree::Rebind: {
640 : 16 : auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
641 : 16 : flatten_rebind (*rebind, rebind_paths);
642 : 16 : break;
643 : : }
644 : 1 : case AST::UseTree::List: {
645 : 1 : auto list = static_cast<const AST::UseTreeList *> (tree);
646 : 1 : flatten_list (*list, paths, glob_paths, rebind_paths, ctx);
647 : 1 : break;
648 : : }
649 : 3 : case AST::UseTree::Glob: {
650 : 3 : auto glob = static_cast<const AST::UseTreeGlob *> (tree);
651 : 3 : flatten_glob (*glob, glob_paths, ctx);
652 : 3 : break;
653 : : }
654 : : break;
655 : : }
656 : 20 : }
657 : :
658 : : static void
659 : 16 : flatten_rebind (
660 : : const AST::UseTreeRebind &rebind,
661 : : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths)
662 : : {
663 : 16 : rebind_paths.emplace_back (rebind.get_path (), rebind);
664 : 16 : }
665 : :
666 : : /** Prefix a list of subpath
667 : : * @param prefix A prefix for all subpath
668 : : * @param subs List of subpath to prefix
669 : : * @param size List where results should be stored
670 : : */
671 : : static void
672 : 6 : prefix_subpaths (AST::SimplePath prefix, std::vector<AST::SimplePath> subs,
673 : : std::vector<AST::SimplePath> &results)
674 : : {
675 : 6 : for (auto &sub : subs)
676 : : {
677 : 0 : auto new_path = prefix;
678 : 0 : std::copy (sub.get_segments ().begin (), sub.get_segments ().end (),
679 : : std::back_inserter (new_path.get_segments ()));
680 : 0 : results.emplace_back (new_path);
681 : 0 : }
682 : 6 : }
683 : :
684 : : static void
685 : 3 : prefix_rebinds (
686 : : AST::SimplePath prefix,
687 : : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> subs,
688 : : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &results)
689 : : {
690 : 6 : for (auto &sub : subs)
691 : : {
692 : 3 : auto new_path = prefix;
693 : 3 : std::copy (sub.first.get_segments ().begin (),
694 : 3 : sub.first.get_segments ().end (),
695 : : std::back_inserter (new_path.get_segments ()));
696 : 6 : results.emplace_back (std::make_pair (new_path, sub.second));
697 : 3 : }
698 : 3 : }
699 : :
700 : : static void
701 : 1 : flatten_list (
702 : : const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths,
703 : : std::vector<AST::SimplePath> &glob_paths,
704 : : std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
705 : : NameResolutionContext &ctx)
706 : : {
707 : 1 : auto prefix = AST::SimplePath::create_empty ();
708 : 1 : if (list.has_path ())
709 : 1 : prefix = list.get_path ();
710 : :
711 : 4 : for (const auto &tree : list.get_trees ())
712 : : {
713 : 3 : auto sub_paths = std::vector<AST::SimplePath> ();
714 : 3 : auto sub_globs = std::vector<AST::SimplePath> ();
715 : 3 : auto sub_rebinds
716 : 3 : = std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> ();
717 : 3 : flatten (tree.get (), sub_paths, sub_globs, sub_rebinds, ctx);
718 : :
719 : 3 : prefix_subpaths (prefix, sub_paths, paths);
720 : 3 : prefix_subpaths (prefix, sub_globs, glob_paths);
721 : 3 : prefix_rebinds (prefix, sub_rebinds, rebind_paths);
722 : 3 : }
723 : 1 : }
724 : :
725 : : static void
726 : 3 : flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths,
727 : : NameResolutionContext &ctx)
728 : : {
729 : 3 : if (glob.has_path ())
730 : 3 : paths.emplace_back (glob.get_path ());
731 : 3 : }
732 : :
733 : : void
734 : 17 : TopLevel::visit (AST::UseDeclaration &use)
735 : : {
736 : 17 : auto paths = std::vector<AST::SimplePath> ();
737 : 17 : auto glob_path = std::vector<AST::SimplePath> ();
738 : 17 : auto rebind_path
739 : 17 : = std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> ();
740 : :
741 : : // FIXME: How do we handle `use foo::{self}` imports? Some beforehand cleanup?
742 : : // How do we handle module imports in general? Should they get added to all
743 : : // namespaces?
744 : :
745 : 17 : const auto &tree = use.get_tree ();
746 : 17 : flatten (tree.get (), paths, glob_path, rebind_path, this->ctx);
747 : :
748 : 17 : for (auto &path : paths)
749 : 0 : if (!handle_use_dec (path))
750 : 0 : rust_error_at (path.get_final_segment ().get_locus (), ErrorCode::E0433,
751 : 0 : "unresolved import %qs", path.as_string ().c_str ());
752 : :
753 : 20 : for (auto &glob : glob_path)
754 : 3 : if (!handle_use_glob (glob))
755 : 0 : rust_error_at (glob.get_final_segment ().get_locus (), ErrorCode::E0433,
756 : 0 : "unresolved import %qs", glob.as_string ().c_str ());
757 : :
758 : 33 : for (auto &rebind : rebind_path)
759 : 16 : if (!handle_rebind (rebind))
760 : 3 : rust_error_at (rebind.first.get_final_segment ().get_locus (),
761 : : ErrorCode::E0433, "unresolved import %qs",
762 : 6 : rebind.first.as_string ().c_str ());
763 : 17 : }
764 : :
765 : : } // namespace Resolver2_0
766 : : } // namespace Rust
|