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-ast-resolve-item.h"
20 : : #include "rust-ast-full-decls.h"
21 : : #include "rust-ast-resolve-toplevel.h"
22 : : #include "rust-ast-resolve-type.h"
23 : : #include "rust-ast-resolve-pattern.h"
24 : : #include "rust-ast-resolve-path.h"
25 : :
26 : : #include "rust-item.h"
27 : : #include "selftest.h"
28 : :
29 : : namespace Rust {
30 : : namespace Resolver {
31 : :
32 : 2492 : ResolveTraitItems::ResolveTraitItems (const CanonicalPath &prefix,
33 : 2492 : const CanonicalPath &canonical_prefix)
34 : 2492 : : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
35 : 2492 : {}
36 : :
37 : : void
38 : 2492 : ResolveTraitItems::go (AST::AssociatedItem *item, const CanonicalPath &prefix,
39 : : const CanonicalPath &canonical_prefix)
40 : : {
41 : 2492 : if (item->is_marked_for_strip ())
42 : 0 : return;
43 : :
44 : 2492 : ResolveTraitItems resolver (prefix, canonical_prefix);
45 : 2492 : item->accept_vis (resolver);
46 : 2492 : }
47 : :
48 : : void
49 : 1735 : ResolveTraitItems::visit (AST::Function &function)
50 : : {
51 : 1735 : auto decl
52 : 1735 : = CanonicalPath::new_seg (function.get_node_id (),
53 : 1735 : function.get_function_name ().as_string ());
54 : 1735 : auto path = prefix.append (decl);
55 : 1735 : auto cpath = canonical_prefix.append (decl);
56 : 1735 : mappings.insert_canonical_path (function.get_node_id (), cpath);
57 : :
58 : 1735 : NodeId scope_node_id = function.get_node_id ();
59 : 1735 : resolver->get_name_scope ().push (scope_node_id);
60 : 1735 : resolver->get_type_scope ().push (scope_node_id);
61 : 1735 : resolver->get_label_scope ().push (scope_node_id);
62 : 1735 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
63 : 1735 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
64 : 1735 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
65 : :
66 : 1735 : if (function.has_generics ())
67 : 9 : ResolveGenericParams::go (function.get_generic_params (), prefix,
68 : : canonical_prefix);
69 : :
70 : 1735 : if (function.has_return_type ())
71 : 1380 : ResolveType::go (function.get_return_type ());
72 : :
73 : : // self turns into (self: Self) as a function param
74 : 1735 : std::vector<PatternBinding> bindings
75 : 3470 : = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
76 : :
77 : : // we make a new scope so the names of parameters are resolved and shadowed
78 : : // correctly
79 : 3923 : for (auto &p : function.get_function_params ())
80 : : {
81 : 2188 : if (p->is_variadic ())
82 : : {
83 : 0 : auto param = static_cast<AST::VariadicParam &> (*p);
84 : 0 : PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
85 : : bindings);
86 : 0 : }
87 : 2188 : else if (p->is_self ())
88 : : {
89 : 1385 : auto ¶m = static_cast<AST::SelfParam &> (*p);
90 : : // FIXME: which location should be used for Rust::Identifier `self`?
91 : 1385 : AST::IdentifierPattern self_pattern (
92 : : param.get_node_id (), {"self"}, param.get_locus (),
93 : 1385 : param.get_has_ref (), param.get_is_mut (),
94 : 1385 : std::unique_ptr<AST::Pattern> (nullptr));
95 : :
96 : 1385 : PatternDeclaration::go (self_pattern, Rib::ItemType::Param);
97 : :
98 : 1385 : if (param.has_type ())
99 : : {
100 : : // This shouldn't happen the parser should already error for this
101 : 0 : rust_assert (!param.get_has_ref ());
102 : 0 : ResolveType::go (param.get_type ());
103 : : }
104 : : else
105 : : {
106 : : // here we implicitly make self have a type path of Self
107 : 1385 : std::vector<std::unique_ptr<AST::TypePathSegment>> segments;
108 : 1385 : segments.push_back (std::unique_ptr<AST::TypePathSegment> (
109 : 1385 : new AST::TypePathSegment ("Self", false, param.get_locus ())));
110 : :
111 : 1385 : AST::TypePath self_type_path (std::move (segments),
112 : 1385 : param.get_locus ());
113 : 1385 : ResolveType::go (self_type_path);
114 : 1385 : }
115 : 1385 : }
116 : : else
117 : : {
118 : 803 : auto ¶m = static_cast<AST::FunctionParam &> (*p);
119 : 803 : ResolveType::go (param.get_type ());
120 : 803 : PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
121 : : bindings);
122 : : }
123 : : }
124 : :
125 : 1735 : if (function.has_where_clause ())
126 : 2 : ResolveWhereClause::Resolve (function.get_where_clause ());
127 : :
128 : : // trait items have an optional body
129 : 1735 : if (function.has_body ())
130 : 232 : ResolveExpr::go (*function.get_definition ().value (), path, cpath);
131 : :
132 : 1735 : resolver->get_name_scope ().pop ();
133 : 1735 : resolver->get_type_scope ().pop ();
134 : 1735 : resolver->get_label_scope ().pop ();
135 : 1735 : }
136 : : void
137 : 714 : ResolveTraitItems::visit (AST::TraitItemType &type)
138 : : {
139 : 714 : auto decl = CanonicalPath::new_seg (type.get_node_id (),
140 : 714 : type.get_identifier ().as_string ());
141 : 714 : auto path = prefix.append (decl);
142 : 714 : auto cpath = canonical_prefix.append (decl);
143 : 714 : mappings.insert_canonical_path (type.get_node_id (), cpath);
144 : :
145 : 750 : for (auto &bound : type.get_type_param_bounds ())
146 : 36 : ResolveTypeBound::go (*bound);
147 : 714 : }
148 : :
149 : : void
150 : 43 : ResolveTraitItems::visit (AST::TraitItemConst &constant)
151 : : {
152 : 43 : auto decl = CanonicalPath::new_seg (constant.get_node_id (),
153 : 43 : constant.get_identifier ().as_string ());
154 : 43 : auto path = prefix.append (decl);
155 : 43 : auto cpath = canonical_prefix.append (decl);
156 : 43 : mappings.insert_canonical_path (constant.get_node_id (), cpath);
157 : :
158 : 43 : ResolveType::go (constant.get_type ());
159 : :
160 : 43 : if (constant.has_expr ())
161 : 9 : ResolveExpr::go (constant.get_expr (), path, cpath);
162 : 43 : }
163 : :
164 : 28478 : ResolveItem::ResolveItem (const CanonicalPath &prefix,
165 : 28478 : const CanonicalPath &canonical_prefix)
166 : 28478 : : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
167 : 28478 : {}
168 : :
169 : : void
170 : 21614 : ResolveItem::go (AST::Item &item, const CanonicalPath &prefix,
171 : : const CanonicalPath &canonical_prefix)
172 : : {
173 : 21614 : ResolveItem resolver (prefix, canonical_prefix);
174 : 21614 : item.accept_vis (resolver);
175 : 21613 : }
176 : :
177 : : void
178 : 1182 : ResolveItem::visit (AST::TypeAlias &alias)
179 : : {
180 : 1182 : auto talias
181 : : = CanonicalPath::new_seg (alias.get_node_id (),
182 : 1182 : alias.get_new_type_name ().as_string ());
183 : 1182 : auto path = prefix.append (talias);
184 : 1182 : auto cpath = canonical_prefix.append (talias);
185 : 1182 : mappings.insert_canonical_path (alias.get_node_id (), cpath);
186 : :
187 : 1182 : NodeId scope_node_id = alias.get_node_id ();
188 : 1182 : resolver->get_type_scope ().push (scope_node_id);
189 : :
190 : 1182 : if (alias.has_generics ())
191 : 9 : ResolveGenericParams::go (alias.get_generic_params (), prefix,
192 : : canonical_prefix);
193 : :
194 : 1182 : if (alias.has_where_clause ())
195 : 0 : ResolveWhereClause::Resolve (alias.get_where_clause ());
196 : :
197 : 1182 : ResolveType::go (alias.get_type_aliased ());
198 : :
199 : 1182 : resolver->get_type_scope ().pop ();
200 : 1182 : }
201 : :
202 : : void
203 : 822 : ResolveItem::visit (AST::Module &module)
204 : : {
205 : 822 : auto mod = CanonicalPath::new_seg (module.get_node_id (),
206 : 822 : module.get_name ().as_string ());
207 : 822 : auto path = prefix.append (mod);
208 : 822 : auto cpath = canonical_prefix.append (mod);
209 : 822 : mappings.insert_canonical_path (module.get_node_id (), cpath);
210 : :
211 : 822 : resolve_visibility (module.get_visibility ());
212 : :
213 : 822 : NodeId scope_node_id = module.get_node_id ();
214 : 822 : resolver->get_name_scope ().push (scope_node_id);
215 : 822 : resolver->get_type_scope ().push (scope_node_id);
216 : 822 : resolver->get_label_scope ().push (scope_node_id);
217 : 822 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
218 : 822 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
219 : 822 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
220 : :
221 : : // FIXME: Should we reinsert a child here? Any reason we ResolveTopLevel::go
222 : : // in ResolveTopLevel::visit (AST::Module) as well as here?
223 : 4232 : for (auto &item : module.get_items ())
224 : 3410 : ResolveTopLevel::go (*item, CanonicalPath::create_empty (), cpath);
225 : :
226 : 822 : resolver->push_new_module_scope (module.get_node_id ());
227 : 4232 : for (auto &item : module.get_items ())
228 : 3410 : ResolveItem::go (*item, path, cpath);
229 : :
230 : 822 : resolver->pop_module_scope ();
231 : :
232 : 822 : resolver->get_name_scope ().pop ();
233 : 822 : resolver->get_type_scope ().pop ();
234 : 822 : resolver->get_label_scope ().pop ();
235 : 822 : }
236 : :
237 : : void
238 : 838 : ResolveItem::visit (AST::TupleStruct &struct_decl)
239 : : {
240 : 838 : auto decl
241 : : = CanonicalPath::new_seg (struct_decl.get_node_id (),
242 : 838 : struct_decl.get_identifier ().as_string ());
243 : 838 : auto path = prefix.append (decl);
244 : 838 : auto cpath = canonical_prefix.append (decl);
245 : 838 : mappings.insert_canonical_path (struct_decl.get_node_id (), cpath);
246 : :
247 : 838 : resolve_visibility (struct_decl.get_visibility ());
248 : :
249 : 838 : NodeId scope_node_id = struct_decl.get_node_id ();
250 : 838 : resolver->get_type_scope ().push (scope_node_id);
251 : :
252 : 838 : if (struct_decl.has_generics ())
253 : 354 : ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
254 : : canonical_prefix);
255 : :
256 : 838 : if (struct_decl.has_where_clause ())
257 : 0 : ResolveWhereClause::Resolve (struct_decl.get_where_clause ());
258 : :
259 : 2031 : for (AST::TupleField &field : struct_decl.get_fields ())
260 : : {
261 : 1193 : if (field.get_field_type ().is_marked_for_strip ())
262 : 0 : continue;
263 : :
264 : 1193 : resolve_visibility (field.get_visibility ());
265 : :
266 : 1193 : ResolveType::go (field.get_field_type ());
267 : : }
268 : :
269 : 838 : resolver->get_type_scope ().pop ();
270 : 838 : }
271 : :
272 : : void
273 : 315 : ResolveItem::visit (AST::Enum &enum_decl)
274 : : {
275 : 315 : auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (),
276 : 315 : enum_decl.get_identifier ().as_string ());
277 : 315 : auto path = prefix.append (decl);
278 : 315 : auto cpath = canonical_prefix.append (decl);
279 : 315 : mappings.insert_canonical_path (enum_decl.get_node_id (), cpath);
280 : :
281 : 315 : resolve_visibility (enum_decl.get_visibility ());
282 : :
283 : 315 : NodeId scope_node_id = enum_decl.get_node_id ();
284 : 315 : resolver->get_type_scope ().push (scope_node_id);
285 : :
286 : 315 : if (enum_decl.has_generics ())
287 : 142 : ResolveGenericParams::go (enum_decl.get_generic_params (), prefix,
288 : : canonical_prefix);
289 : :
290 : 315 : if (enum_decl.has_where_clause ())
291 : 0 : ResolveWhereClause::Resolve (enum_decl.get_where_clause ());
292 : :
293 : : /* The actual fields are inside the variants. */
294 : 1062 : for (auto &variant : enum_decl.get_variants ())
295 : 747 : ResolveItem::go (*variant, path, cpath);
296 : :
297 : 315 : resolver->get_type_scope ().pop ();
298 : 315 : }
299 : :
300 : : /* EnumItem doesn't need to be handled, no fields. */
301 : : void
302 : 336 : ResolveItem::visit (AST::EnumItem &item)
303 : : {
304 : : // Since at this point we cannot have visibilities on enum items anymore, we
305 : : // can skip handling them
306 : :
307 : 336 : auto decl = CanonicalPath::new_seg (item.get_node_id (),
308 : 336 : item.get_identifier ().as_string ());
309 : 336 : auto path = prefix.append (decl);
310 : 336 : auto cpath = canonical_prefix.append (decl);
311 : 336 : mappings.insert_canonical_path (item.get_node_id (), cpath);
312 : 336 : }
313 : :
314 : : void
315 : 331 : ResolveItem::visit (AST::EnumItemTuple &item)
316 : : {
317 : 331 : auto decl = CanonicalPath::new_seg (item.get_node_id (),
318 : 331 : item.get_identifier ().as_string ());
319 : 331 : auto path = prefix.append (decl);
320 : 331 : auto cpath = canonical_prefix.append (decl);
321 : 331 : mappings.insert_canonical_path (item.get_node_id (), cpath);
322 : :
323 : 664 : for (auto &field : item.get_tuple_fields ())
324 : : {
325 : 333 : if (field.get_field_type ().is_marked_for_strip ())
326 : 0 : continue;
327 : :
328 : 333 : ResolveType::go (field.get_field_type ());
329 : : }
330 : 331 : }
331 : :
332 : : void
333 : 69 : ResolveItem::visit (AST::EnumItemStruct &item)
334 : : {
335 : 69 : auto decl = CanonicalPath::new_seg (item.get_node_id (),
336 : 69 : item.get_identifier ().as_string ());
337 : 69 : auto path = prefix.append (decl);
338 : 69 : auto cpath = canonical_prefix.append (decl);
339 : 69 : mappings.insert_canonical_path (item.get_node_id (), cpath);
340 : :
341 : 188 : for (auto &field : item.get_struct_fields ())
342 : : {
343 : 119 : if (field.get_field_type ().is_marked_for_strip ())
344 : 0 : continue;
345 : :
346 : 119 : ResolveType::go (field.get_field_type ());
347 : : }
348 : 69 : }
349 : :
350 : : void
351 : 11 : ResolveItem::visit (AST::EnumItemDiscriminant &item)
352 : : {
353 : 11 : auto decl = CanonicalPath::new_seg (item.get_node_id (),
354 : 11 : item.get_identifier ().as_string ());
355 : 11 : auto path = prefix.append (decl);
356 : 11 : auto cpath = canonical_prefix.append (decl);
357 : :
358 : 11 : mappings.insert_canonical_path (item.get_node_id (), cpath);
359 : :
360 : 11 : ResolveExpr::go (item.get_expr (), path, cpath);
361 : 11 : }
362 : :
363 : : void
364 : 1091 : ResolveItem::visit (AST::StructStruct &struct_decl)
365 : : {
366 : 1091 : auto decl
367 : : = CanonicalPath::new_seg (struct_decl.get_node_id (),
368 : 1091 : struct_decl.get_identifier ().as_string ());
369 : 1091 : auto path = prefix.append (decl);
370 : 1091 : auto cpath = canonical_prefix.append (decl);
371 : 1091 : mappings.insert_canonical_path (struct_decl.get_node_id (), cpath);
372 : :
373 : 1091 : resolve_visibility (struct_decl.get_visibility ());
374 : :
375 : 1091 : NodeId scope_node_id = struct_decl.get_node_id ();
376 : 1091 : resolver->get_type_scope ().push (scope_node_id);
377 : :
378 : 1091 : if (struct_decl.has_generics ())
379 : 299 : ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
380 : : canonical_prefix);
381 : :
382 : 1091 : if (struct_decl.has_where_clause ())
383 : 2 : ResolveWhereClause::Resolve (struct_decl.get_where_clause ());
384 : :
385 : 2615 : for (AST::StructField &field : struct_decl.get_fields ())
386 : : {
387 : 1524 : if (field.get_field_type ().is_marked_for_strip ())
388 : 0 : continue;
389 : :
390 : 1524 : resolve_visibility (field.get_visibility ());
391 : :
392 : 1524 : ResolveType::go (field.get_field_type ());
393 : : }
394 : :
395 : 1091 : resolver->get_type_scope ().pop ();
396 : 1091 : }
397 : :
398 : : void
399 : 101 : ResolveItem::visit (AST::Union &union_decl)
400 : : {
401 : 101 : auto decl
402 : : = CanonicalPath::new_seg (union_decl.get_node_id (),
403 : 101 : union_decl.get_identifier ().as_string ());
404 : 101 : auto path = prefix.append (decl);
405 : 101 : auto cpath = canonical_prefix.append (decl);
406 : 101 : mappings.insert_canonical_path (union_decl.get_node_id (), cpath);
407 : :
408 : 101 : resolve_visibility (union_decl.get_visibility ());
409 : :
410 : 101 : NodeId scope_node_id = union_decl.get_node_id ();
411 : 101 : resolver->get_type_scope ().push (scope_node_id);
412 : :
413 : 101 : if (union_decl.has_generics ())
414 : 74 : ResolveGenericParams::go (union_decl.get_generic_params (), prefix,
415 : : canonical_prefix);
416 : :
417 : 101 : if (union_decl.has_where_clause ())
418 : 0 : ResolveWhereClause::Resolve (union_decl.get_where_clause ());
419 : :
420 : 399 : for (AST::StructField &field : union_decl.get_variants ())
421 : : {
422 : 298 : if (field.get_field_type ().is_marked_for_strip ())
423 : 0 : continue;
424 : :
425 : 298 : ResolveType::go (field.get_field_type ());
426 : : }
427 : :
428 : 101 : resolver->get_type_scope ().pop ();
429 : 101 : }
430 : :
431 : : void
432 : 68 : ResolveItem::visit (AST::StaticItem &var)
433 : : {
434 : 68 : auto decl = CanonicalPath::new_seg (var.get_node_id (),
435 : 68 : var.get_identifier ().as_string ());
436 : 68 : auto path = prefix.append (decl);
437 : 68 : auto cpath = canonical_prefix.append (decl);
438 : 68 : mappings.insert_canonical_path (var.get_node_id (), cpath);
439 : :
440 : 68 : ResolveType::go (var.get_type ());
441 : 68 : ResolveExpr::go (var.get_expr (), path, cpath);
442 : 68 : }
443 : :
444 : : void
445 : 455 : ResolveItem::visit (AST::ConstantItem &constant)
446 : : {
447 : 455 : auto decl = CanonicalPath::new_seg (constant.get_node_id (),
448 : 455 : constant.get_identifier ());
449 : 455 : auto path = prefix.append (decl);
450 : 455 : auto cpath = canonical_prefix.append (decl);
451 : 455 : mappings.insert_canonical_path (constant.get_node_id (), cpath);
452 : :
453 : 455 : resolve_visibility (constant.get_visibility ());
454 : :
455 : 455 : ResolveType::go (constant.get_type ());
456 : 455 : ResolveExpr::go (constant.get_expr (), path, cpath);
457 : 455 : }
458 : :
459 : : void
460 : 11999 : ResolveItem::visit (AST::Function &function)
461 : : {
462 : 11999 : auto decl
463 : 11999 : = CanonicalPath::new_seg (function.get_node_id (),
464 : 11999 : function.get_function_name ().as_string ());
465 : 11999 : auto path = prefix.append (decl);
466 : 11999 : auto cpath = canonical_prefix.append (decl);
467 : :
468 : 11999 : mappings.insert_canonical_path (function.get_node_id (), cpath);
469 : :
470 : 11999 : resolve_visibility (function.get_visibility ());
471 : :
472 : 11999 : NodeId scope_node_id = function.get_node_id ();
473 : 11999 : resolver->get_name_scope ().push (scope_node_id);
474 : 11999 : resolver->get_type_scope ().push (scope_node_id);
475 : 11999 : resolver->get_label_scope ().push (scope_node_id);
476 : 11999 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
477 : 11999 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
478 : 11999 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
479 : :
480 : 11999 : if (function.has_generics ())
481 : 650 : ResolveGenericParams::go (function.get_generic_params (), prefix,
482 : : canonical_prefix);
483 : :
484 : : // resolve any where clause items
485 : 11999 : if (function.has_where_clause ())
486 : 13 : ResolveWhereClause::Resolve (function.get_where_clause ());
487 : :
488 : 11999 : if (function.has_return_type ())
489 : 8361 : ResolveType::go (function.get_return_type ());
490 : :
491 : 11999 : if (function.has_self_param ())
492 : : {
493 : : // self turns into (self: Self) as a function param
494 : 4514 : AST::Param &s_param = function.get_self_param ();
495 : 4514 : auto &self_param = static_cast<AST::SelfParam &> (s_param);
496 : :
497 : : // FIXME: which location should be used for Rust::Identifier `self`?
498 : 4514 : AST::IdentifierPattern self_pattern (
499 : : self_param.get_node_id (), {"self"}, self_param.get_locus (),
500 : 4514 : self_param.get_has_ref (), self_param.get_is_mut (),
501 : 4514 : std::unique_ptr<AST::Pattern> (nullptr));
502 : 4514 : PatternDeclaration::go (self_pattern, Rib::ItemType::Param);
503 : :
504 : 4514 : if (self_param.has_type ())
505 : : {
506 : : // This shouldn't happen the parser should already error for this
507 : 1 : rust_assert (!self_param.get_has_ref ());
508 : 1 : ResolveType::go (self_param.get_type ());
509 : : }
510 : : else
511 : : {
512 : : // here we implicitly make self have a type path of Self
513 : 4513 : std::vector<std::unique_ptr<AST::TypePathSegment>> segments;
514 : 4513 : segments.push_back (std::unique_ptr<AST::TypePathSegment> (
515 : 4513 : new AST::TypePathSegment ("Self", false, self_param.get_locus ())));
516 : :
517 : 4513 : AST::TypePath self_type_path (std::move (segments),
518 : 4513 : self_param.get_locus ());
519 : 4513 : ResolveType::go (self_type_path);
520 : 4513 : }
521 : 4514 : }
522 : :
523 : 11999 : std::vector<PatternBinding> bindings
524 : 23998 : = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
525 : :
526 : : // we make a new scope so the names of parameters are resolved and shadowed
527 : : // correctly
528 : 21371 : for (auto &p : function.get_function_params ())
529 : : {
530 : 9372 : if (p->is_variadic ())
531 : : {
532 : 0 : auto ¶m = static_cast<AST::VariadicParam &> (*p);
533 : 0 : if (param.has_pattern ())
534 : 0 : PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
535 : : bindings);
536 : : }
537 : 9372 : else if (p->is_self ())
538 : : {
539 : 4514 : auto ¶m = static_cast<AST::SelfParam &> (*p);
540 : 4514 : if (param.has_type ())
541 : 1 : ResolveType::go (param.get_type ());
542 : : }
543 : : else
544 : : {
545 : 4858 : auto ¶m = static_cast<AST::FunctionParam &> (*p);
546 : 4858 : ResolveType::go (param.get_type ());
547 : 4858 : PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
548 : : bindings);
549 : : }
550 : : }
551 : :
552 : : // resolve the function body
553 : 11999 : ResolveExpr::go (*function.get_definition ().value (), path, cpath);
554 : :
555 : 11998 : resolver->get_name_scope ().pop ();
556 : 11998 : resolver->get_type_scope ().pop ();
557 : 11998 : resolver->get_label_scope ().pop ();
558 : 11998 : }
559 : :
560 : : void
561 : 905 : ResolveItem::visit (AST::InherentImpl &impl_block)
562 : : {
563 : 905 : NodeId scope_node_id = impl_block.get_node_id ();
564 : 905 : resolver->get_name_scope ().push (scope_node_id);
565 : 905 : resolver->get_type_scope ().push (scope_node_id);
566 : 905 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
567 : 905 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
568 : :
569 : 905 : resolve_visibility (impl_block.get_visibility ());
570 : :
571 : 905 : if (impl_block.has_generics ())
572 : 314 : ResolveGenericParams::go (impl_block.get_generic_params (), prefix,
573 : : canonical_prefix);
574 : :
575 : : // resolve any where clause items
576 : 905 : if (impl_block.has_where_clause ())
577 : 0 : ResolveWhereClause::Resolve (impl_block.get_where_clause ());
578 : :
579 : : // FIXME this needs to be protected behind nominal type-checks see:
580 : : // rustc --explain E0118
581 : : // issue #2634
582 : 905 : ResolveType::go (impl_block.get_type ());
583 : :
584 : : // Setup paths
585 : 905 : CanonicalPath self_cpath = CanonicalPath::create_empty ();
586 : 905 : bool ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (), self_cpath);
587 : 905 : if (!ok)
588 : : {
589 : 2 : resolver->get_name_scope ().pop ();
590 : 2 : resolver->get_type_scope ().pop ();
591 : 2 : resolver->get_label_scope ().pop ();
592 : 2 : return;
593 : : }
594 : :
595 : 903 : rust_debug ("AST::InherentImpl resolve Self: {%s}",
596 : : self_cpath.get ().c_str ());
597 : :
598 : 903 : CanonicalPath impl_type = self_cpath;
599 : 903 : CanonicalPath impl_type_seg
600 : 903 : = CanonicalPath::inherent_impl_seg (impl_block.get_node_id (), impl_type);
601 : 903 : CanonicalPath impl_prefix = prefix.append (impl_type_seg);
602 : :
603 : : // see https://godbolt.org/z/a3vMbsT6W
604 : 903 : CanonicalPath cpath = CanonicalPath::create_empty ();
605 : 903 : if (canonical_prefix.size () <= 1)
606 : : {
607 : 827 : cpath = impl_prefix;
608 : : }
609 : : else
610 : : {
611 : 152 : std::string seg_buf = "<impl " + self_cpath.get () + ">";
612 : 76 : CanonicalPath seg
613 : 76 : = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf);
614 : 76 : cpath = canonical_prefix.append (seg);
615 : 76 : }
616 : :
617 : : // done setup paths
618 : :
619 : 903 : auto Self
620 : 903 : = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ());
621 : :
622 : 1806 : resolver->get_type_scope ().insert (Self,
623 : 903 : impl_block.get_type ().get_node_id (),
624 : 903 : impl_block.get_type ().get_locus ());
625 : :
626 : 3511 : for (auto &impl_item : impl_block.get_impl_items ())
627 : : {
628 : 2608 : rust_debug (
629 : : "AST::InherentImpl resolve_impl_item: impl_prefix={%s} cpath={%s}",
630 : : impl_prefix.get ().c_str (), cpath.get ().c_str ());
631 : 2608 : resolve_impl_item (*impl_item, impl_prefix, cpath);
632 : : }
633 : :
634 : 1806 : resolver->get_type_scope ().peek ()->clear_name (
635 : 903 : Self, impl_block.get_type ().get_node_id ());
636 : :
637 : 903 : resolver->get_type_scope ().pop ();
638 : 903 : resolver->get_name_scope ().pop ();
639 : 905 : }
640 : :
641 : : void
642 : 4077 : ResolveItem::visit (AST::TraitImpl &impl_block)
643 : : {
644 : 4077 : NodeId scope_node_id = impl_block.get_node_id ();
645 : :
646 : 4077 : resolve_visibility (impl_block.get_visibility ());
647 : :
648 : 4077 : resolver->get_name_scope ().push (scope_node_id);
649 : 4077 : resolver->get_type_scope ().push (scope_node_id);
650 : 4077 : resolver->get_label_scope ().push (scope_node_id);
651 : 4077 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
652 : 4077 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
653 : 4077 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
654 : :
655 : 4077 : if (impl_block.has_generics ())
656 : 674 : ResolveGenericParams::go (impl_block.get_generic_params (), prefix,
657 : : canonical_prefix);
658 : :
659 : : // resolve any where clause items
660 : 4077 : if (impl_block.has_where_clause ())
661 : 83 : ResolveWhereClause::Resolve (impl_block.get_where_clause ());
662 : :
663 : : // CanonicalPath canonical_trait_type = CanonicalPath::create_empty ();
664 : 4077 : NodeId trait_resolved_node = ResolveType::go (impl_block.get_trait_path ());
665 : 4077 : if (trait_resolved_node == UNKNOWN_NODEID)
666 : : {
667 : 1 : resolver->get_name_scope ().pop ();
668 : 1 : resolver->get_type_scope ().pop ();
669 : 1 : resolver->get_label_scope ().pop ();
670 : 4 : return;
671 : : }
672 : :
673 : : // CanonicalPath canonical_impl_type = CanonicalPath::create_empty ();
674 : 4076 : NodeId type_resolved_node = ResolveType::go (impl_block.get_type ());
675 : 4076 : if (type_resolved_node == UNKNOWN_NODEID)
676 : : {
677 : 2 : resolver->get_name_scope ().pop ();
678 : 2 : resolver->get_type_scope ().pop ();
679 : 2 : resolver->get_label_scope ().pop ();
680 : 2 : return;
681 : : }
682 : :
683 : 4074 : bool ok = true;
684 : :
685 : : // setup paths
686 : 4074 : CanonicalPath canonical_trait_type = CanonicalPath::create_empty ();
687 : :
688 : 4074 : ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path (),
689 : : canonical_trait_type);
690 : 4074 : if (!ok)
691 : : {
692 : 0 : resolver->get_name_scope ().pop ();
693 : 0 : resolver->get_type_scope ().pop ();
694 : 0 : resolver->get_label_scope ().pop ();
695 : 0 : return;
696 : : }
697 : :
698 : 4074 : rust_debug ("AST::TraitImpl resolve trait type: {%s}",
699 : : canonical_trait_type.get ().c_str ());
700 : :
701 : 4074 : CanonicalPath canonical_impl_type = CanonicalPath::create_empty ();
702 : 4074 : ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (),
703 : : canonical_impl_type);
704 : 4074 : if (!ok)
705 : : {
706 : 0 : resolver->get_name_scope ().pop ();
707 : 0 : resolver->get_type_scope ().pop ();
708 : 0 : resolver->get_label_scope ().pop ();
709 : 0 : return;
710 : : }
711 : :
712 : 4074 : rust_debug ("AST::TraitImpl resolve self: {%s}",
713 : : canonical_impl_type.get ().c_str ());
714 : :
715 : : // raw paths
716 : 4074 : CanonicalPath impl_type_seg = canonical_impl_type;
717 : 4074 : CanonicalPath trait_type_seg = canonical_trait_type;
718 : 4074 : CanonicalPath projection
719 : : = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (),
720 : 4074 : trait_type_seg, impl_type_seg);
721 : 4074 : CanonicalPath impl_prefix = prefix.append (projection);
722 : :
723 : : // setup canonical-path
724 : 4074 : CanonicalPath canonical_projection
725 : : = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (),
726 : : canonical_trait_type,
727 : 4074 : canonical_impl_type);
728 : 4074 : CanonicalPath cpath = CanonicalPath::create_empty ();
729 : 4074 : if (canonical_prefix.size () <= 1)
730 : : {
731 : 1944 : cpath = canonical_projection;
732 : : }
733 : : else
734 : : {
735 : 2130 : std::string projection_str = canonical_projection.get ();
736 : 2130 : std::string seg_buf
737 : 4260 : = "<impl " + projection_str.substr (1, projection_str.size () - 2)
738 : 2130 : + ">";
739 : 2130 : CanonicalPath seg
740 : 2130 : = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf);
741 : 2130 : cpath = canonical_prefix.append (seg);
742 : 2130 : }
743 : :
744 : : // DONE setup canonical-path
745 : :
746 : 4074 : auto Self
747 : 4074 : = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ());
748 : :
749 : 8148 : resolver->get_type_scope ().insert (Self,
750 : 4074 : impl_block.get_type ().get_node_id (),
751 : 4074 : impl_block.get_type ().get_locus ());
752 : :
753 : 8330 : for (auto &impl_item : impl_block.get_impl_items ())
754 : : {
755 : 4256 : rust_debug (
756 : : "AST::TraitImpl resolve_impl_item: impl_prefix={%s} cpath={%s}",
757 : : impl_prefix.get ().c_str (), cpath.get ().c_str ());
758 : 4256 : resolve_impl_item (*impl_item, impl_prefix, cpath);
759 : : }
760 : :
761 : 4074 : Rib *r = resolver->get_type_scope ().peek ();
762 : 4074 : r->clear_name (Self, impl_block.get_type ().get_node_id ());
763 : :
764 : 4074 : resolver->get_name_scope ().pop ();
765 : 4074 : resolver->get_type_scope ().pop ();
766 : 4074 : resolver->get_label_scope ().pop ();
767 : 4074 : }
768 : :
769 : : void
770 : 3143 : ResolveItem::visit (AST::Trait &trait)
771 : : {
772 : 3143 : NodeId scope_node_id = trait.get_node_id ();
773 : :
774 : 3143 : resolve_visibility (trait.get_visibility ());
775 : :
776 : 3143 : resolver->get_name_scope ().push (scope_node_id);
777 : 3143 : resolver->get_type_scope ().push (scope_node_id);
778 : 3143 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
779 : 3143 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
780 : :
781 : 3143 : ResolveGenericParams::go_single (trait.get_implicit_self (), prefix,
782 : : canonical_prefix);
783 : 3143 : ResolveGenericParams::go (trait.get_generic_params (), prefix,
784 : : canonical_prefix);
785 : :
786 : : // Self is an implicit TypeParam so lets mark it as such
787 : 3143 : resolver->get_type_scope ().append_reference_for_def (
788 : 3143 : trait.get_node_id (), trait.get_implicit_self ().get_node_id ());
789 : :
790 : 3143 : if (trait.has_type_param_bounds ())
791 : : {
792 : 701 : for (auto &bound : trait.get_type_param_bounds ())
793 : : {
794 : 351 : ResolveTypeBound::go (*bound);
795 : : }
796 : : }
797 : :
798 : : // resolve any where clause items
799 : 3143 : if (trait.has_where_clause ())
800 : 7 : ResolveWhereClause::Resolve (trait.get_where_clause ());
801 : :
802 : : // resolve the paths
803 : 3143 : CanonicalPath path = CanonicalPath::create_empty ();
804 : 3143 : CanonicalPath cpath = CanonicalPath::create_empty ();
805 : : //
806 : :
807 : 5635 : for (auto &item : trait.get_trait_items ())
808 : : {
809 : 2492 : ResolveTraitItems::go (item.get (), path, cpath);
810 : : }
811 : :
812 : 3143 : resolver->get_type_scope ().pop ();
813 : 3143 : resolver->get_name_scope ().pop ();
814 : 3143 : }
815 : :
816 : : void
817 : 1377 : ResolveItem::visit (AST::ExternBlock &extern_block)
818 : : {
819 : 1377 : resolve_visibility (extern_block.get_visibility ());
820 : :
821 : 3541 : for (auto &item : extern_block.get_extern_items ())
822 : : {
823 : 2164 : resolve_extern_item (*item);
824 : : }
825 : 1377 : }
826 : :
827 : : void
828 : 6864 : ResolveItem::resolve_impl_item (AST::AssociatedItem &item,
829 : : const CanonicalPath &prefix,
830 : : const CanonicalPath &canonical_prefix)
831 : : {
832 : 6864 : ResolveImplItems::go (item, prefix, canonical_prefix);
833 : 6864 : }
834 : :
835 : : void
836 : 2164 : ResolveItem::resolve_extern_item (AST::ExternalItem &item)
837 : : {
838 : 2164 : ResolveExternItem::go (item, prefix, canonical_prefix);
839 : 2164 : }
840 : :
841 : : static void
842 : : flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports);
843 : : static void
844 : : flatten_rebind (const AST::UseTreeRebind &glob, std::vector<Import> &imports);
845 : : static void
846 : : flatten_list (const AST::UseTreeList &glob, std::vector<Import> &imports);
847 : :
848 : : static void
849 : 413 : flatten (const AST::UseTree *tree, std::vector<Import> &imports)
850 : : {
851 : 413 : switch (tree->get_kind ())
852 : : {
853 : 3 : case AST::UseTree::Glob: {
854 : 3 : auto glob = static_cast<const AST::UseTreeGlob *> (tree);
855 : 3 : flatten_glob (*glob, imports);
856 : 3 : break;
857 : : }
858 : 355 : case AST::UseTree::Rebind: {
859 : 355 : auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
860 : 355 : flatten_rebind (*rebind, imports);
861 : 355 : break;
862 : : }
863 : 55 : case AST::UseTree::List: {
864 : 55 : auto list = static_cast<const AST::UseTreeList *> (tree);
865 : 55 : flatten_list (*list, imports);
866 : 55 : break;
867 : : }
868 : : break;
869 : : }
870 : 413 : }
871 : :
872 : : static void
873 : 5 : flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports)
874 : : {
875 : 5 : if (glob.has_path ())
876 : 5 : imports.emplace_back (glob.get_path (), true, std::string ());
877 : 5 : }
878 : :
879 : : static void
880 : 358 : flatten_rebind (const AST::UseTreeRebind &rebind, std::vector<Import> &imports)
881 : : {
882 : 358 : auto path = rebind.get_path ();
883 : :
884 : 358 : std::string label;
885 : 358 : if (rebind.has_identifier ())
886 : 4 : label = rebind.get_identifier ().as_string ();
887 : : else
888 : 354 : label = path.get_final_segment ().as_string ();
889 : :
890 : 358 : imports.emplace_back (path, false, label);
891 : 358 : }
892 : :
893 : : static void
894 : 56 : flatten_list (const AST::UseTreeList &list, std::vector<Import> &imports)
895 : : {
896 : 56 : auto prefix = AST::SimplePath::create_empty ();
897 : 56 : if (list.has_path ())
898 : 56 : prefix = list.get_path ();
899 : :
900 : 221 : for (const auto &tree : list.get_trees ())
901 : : {
902 : : // append imports to the main list, then modify them in-place
903 : 165 : auto start_idx = imports.size ();
904 : 165 : flatten (tree.get (), imports);
905 : :
906 : 330 : for (auto import = imports.begin () + start_idx; import != imports.end ();
907 : 165 : import++)
908 : : {
909 : : // avoid duplicate node ids
910 : 165 : auto prefix_copy
911 : 165 : = AST::SimplePath ({}, prefix.has_opening_scope_resolution (),
912 : 165 : prefix.get_locus ());
913 : 488 : for (auto &seg : prefix.get_segments ())
914 : 646 : prefix_copy.get_segments ().push_back (
915 : 646 : AST::SimplePathSegment (seg.get_segment_name (),
916 : 646 : seg.get_locus ()));
917 : :
918 : 165 : import->add_prefix (std::move (prefix_copy));
919 : 165 : }
920 : : }
921 : 56 : }
922 : :
923 : : void
924 : 165 : Import::add_prefix (AST::SimplePath prefix)
925 : : {
926 : 165 : AST::SimplePath old_path (std::move (path));
927 : 165 : path = std::move (prefix);
928 : 165 : std::move (old_path.get_segments ().begin (), old_path.get_segments ().end (),
929 : : std::back_inserter (path.get_segments ()));
930 : 165 : }
931 : :
932 : : /**
933 : : * Flatten a UseDeclaration's UseTree into multiple simple paths to resolve.
934 : : *
935 : : * Given the following use declarations:
936 : : * ```
937 : : * use some::path::to_resolve; #1
938 : : * use some::path::to_glob::*; #2
939 : : * use some::path::{one, two}; #2
940 : : * ```
941 : : *
942 : : * In the first case, we simply want to return a vector with a single
943 : : * SimplePath:
944 : : * [some::path::to_resolve]
945 : : *
946 : : * In the second case, we want to resolve the glob's "origin path":
947 : : * [some::path::to_glob]
948 : : *
949 : : * Finally in the third case, we want to create two SimplePaths to resolve:
950 : : * [some::path::one, some::path::two]
951 : : */
952 : : static std::vector<Import>
953 : 248 : flatten_use_dec_to_imports (const AST::UseDeclaration &use_item)
954 : : {
955 : 0 : auto imports = std::vector<Import> ();
956 : :
957 : 248 : const auto &tree = use_item.get_tree ();
958 : 248 : flatten (tree.get (), imports);
959 : :
960 : 248 : return imports;
961 : : }
962 : :
963 : : void
964 : 248 : ResolveItem::visit (AST::UseDeclaration &use_item)
965 : : {
966 : 248 : std::vector<Import> to_resolve = flatten_use_dec_to_imports (use_item);
967 : :
968 : : // FIXME: I think this does not actually resolve glob use-decls and is going
969 : : // the wrong way about it. RFC #1560 specifies the following:
970 : : //
971 : : // > When we find a glob import, we have to record a 'back link', so that when
972 : : // a public name is added for the supplying module, we can add it for the
973 : : // importing module.
974 : : //
975 : : // Which is the opposite of what we're doing if I understand correctly?
976 : :
977 : 248 : NodeId current_module = resolver->peek_current_module_scope ();
978 : 604 : for (auto &import : to_resolve)
979 : : {
980 : 356 : auto &path = import.get_path ();
981 : :
982 : 356 : rust_debug ("resolving use-decl path: [%s]", path.as_string ().c_str ());
983 : 356 : NodeId resolved_node_id = ResolvePath::go (path);
984 : 356 : bool ok = resolved_node_id != UNKNOWN_NODEID;
985 : 356 : if (!ok)
986 : 7 : continue;
987 : :
988 : 351 : if (import.is_glob ())
989 : 2 : continue;
990 : :
991 : 349 : auto decl = CanonicalPath::new_seg (resolved_node_id, import.get_name ());
992 : 349 : mappings.insert_module_child_item (current_module, decl);
993 : :
994 : 349 : resolver->get_type_scope ().insert (decl, resolved_node_id,
995 : : path.get_locus (),
996 : : Rib::ItemType::Type);
997 : 349 : rust_debug ("use-decl rexporting: [%s]", decl.get ().c_str ());
998 : 349 : }
999 : 248 : }
1000 : :
1001 : 6864 : ResolveImplItems::ResolveImplItems (const CanonicalPath &prefix,
1002 : 6864 : const CanonicalPath &canonical_prefix)
1003 : 6864 : : ResolveItem (prefix, canonical_prefix)
1004 : 6864 : {}
1005 : :
1006 : : void
1007 : 6864 : ResolveImplItems::go (AST::AssociatedItem &item, const CanonicalPath &prefix,
1008 : : const CanonicalPath &canonical_prefix)
1009 : : {
1010 : 6864 : if (item.is_marked_for_strip ())
1011 : 0 : return;
1012 : :
1013 : 6864 : ResolveImplItems resolver (prefix, canonical_prefix);
1014 : 6864 : item.accept_vis (resolver);
1015 : 6864 : }
1016 : :
1017 : : void
1018 : 1135 : ResolveImplItems::visit (AST::TypeAlias &alias)
1019 : : {
1020 : 1135 : ResolveItem::visit (alias);
1021 : :
1022 : 1135 : resolve_visibility (alias.get_visibility ());
1023 : :
1024 : : // FIXME this stops the erronious unused decls which will be fixed later on
1025 : 1135 : resolver->get_type_scope ().append_reference_for_def (alias.get_node_id (),
1026 : : alias.get_node_id ());
1027 : 1135 : }
1028 : :
1029 : : void
1030 : 2187 : ResolveExternItem::go (AST::ExternalItem &item, const CanonicalPath &prefix,
1031 : : const CanonicalPath &canonical_prefix)
1032 : : {
1033 : 2187 : ResolveExternItem resolver (prefix, canonical_prefix);
1034 : 2187 : item.accept_vis (resolver);
1035 : 2187 : }
1036 : :
1037 : : void
1038 : 2186 : ResolveExternItem::visit (AST::Function &function)
1039 : : {
1040 : 2186 : NodeId scope_node_id = function.get_node_id ();
1041 : 2186 : auto decl
1042 : 2186 : = CanonicalPath::new_seg (function.get_node_id (),
1043 : 2186 : function.get_function_name ().as_string ());
1044 : 2186 : auto path = prefix.append (decl);
1045 : 2186 : auto cpath = canonical_prefix.append (decl);
1046 : :
1047 : 2186 : mappings.insert_canonical_path (function.get_node_id (), cpath);
1048 : :
1049 : 2186 : resolve_visibility (function.get_visibility ());
1050 : :
1051 : 2186 : resolver->get_name_scope ().push (scope_node_id);
1052 : 2186 : resolver->get_type_scope ().push (scope_node_id);
1053 : 2186 : resolver->get_label_scope ().push (scope_node_id);
1054 : 2186 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
1055 : 2186 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
1056 : 2186 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
1057 : :
1058 : : // resolve the generics
1059 : 2186 : if (function.has_generics ())
1060 : 821 : ResolveGenericParams::go (function.get_generic_params (), prefix,
1061 : : canonical_prefix);
1062 : :
1063 : 2186 : if (function.has_return_type ())
1064 : 1004 : ResolveType::go (function.get_return_type ());
1065 : :
1066 : : // we make a new scope so the names of parameters are resolved and shadowed
1067 : : // correctly
1068 : 5805 : for (auto ¶m : function.get_function_params ())
1069 : 3619 : if (!param->is_variadic ())
1070 : : {
1071 : 2675 : auto &p = static_cast<AST::FunctionParam &> (*param);
1072 : 2675 : ResolveType::go (p.get_type ());
1073 : : }
1074 : :
1075 : : // done
1076 : 2186 : resolver->get_name_scope ().pop ();
1077 : 2186 : resolver->get_type_scope ().pop ();
1078 : 2186 : resolver->get_label_scope ().pop ();
1079 : 2186 : }
1080 : :
1081 : : void
1082 : 1 : ResolveExternItem::visit (AST::ExternalStaticItem &item)
1083 : : {
1084 : 1 : resolve_visibility (item.get_visibility ());
1085 : :
1086 : 1 : ResolveType::go (item.get_type ());
1087 : 1 : }
1088 : :
1089 : : } // namespace Resolver
1090 : : } // namespace Rust
1091 : :
1092 : : #if CHECKING_P
1093 : :
1094 : : namespace selftest {
1095 : :
1096 : : static void
1097 : 1 : rust_flatten_nested_glob (void)
1098 : : {
1099 : 1 : auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION);
1100 : 1 : auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION);
1101 : 3 : auto foobar = Rust::AST::SimplePath ({foo, bar});
1102 : :
1103 : 1 : auto glob
1104 : : = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED,
1105 : 1 : foobar, UNDEF_LOCATION);
1106 : :
1107 : 1 : auto imports = std::vector<Rust::Resolver::Import> ();
1108 : 1 : Rust::Resolver::flatten_glob (glob, imports);
1109 : :
1110 : 1 : ASSERT_TRUE (!imports.empty ());
1111 : 1 : ASSERT_EQ (imports.size (), 1);
1112 : 1 : ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
1113 : 1 : ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
1114 : 1 : }
1115 : :
1116 : : static void
1117 : 1 : rust_flatten_glob (void)
1118 : : {
1119 : 1 : auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION);
1120 : :
1121 : 1 : auto glob
1122 : : = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED,
1123 : 1 : frob, UNDEF_LOCATION);
1124 : :
1125 : 1 : auto imports = std::vector<Rust::Resolver::Import> ();
1126 : 1 : Rust::Resolver::flatten_glob (glob, imports);
1127 : :
1128 : 1 : ASSERT_TRUE (!imports.empty ());
1129 : 1 : ASSERT_EQ (imports.size (), 1);
1130 : 1 : ASSERT_EQ (imports[0].get_path (), "frobulator");
1131 : 1 : }
1132 : :
1133 : : static void
1134 : 1 : rust_flatten_rebind_none (void)
1135 : : {
1136 : 1 : auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION);
1137 : 1 : auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION);
1138 : 3 : auto foobar = Rust::AST::SimplePath ({foo, bar});
1139 : :
1140 : 1 : auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE,
1141 : 1 : foobar, UNDEF_LOCATION);
1142 : :
1143 : 1 : auto imports = std::vector<Rust::Resolver::Import> ();
1144 : 1 : Rust::Resolver::flatten_rebind (rebind, imports);
1145 : :
1146 : 1 : ASSERT_TRUE (!imports.empty ());
1147 : 1 : ASSERT_EQ (imports.size (), 1);
1148 : 1 : ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
1149 : 1 : ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
1150 : 1 : }
1151 : :
1152 : : static void
1153 : 1 : rust_flatten_rebind (void)
1154 : : {
1155 : 1 : auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION);
1156 : :
1157 : 1 : auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER,
1158 : 1 : frob, UNDEF_LOCATION, {"saindoux"});
1159 : :
1160 : 1 : auto imports = std::vector<Rust::Resolver::Import> ();
1161 : 1 : Rust::Resolver::flatten_rebind (rebind, imports);
1162 : :
1163 : 1 : ASSERT_TRUE (!imports.empty ());
1164 : 1 : ASSERT_EQ (imports.size (), 1);
1165 : 1 : ASSERT_EQ (imports[0].get_path (), "frobulator");
1166 : 1 : ASSERT_EQ (imports[0].get_name (), "saindoux");
1167 : 1 : }
1168 : :
1169 : : static void
1170 : 1 : rust_flatten_rebind_nested (void)
1171 : : {
1172 : 1 : auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION);
1173 : 1 : auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION);
1174 : 1 : auto baz = Rust::AST::SimplePathSegment ("baz", UNDEF_LOCATION);
1175 : :
1176 : 4 : auto foo_bar_baz = Rust::AST::SimplePath ({foo, bar, baz});
1177 : :
1178 : 1 : auto rebind
1179 : : = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER,
1180 : 1 : foo_bar_baz, UNDEF_LOCATION, {"saindoux"});
1181 : :
1182 : 1 : auto imports = std::vector<Rust::Resolver::Import> ();
1183 : 1 : Rust::Resolver::flatten_rebind (rebind, imports);
1184 : :
1185 : 1 : ASSERT_TRUE (!imports.empty ());
1186 : 1 : ASSERT_EQ (imports.size (), 1);
1187 : 1 : ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
1188 : 1 : ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
1189 : 1 : ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz");
1190 : 1 : ASSERT_EQ (imports[0].get_name (), "saindoux");
1191 : 1 : }
1192 : :
1193 : : static void
1194 : 1 : rust_flatten_list (void)
1195 : : {
1196 : 1 : auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION);
1197 : 1 : auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION);
1198 : 3 : auto foo_bar = Rust::AST::SimplePath ({foo, bar});
1199 : :
1200 : 1 : auto baz = Rust::AST::SimplePath::from_str ("baz", UNDEF_LOCATION);
1201 : 1 : auto bul = Rust::AST::SimplePath::from_str ("bul", UNDEF_LOCATION);
1202 : :
1203 : : // use foo::bar::{baz, bul};
1204 : :
1205 : 1 : auto use0 = std::unique_ptr<Rust::AST::UseTree> (
1206 : : new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, baz,
1207 : 1 : UNDEF_LOCATION));
1208 : 1 : auto use1 = std::unique_ptr<Rust::AST::UseTree> (
1209 : : new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, bul,
1210 : 1 : UNDEF_LOCATION));
1211 : :
1212 : 1 : auto uses = std::vector<std::unique_ptr<Rust::AST::UseTree>> ();
1213 : 1 : uses.emplace_back (std::move (use0));
1214 : 1 : uses.emplace_back (std::move (use1));
1215 : :
1216 : 1 : auto list
1217 : : = Rust::AST::UseTreeList (Rust::AST::UseTreeList::PATH_PREFIXED, foo_bar,
1218 : 1 : std::move (uses), UNDEF_LOCATION);
1219 : :
1220 : 1 : auto imports = std::vector<Rust::Resolver::Import> ();
1221 : 1 : Rust::Resolver::flatten_list (list, imports);
1222 : :
1223 : 1 : ASSERT_TRUE (!imports.empty ());
1224 : 1 : ASSERT_EQ (imports.size (), 2);
1225 : 1 : ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
1226 : 1 : ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
1227 : 1 : ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz");
1228 : 1 : ASSERT_EQ (imports[1].get_path ().get_segments ()[0].as_string (), "foo");
1229 : 1 : ASSERT_EQ (imports[1].get_path ().get_segments ()[1].as_string (), "bar");
1230 : 1 : ASSERT_EQ (imports[1].get_path ().get_segments ()[2].as_string (), "bul");
1231 : 1 : }
1232 : :
1233 : : static void
1234 : 1 : rust_use_dec_flattening (void)
1235 : : {
1236 : 1 : rust_flatten_glob ();
1237 : 1 : rust_flatten_nested_glob ();
1238 : 1 : rust_flatten_rebind_none ();
1239 : 1 : rust_flatten_rebind ();
1240 : 1 : rust_flatten_rebind_nested ();
1241 : 1 : rust_flatten_list ();
1242 : 1 : }
1243 : :
1244 : : void
1245 : 1 : rust_simple_path_resolve_test (void)
1246 : : {
1247 : 1 : rust_use_dec_flattening ();
1248 : 1 : }
1249 : :
1250 : : } // namespace selftest
1251 : :
1252 : : #endif // CHECKING_P
|