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