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