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