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