Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #include "rust-expand-visitor.h"
20 : : #include "rust-ast-fragment.h"
21 : : #include "rust-proc-macro.h"
22 : : #include "rust-attributes.h"
23 : : #include "rust-ast.h"
24 : : #include "rust-type.h"
25 : : #include "rust-derive.h"
26 : :
27 : : namespace Rust {
28 : :
29 : : bool
30 : 5594 : is_builtin (AST::Attribute &attr)
31 : : {
32 : 5594 : auto &segments = attr.get_path ().get_segments ();
33 : 5594 : return !segments.empty ()
34 : 5594 : && !Analysis::BuiltinAttributeMappings::get ()
35 : 5594 : ->lookup_builtin (segments[0].get_segment_name ())
36 : 5594 : .is_error ();
37 : : }
38 : :
39 : : /* Expand all of the macro invocations currently contained in a crate */
40 : : void
41 : 8686 : ExpandVisitor::go (AST::Crate &crate)
42 : : {
43 : 8686 : visit (crate);
44 : 8686 : }
45 : :
46 : : static std::vector<std::unique_ptr<AST::Item>>
47 : 128 : builtin_derive_item (AST::Item &item, const AST::Attribute &derive,
48 : : BuiltinMacro to_derive)
49 : : {
50 : 0 : return AST::DeriveVisitor::derive (item, derive, to_derive);
51 : : }
52 : :
53 : : static std::vector<std::unique_ptr<AST::Item>>
54 : 0 : derive_item (AST::Item &item, AST::SimplePath &to_derive,
55 : : MacroExpander &expander)
56 : : {
57 : 0 : std::vector<std::unique_ptr<AST::Item>> result;
58 : 0 : auto frag = expander.expand_derive_proc_macro (item, to_derive);
59 : 0 : if (!frag.is_error ())
60 : : {
61 : 0 : for (auto &node : frag.get_nodes ())
62 : : {
63 : 0 : switch (node.get_kind ())
64 : : {
65 : 0 : case AST::SingleASTNode::ITEM:
66 : 0 : result.push_back (node.take_item ());
67 : 0 : break;
68 : 0 : default:
69 : 0 : rust_unreachable ();
70 : : }
71 : : }
72 : : }
73 : 0 : return result;
74 : 0 : }
75 : :
76 : : static std::vector<std::unique_ptr<AST::Item>>
77 : 0 : expand_item_attribute (AST::Item &item, AST::SimplePath &name,
78 : : MacroExpander &expander)
79 : : {
80 : 0 : std::vector<std::unique_ptr<AST::Item>> result;
81 : 0 : auto frag = expander.expand_attribute_proc_macro (item, name);
82 : 0 : if (!frag.is_error ())
83 : : {
84 : 0 : for (auto &node : frag.get_nodes ())
85 : : {
86 : 0 : switch (node.get_kind ())
87 : : {
88 : 0 : case AST::SingleASTNode::ITEM:
89 : 0 : result.push_back (node.take_item ());
90 : 0 : break;
91 : 0 : default:
92 : 0 : rust_unreachable ();
93 : : }
94 : : }
95 : : }
96 : 0 : return result;
97 : 0 : }
98 : :
99 : : /* Helper function to expand a given attribute on a statement and collect back
100 : : * statements.
101 : : * T should be anything that can be used as a statement accepting outer
102 : : * attributes.
103 : : */
104 : : template <typename T>
105 : : static std::vector<std::unique_ptr<AST::Stmt>>
106 : 0 : expand_stmt_attribute (T &statement, AST::SimplePath &attribute,
107 : : MacroExpander &expander)
108 : : {
109 : 0 : std::vector<std::unique_ptr<AST::Stmt>> result;
110 : 0 : auto frag = expander.expand_attribute_proc_macro (statement, attribute);
111 : 0 : if (!frag.is_error ())
112 : : {
113 : 0 : for (auto &node : frag.get_nodes ())
114 : : {
115 : 0 : switch (node.get_kind ())
116 : : {
117 : 0 : case AST::SingleASTNode::STMT:
118 : 0 : result.push_back (node.take_stmt ());
119 : : break;
120 : 0 : default:
121 : 0 : rust_unreachable ();
122 : : }
123 : : }
124 : : }
125 : 0 : return result;
126 : 0 : }
127 : :
128 : : void
129 : 31147 : expand_tail_expr (AST::BlockExpr &block_expr, MacroExpander &expander)
130 : : {
131 : 31147 : if (block_expr.has_tail_expr ())
132 : : {
133 : 22803 : auto tail = block_expr.take_tail_expr ();
134 : 22803 : auto attrs = tail->get_outer_attrs ();
135 : 22803 : bool changed = false;
136 : 23405 : for (auto it = attrs.begin (); it != attrs.end ();)
137 : : {
138 : 602 : auto current = *it;
139 : 602 : if (is_builtin (current))
140 : : {
141 : 602 : it++;
142 : : }
143 : : else
144 : : {
145 : 0 : it = attrs.erase (it);
146 : 0 : changed = true;
147 : 0 : auto new_stmts
148 : : = expand_stmt_attribute (block_expr, current.get_path (),
149 : 0 : expander);
150 : 0 : auto &stmts = block_expr.get_statements ();
151 : 0 : std::move (new_stmts.begin (), new_stmts.end (),
152 : : std::inserter (stmts, stmts.end ()));
153 : 0 : }
154 : 602 : }
155 : 22803 : if (changed)
156 : 0 : block_expr.normalize_tail_expr ();
157 : : else
158 : 22803 : block_expr.set_tail_expr (std::move (tail));
159 : 22803 : }
160 : 31147 : }
161 : :
162 : : void
163 : 10498 : ExpandVisitor::expand_inner_items (
164 : : std::vector<std::unique_ptr<AST::Item>> &items)
165 : : {
166 : 10498 : expander.push_context (MacroExpander::ContextType::ITEM);
167 : :
168 : 48166 : for (auto it = items.begin (); it != items.end (); it++)
169 : : {
170 : 37668 : Rust::AST::Item &item = **it;
171 : 37668 : if (item.has_outer_attrs ())
172 : : {
173 : 4861 : auto &attrs = item.get_outer_attrs ();
174 : :
175 : 9958 : for (auto attr_it = attrs.begin (); attr_it != attrs.end ();
176 : : /* erase => No increment*/)
177 : : {
178 : 5097 : auto current = *attr_it;
179 : :
180 : 5097 : if (current.is_derive ())
181 : : {
182 : 117 : current.parse_attr_to_meta_item ();
183 : 117 : attr_it = attrs.erase (attr_it);
184 : : // Get traits to derive in the current attribute
185 : 117 : auto traits_to_derive = current.get_traits_to_derive ();
186 : 245 : for (auto &to_derive : traits_to_derive)
187 : : {
188 : 128 : auto maybe_builtin = MacroBuiltin::builtins.lookup (
189 : 128 : to_derive.get ().as_string ());
190 : 128 : if (maybe_builtin.has_value ())
191 : : {
192 : 128 : auto new_items
193 : : = builtin_derive_item (item, current,
194 : 128 : maybe_builtin.value ());
195 : :
196 : 289 : for (auto &&new_item : new_items)
197 : 161 : it = items.insert (it, std::move (new_item));
198 : 128 : }
199 : : else
200 : : {
201 : : // Macro is not a builtin, so it must be a
202 : : // user-defined derive macro.
203 : 0 : auto new_items
204 : 0 : = derive_item (item, to_derive, expander);
205 : 0 : std::move (new_items.begin (), new_items.end (),
206 : : std::inserter (items, it));
207 : 0 : }
208 : : }
209 : 117 : }
210 : : else /* Attribute */
211 : : {
212 : 4980 : if (is_builtin (current))
213 : : {
214 : 4980 : attr_it++;
215 : : }
216 : : else
217 : : {
218 : 0 : attr_it = attrs.erase (attr_it);
219 : 0 : auto new_items
220 : : = expand_item_attribute (item, current.get_path (),
221 : 0 : expander);
222 : 0 : it = items.erase (it);
223 : 0 : std::move (new_items.begin (), new_items.end (),
224 : : std::inserter (items, it));
225 : : // TODO: Improve this ?
226 : : // item is invalid since it refers to now deleted,
227 : : // cancel the loop increment and break.
228 : 0 : it--;
229 : 0 : break;
230 : 0 : }
231 : : }
232 : 5097 : }
233 : : }
234 : : }
235 : :
236 : 10498 : std::function<std::unique_ptr<AST::Item> (AST::SingleASTNode)> extractor
237 : 2913 : = [] (AST::SingleASTNode node) { return node.take_item (); };
238 : :
239 : 10498 : expand_macro_children (items, extractor);
240 : :
241 : 10498 : expander.pop_context ();
242 : 10498 : }
243 : :
244 : : void
245 : 31147 : ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr)
246 : : {
247 : 31147 : auto &stmts = expr.get_statements ();
248 : 31147 : expander.push_context (MacroExpander::ContextType::STMT);
249 : :
250 : 59470 : for (auto it = stmts.begin (); it != stmts.end (); it++)
251 : : {
252 : 28323 : auto &stmt = *it;
253 : :
254 : : // skip all non-item statements
255 : 28323 : if (stmt->get_stmt_kind () != AST::Stmt::Kind::Item)
256 : 26969 : continue;
257 : :
258 : 1354 : auto &item = static_cast<AST::Item &> (*stmt.get ());
259 : :
260 : 1354 : if (item.has_outer_attrs ())
261 : : {
262 : 12 : auto &attrs = item.get_outer_attrs ();
263 : :
264 : 24 : for (auto attr_it = attrs.begin (); attr_it != attrs.end ();
265 : : /* erase => No increment*/)
266 : : {
267 : 12 : auto current = *attr_it;
268 : :
269 : 12 : if (current.is_derive ())
270 : : {
271 : 0 : attr_it = attrs.erase (attr_it);
272 : : // Get traits to derive in the current attribute
273 : 0 : auto traits_to_derive = current.get_traits_to_derive ();
274 : 0 : for (auto &to_derive : traits_to_derive)
275 : : {
276 : 0 : auto maybe_builtin = MacroBuiltin::builtins.lookup (
277 : 0 : to_derive.get ().as_string ());
278 : 0 : if (maybe_builtin.has_value ())
279 : : {
280 : 0 : auto new_items
281 : : = builtin_derive_item (item, current,
282 : 0 : maybe_builtin.value ());
283 : :
284 : : // this inserts the derive *before* the item - is it a
285 : : // problem?
286 : 0 : for (auto &&new_item : new_items)
287 : 0 : it = stmts.insert (it, std::move (new_item));
288 : 0 : }
289 : : else
290 : : {
291 : 0 : auto new_items
292 : 0 : = derive_item (item, to_derive, expander);
293 : 0 : std::move (new_items.begin (), new_items.end (),
294 : : std::inserter (stmts, it));
295 : 0 : }
296 : : }
297 : 0 : }
298 : : else /* Attribute */
299 : : {
300 : 12 : if (is_builtin (current))
301 : : {
302 : 12 : attr_it++;
303 : : }
304 : : else
305 : : {
306 : 0 : attr_it = attrs.erase (attr_it);
307 : 0 : auto new_items
308 : : = expand_stmt_attribute (item, current.get_path (),
309 : 0 : expander);
310 : 0 : it = stmts.erase (it);
311 : 0 : std::move (new_items.begin (), new_items.end (),
312 : : std::inserter (stmts, it));
313 : : // TODO: Improve this ?
314 : : // item is invalid since it refers to now deleted,
315 : : // cancel the loop increment and break.
316 : 0 : it--;
317 : 0 : break;
318 : 0 : }
319 : : }
320 : 12 : }
321 : : }
322 : : }
323 : :
324 : 31147 : if (!expr.has_tail_expr ())
325 : 8364 : expr.normalize_tail_expr ();
326 : :
327 : 31147 : std::function<std::unique_ptr<AST::Stmt> (AST::SingleASTNode)> extractor
328 : 492 : = [] (AST::SingleASTNode node) { return node.take_stmt (); };
329 : :
330 : 31147 : expand_macro_children (stmts, extractor);
331 : :
332 : 31147 : expander.pop_context ();
333 : 31147 : }
334 : :
335 : : void
336 : 2187552 : ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
337 : : {
338 : 2187552 : expander.push_context (MacroExpander::ContextType::EXPR);
339 : 2187552 : expr->accept_vis (*this);
340 : 2187552 : expander.pop_context ();
341 : :
342 : 2187552 : auto final_fragment = expander.take_expanded_fragment ();
343 : 2187552 : if (final_fragment.should_expand ()
344 : 2187552 : && final_fragment.is_expression_fragment ())
345 : 2839 : expr = final_fragment.take_expression_fragment ();
346 : 2187552 : }
347 : :
348 : : void
349 : 56206 : ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
350 : : {
351 : 56206 : expander.push_context (MacroExpander::ContextType::TYPE);
352 : :
353 : 56206 : type->accept_vis (*this);
354 : 56206 : auto final_fragment = expander.take_expanded_fragment ();
355 : 56206 : if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
356 : 33 : type = final_fragment.take_type_fragment ();
357 : :
358 : 56206 : expander.pop_context ();
359 : 56206 : }
360 : :
361 : : // FIXME: Can this be refactored into a `scoped` method? Which takes a
362 : : // ContextType as parameter and a lambda? And maybe just an std::vector<T>&?
363 : : void
364 : 2146 : ExpandVisitor::expand_struct_fields (std::vector<AST::StructField> &fields)
365 : : {
366 : 4886 : for (auto &field : fields)
367 : : {
368 : 2740 : maybe_expand_type (field.get_field_type_ptr ());
369 : : }
370 : 2146 : }
371 : :
372 : : void
373 : 1973 : ExpandVisitor::expand_tuple_fields (std::vector<AST::TupleField> &fields)
374 : : {
375 : 5140 : for (auto &field : fields)
376 : 3167 : maybe_expand_type (field.get_field_type_ptr ());
377 : 1973 : }
378 : :
379 : : // FIXME: This can definitely be refactored with the method above
380 : : void
381 : 27592 : ExpandVisitor::expand_function_params (
382 : : std::vector<std::unique_ptr<AST::Param>> ¶ms)
383 : : {
384 : 53855 : for (auto &p : params)
385 : 26263 : visit (p);
386 : 27592 : }
387 : :
388 : : void
389 : 5547 : ExpandVisitor::expand_generic_args (AST::GenericArgs &args)
390 : : {
391 : 11376 : for (auto &arg : args.get_generic_args ())
392 : : {
393 : 5829 : switch (arg.get_kind ())
394 : : {
395 : 2325 : case AST::GenericArg::Kind::Type:
396 : 2325 : maybe_expand_type (arg.get_type_ptr ());
397 : 2325 : break;
398 : 67 : case AST::GenericArg::Kind::Const:
399 : 67 : maybe_expand_expr (arg.get_expression_ptr ());
400 : 67 : break;
401 : : default:
402 : : break;
403 : : // FIXME: Figure out what to do here if there is ambiguity. Since the
404 : : // resolver comes after the expansion, we need to figure out a way to
405 : : // strip ambiguous values here
406 : : // TODO: ARTHUR: Probably add a `mark_as_strip` method to `GenericArg`
407 : : // or something. This would clean up this whole thing
408 : : }
409 : : }
410 : :
411 : : // FIXME: Can we have macro invocations in generic type bindings?
412 : : // expand binding args - strip sub-types only
413 : : // FIXME: ARTHUR: This needs a test! Foo<Item = macro!()>
414 : 5690 : for (auto &binding : args.get_binding_args ())
415 : 143 : maybe_expand_type (binding.get_type_ptr ());
416 : 5547 : }
417 : :
418 : : void
419 : 825 : ExpandVisitor::expand_qualified_path_type (AST::QualifiedPathType &path_type)
420 : : {
421 : 825 : maybe_expand_type (path_type.get_type_ptr ());
422 : :
423 : : // FIXME: ARTHUR: Can we do macro expansion in there? Needs a test!
424 : 825 : if (path_type.has_as_clause ())
425 : 749 : path_type.get_as_type_path ().accept_vis (*this);
426 : 825 : }
427 : :
428 : : void
429 : 72 : ExpandVisitor::expand_closure_params (std::vector<AST::ClosureParam> ¶ms)
430 : : {
431 : 139 : for (auto ¶m : params)
432 : : {
433 : 67 : if (param.has_type_given ())
434 : 55 : maybe_expand_type (param.get_type_ptr ());
435 : : }
436 : 72 : }
437 : :
438 : : void
439 : 202 : ExpandVisitor::expand_where_clause (AST::WhereClause &where_clause)
440 : : {
441 : 413 : for (auto &item : where_clause.get_items ())
442 : 211 : visit (item);
443 : 202 : }
444 : :
445 : : void
446 : 8686 : ExpandVisitor::visit (AST::Crate &crate)
447 : : {
448 : 8686 : expand_inner_items (crate.items);
449 : 8686 : }
450 : :
451 : : void
452 : 0 : ExpandVisitor::visit (AST::DelimTokenTree &)
453 : 0 : {}
454 : :
455 : : void
456 : 0 : ExpandVisitor::visit (AST::AttrInputMetaItemContainer &)
457 : 0 : {}
458 : :
459 : : void
460 : 29158 : ExpandVisitor::visit (AST::IdentifierExpr &ident_expr)
461 : 29158 : {}
462 : :
463 : : void
464 : 618 : ExpandVisitor::visit (AST::LifetimeParam &)
465 : 618 : {}
466 : :
467 : : void
468 : 85 : ExpandVisitor::visit (AST::ConstGenericParam &)
469 : 85 : {}
470 : :
471 : : void
472 : 3906 : ExpandVisitor::visit (AST::MacroInvocation ¯o_invoc)
473 : : {
474 : : // TODO: Can we do the AST fragment replacing here? Probably not, right?
475 : 6806 : expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ()
476 : : ? AST::InvocKind::Semicoloned
477 : : : AST::InvocKind::Expr);
478 : 3906 : }
479 : :
480 : : void
481 : 27496 : ExpandVisitor::visit (AST::PathInExpression &path)
482 : : {
483 : 27496 : if (!path.is_lang_item ())
484 : 65778 : for (auto &segment : path.get_segments ())
485 : 76638 : if (segment.has_generic_args ())
486 : 1518 : expand_generic_args (segment.get_generic_args ());
487 : 27496 : }
488 : :
489 : : void
490 : 4032 : ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment)
491 : : {
492 : 4032 : if (segment.has_generic_args ())
493 : 4029 : expand_generic_args (segment.get_generic_args ());
494 : 4032 : }
495 : :
496 : : void
497 : 38 : ExpandVisitor::visit (AST::TypePathSegmentFunction &segment)
498 : : {
499 : 38 : auto &type_path_function = segment.get_type_path_function ();
500 : :
501 : 82 : for (auto &type : type_path_function.get_params ())
502 : 44 : visit (type);
503 : :
504 : 38 : if (type_path_function.has_return_type ())
505 : 32 : maybe_expand_type (type_path_function.get_return_type_ptr ());
506 : 38 : }
507 : :
508 : : void
509 : 184 : ExpandVisitor::visit (AST::QualifiedPathInExpression &path)
510 : : {
511 : 184 : expand_qualified_path_type (path.get_qualified_path_type ());
512 : :
513 : 368 : for (auto &segment : path.get_segments ())
514 : 368 : if (segment.has_generic_args ())
515 : 0 : expand_generic_args (segment.get_generic_args ());
516 : 184 : }
517 : :
518 : : void
519 : 641 : ExpandVisitor::visit (AST::QualifiedPathInType &path)
520 : : {
521 : 641 : expand_qualified_path_type (path.get_qualified_path_type ());
522 : :
523 : : // this shouldn't strip any segments, but can strip inside them
524 : 641 : for (auto &segment : path.get_segments ())
525 : 0 : visit (segment);
526 : 641 : }
527 : :
528 : : void
529 : 1068285 : ExpandVisitor::visit (AST::LiteralExpr &expr)
530 : 1068285 : {}
531 : :
532 : : void
533 : 0 : ExpandVisitor::visit (AST::AttrInputLiteral &)
534 : 0 : {}
535 : :
536 : : void
537 : 0 : ExpandVisitor::visit (AST::AttrInputMacro ¯o)
538 : : {
539 : 0 : rust_sorry_at (UNDEF_LOCATION, "macros in attributes not supported");
540 : 0 : }
541 : :
542 : : void
543 : 0 : ExpandVisitor::visit (AST::MetaItemLitExpr &)
544 : 0 : {}
545 : :
546 : : void
547 : 0 : ExpandVisitor::visit (AST::MetaItemPathLit &)
548 : 0 : {}
549 : :
550 : : void
551 : 3 : ExpandVisitor::visit (AST::ErrorPropagationExpr &expr)
552 : : {
553 : 3 : visit (expr.get_propagating_expr ());
554 : 3 : }
555 : :
556 : : void
557 : 1052648 : ExpandVisitor::visit (AST::ArithmeticOrLogicalExpr &expr)
558 : : {
559 : 1052648 : maybe_expand_expr (expr.get_left_expr_ptr ());
560 : 1052648 : maybe_expand_expr (expr.get_right_expr_ptr ());
561 : 1052648 : }
562 : :
563 : : void
564 : 1597 : ExpandVisitor::visit (AST::ComparisonExpr &expr)
565 : : {
566 : 1597 : maybe_expand_expr (expr.get_left_expr_ptr ());
567 : 1597 : maybe_expand_expr (expr.get_right_expr_ptr ());
568 : 1597 : }
569 : :
570 : : void
571 : 387 : ExpandVisitor::visit (AST::LazyBooleanExpr &expr)
572 : : {
573 : 387 : maybe_expand_expr (expr.get_left_expr_ptr ());
574 : 387 : maybe_expand_expr (expr.get_right_expr_ptr ());
575 : 387 : }
576 : :
577 : : void
578 : 2426 : ExpandVisitor::visit (AST::AssignmentExpr &expr)
579 : : {
580 : 2426 : maybe_expand_expr (expr.get_left_expr_ptr ());
581 : 2426 : maybe_expand_expr (expr.get_right_expr_ptr ());
582 : 2426 : }
583 : :
584 : : void
585 : 354 : ExpandVisitor::visit (AST::CompoundAssignmentExpr &expr)
586 : : {
587 : 354 : maybe_expand_expr (expr.get_left_expr_ptr ());
588 : 354 : maybe_expand_expr (expr.get_right_expr_ptr ());
589 : 354 : }
590 : :
591 : : void
592 : 371 : ExpandVisitor::visit (AST::GroupedExpr &expr)
593 : : {
594 : 371 : maybe_expand_expr (expr.get_expr_in_parens_ptr ());
595 : 371 : }
596 : :
597 : : void
598 : 76 : ExpandVisitor::visit (AST::StructExprStruct &expr)
599 : 76 : {}
600 : :
601 : : void
602 : 15364 : ExpandVisitor::visit (AST::CallExpr &expr)
603 : : {
604 : 15364 : visit (expr.get_function_expr ());
605 : :
606 : 34464 : for (auto ¶m : expr.get_params ())
607 : 19100 : maybe_expand_expr (param);
608 : 15364 : }
609 : :
610 : : void
611 : 2327 : ExpandVisitor::visit (AST::MethodCallExpr &expr)
612 : : {
613 : 2327 : visit (expr.get_receiver_expr ());
614 : :
615 : 3564 : for (auto ¶m : expr.get_params ())
616 : 1237 : maybe_expand_expr (param);
617 : 2327 : }
618 : :
619 : : void
620 : 38 : ExpandVisitor::visit (AST::ClosureExprInner &expr)
621 : : {
622 : 38 : expand_closure_params (expr.get_params ());
623 : :
624 : 38 : visit (expr.get_definition_expr ());
625 : 38 : }
626 : :
627 : : void
628 : 31147 : ExpandVisitor::visit (AST::BlockExpr &expr)
629 : : {
630 : 31147 : expand_inner_stmts (expr);
631 : :
632 : 31147 : expand_tail_expr (expr, expander);
633 : 31147 : if (expr.has_tail_expr ())
634 : 22803 : maybe_expand_expr (expr.get_tail_expr_ptr ());
635 : 31147 : }
636 : :
637 : : void
638 : 34 : ExpandVisitor::visit (AST::ClosureExprInnerTyped &expr)
639 : : {
640 : 34 : expand_closure_params (expr.get_params ());
641 : :
642 : 34 : maybe_expand_type (expr.get_return_type_ptr ());
643 : :
644 : 34 : visit (expr.get_definition_block ());
645 : 34 : }
646 : :
647 : : void
648 : 18 : ExpandVisitor::visit (AST::ContinueExpr &expr)
649 : 18 : {}
650 : :
651 : : void
652 : 566 : ExpandVisitor::visit (AST::IfExpr &expr)
653 : : {
654 : 566 : maybe_expand_expr (expr.get_condition_expr_ptr ());
655 : :
656 : 566 : visit (expr.get_if_block ());
657 : 566 : }
658 : :
659 : : void
660 : 968 : ExpandVisitor::visit (AST::IfExprConseqElse &expr)
661 : : {
662 : 968 : maybe_expand_expr (expr.get_condition_expr_ptr ());
663 : :
664 : 968 : visit (expr.get_if_block ());
665 : 968 : visit (expr.get_else_block ());
666 : 968 : }
667 : :
668 : : void
669 : 22 : ExpandVisitor::visit (AST::IfLetExpr &expr)
670 : : {
671 : 22 : maybe_expand_expr (expr.get_value_expr_ptr ());
672 : :
673 : 22 : visit (expr.get_if_block ());
674 : 22 : }
675 : :
676 : : void
677 : 20 : ExpandVisitor::visit (AST::IfLetExprConseqElse &expr)
678 : : {
679 : 20 : maybe_expand_expr (expr.get_value_expr_ptr ());
680 : :
681 : 20 : visit (expr.get_if_block ());
682 : 20 : visit (expr.get_else_block ());
683 : 20 : }
684 : :
685 : : void
686 : 630 : ExpandVisitor::visit (AST::MatchExpr &expr)
687 : : {
688 : 630 : visit (expr.get_scrutinee_expr ());
689 : :
690 : 2030 : for (auto &match_case : expr.get_match_cases ())
691 : : {
692 : 1400 : auto &arm = match_case.get_arm ();
693 : :
694 : 2800 : for (auto &pattern : arm.get_patterns ())
695 : 1400 : visit (pattern);
696 : :
697 : 1400 : if (arm.has_match_arm_guard ())
698 : 4 : maybe_expand_expr (arm.get_guard_expr_ptr ());
699 : :
700 : 1400 : maybe_expand_expr (match_case.get_expr_ptr ());
701 : : }
702 : 630 : }
703 : :
704 : : void
705 : 6894 : ExpandVisitor::visit (AST::TypeParam ¶m)
706 : : {
707 : 7645 : for (auto &bound : param.get_type_param_bounds ())
708 : 751 : visit (bound);
709 : :
710 : 6894 : if (param.has_type ())
711 : 321 : maybe_expand_type (param.get_type_ptr ());
712 : 6894 : }
713 : :
714 : : void
715 : 2 : ExpandVisitor::visit (AST::LifetimeWhereClauseItem &)
716 : 2 : {}
717 : :
718 : : void
719 : 209 : ExpandVisitor::visit (AST::TypeBoundWhereClauseItem &item)
720 : : {
721 : 209 : maybe_expand_type (item.get_type_ptr ());
722 : :
723 : 418 : for (auto &bound : item.get_type_param_bounds ())
724 : 209 : visit (bound);
725 : 209 : }
726 : :
727 : : void
728 : 1812 : ExpandVisitor::visit (AST::Module &module)
729 : : {
730 : 1812 : expand_inner_items (module.get_items ());
731 : 1812 : }
732 : :
733 : : void
734 : 24 : ExpandVisitor::visit (AST::ExternCrate &crate)
735 : 24 : {}
736 : :
737 : : void
738 : 0 : ExpandVisitor::visit (AST::UseTreeGlob &)
739 : 0 : {}
740 : :
741 : : void
742 : 0 : ExpandVisitor::visit (AST::UseTreeList &)
743 : 0 : {}
744 : :
745 : : void
746 : 0 : ExpandVisitor::visit (AST::UseTreeRebind &)
747 : 0 : {}
748 : :
749 : : void
750 : 681 : ExpandVisitor::visit (AST::UseDeclaration &use_decl)
751 : 681 : {}
752 : :
753 : : void
754 : 27592 : ExpandVisitor::visit (AST::Function &function)
755 : : {
756 : 27592 : if (function.has_body ())
757 : 21652 : visit_inner_using_attrs (
758 : 21652 : function, function.get_definition ().value ()->get_inner_attrs ());
759 : 30782 : for (auto ¶m : function.get_generic_params ())
760 : 3190 : visit (param);
761 : :
762 : 27592 : expand_function_params (function.get_function_params ());
763 : :
764 : 27592 : if (function.has_return_type ())
765 : 19378 : maybe_expand_type (function.get_return_type_ptr ());
766 : :
767 : 27592 : if (function.has_where_clause ())
768 : 34 : expand_where_clause (function.get_where_clause ());
769 : :
770 : 27592 : if (function.has_body ())
771 : 21652 : visit (*function.get_definition ());
772 : 27592 : }
773 : :
774 : : void
775 : 1910 : ExpandVisitor::visit (AST::StructStruct &struct_item)
776 : : {
777 : 2455 : for (auto &generic : struct_item.get_generic_params ())
778 : 545 : visit (generic);
779 : :
780 : 1910 : if (struct_item.has_where_clause ())
781 : 6 : expand_where_clause (struct_item.get_where_clause ());
782 : :
783 : 1910 : expand_struct_fields (struct_item.get_fields ());
784 : 1910 : }
785 : :
786 : : void
787 : 1288 : ExpandVisitor::visit (AST::TupleStruct &tuple_struct)
788 : : {
789 : 1815 : for (auto &generic : tuple_struct.get_generic_params ())
790 : 527 : visit (generic);
791 : :
792 : 1288 : if (tuple_struct.has_where_clause ())
793 : 0 : expand_where_clause (tuple_struct.get_where_clause ());
794 : :
795 : 1288 : expand_tuple_fields (tuple_struct.get_fields ());
796 : 1288 : }
797 : :
798 : : void
799 : 574 : ExpandVisitor::visit (AST::EnumItem &item)
800 : 574 : {}
801 : :
802 : : void
803 : 685 : ExpandVisitor::visit (AST::EnumItemTuple &item)
804 : : {
805 : 685 : expand_tuple_fields (item.get_tuple_fields ());
806 : 685 : }
807 : :
808 : : void
809 : 106 : ExpandVisitor::visit (AST::EnumItemStruct &item)
810 : : {
811 : 106 : expand_struct_fields (item.get_struct_fields ());
812 : 106 : }
813 : :
814 : : void
815 : 49 : ExpandVisitor::visit (AST::EnumItemDiscriminant &item)
816 : : {
817 : 49 : maybe_expand_expr (item.get_expr_ptr ());
818 : 49 : }
819 : :
820 : : void
821 : 130 : ExpandVisitor::visit (AST::Union &union_item)
822 : : {
823 : 207 : for (auto &generic : union_item.get_generic_params ())
824 : 77 : visit (generic);
825 : :
826 : 130 : expand_struct_fields (union_item.get_variants ());
827 : 130 : }
828 : :
829 : : void
830 : 689 : ExpandVisitor::visit (AST::ConstantItem &const_item)
831 : : {
832 : 689 : maybe_expand_type (const_item.get_type_ptr ());
833 : :
834 : 689 : if (const_item.has_expr ())
835 : 683 : maybe_expand_expr (const_item.get_expr_ptr ());
836 : 689 : }
837 : :
838 : : void
839 : 86 : ExpandVisitor::visit (AST::StaticItem &static_item)
840 : : {
841 : 86 : maybe_expand_type (static_item.get_type_ptr ());
842 : :
843 : 86 : maybe_expand_expr (static_item.get_expr_ptr ());
844 : 86 : }
845 : :
846 : : void
847 : 73 : ExpandVisitor::visit (AST::TraitItemConst &const_item)
848 : : {
849 : 73 : maybe_expand_type (const_item.get_type_ptr ());
850 : :
851 : 73 : if (const_item.has_expr ())
852 : 19 : maybe_expand_expr (const_item.get_expr_ptr ());
853 : 73 : }
854 : :
855 : : void
856 : 4653 : ExpandVisitor::visit (AST::Trait &trait)
857 : : {
858 : 5480 : for (auto &generic : trait.get_generic_params ())
859 : 827 : visit (generic);
860 : :
861 : 5385 : for (auto &bound : trait.get_type_param_bounds ())
862 : 732 : visit (bound);
863 : :
864 : 4653 : if (trait.has_where_clause ())
865 : 17 : expand_where_clause (trait.get_where_clause ());
866 : :
867 : 4653 : expander.push_context (MacroExpander::ContextType::TRAIT);
868 : :
869 : 4653 : std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)>
870 : : extractor
871 : 4 : = [] (AST::SingleASTNode node) { return node.take_assoc_item (); };
872 : :
873 : 4653 : expand_macro_children (MacroExpander::ContextType::TRAIT,
874 : : trait.get_trait_items (), extractor);
875 : :
876 : 4653 : expander.pop_context ();
877 : 4653 : }
878 : :
879 : : void
880 : 1442 : ExpandVisitor::visit (AST::InherentImpl &impl)
881 : : {
882 : 2884 : visit_inner_attrs (impl);
883 : : // just expand sub-stuff - can't actually strip generic params themselves
884 : 1946 : for (auto &generic : impl.get_generic_params ())
885 : 504 : visit (generic);
886 : :
887 : : // FIXME: Is that correct? How do we test that?
888 : 1442 : expander.push_context (MacroExpander::ContextType::ITEM);
889 : :
890 : 1442 : maybe_expand_type (impl.get_type_ptr ());
891 : :
892 : 1442 : expander.pop_context ();
893 : :
894 : 1442 : if (impl.has_where_clause ())
895 : 3 : expand_where_clause (impl.get_where_clause ());
896 : :
897 : 1442 : std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)>
898 : : extractor
899 : 4 : = [] (AST::SingleASTNode node) { return node.take_assoc_item (); };
900 : :
901 : 1442 : expand_macro_children (MacroExpander::ContextType::IMPL,
902 : : impl.get_impl_items (), extractor);
903 : 1442 : }
904 : :
905 : : void
906 : 6330 : ExpandVisitor::visit (AST::TraitImpl &impl)
907 : : {
908 : 12660 : visit_inner_attrs (impl);
909 : : // just expand sub-stuff - can't actually strip generic params themselves
910 : 7762 : for (auto ¶m : impl.get_generic_params ())
911 : 1432 : visit (param);
912 : :
913 : : // FIXME: Is that correct? How do we test that?
914 : 6330 : expander.push_context (MacroExpander::ContextType::ITEM);
915 : :
916 : 6330 : maybe_expand_type (impl.get_type_ptr ());
917 : :
918 : 6330 : expander.pop_context ();
919 : :
920 : 6330 : visit (impl.get_trait_path ());
921 : :
922 : 6330 : if (impl.has_where_clause ())
923 : 142 : expand_where_clause (impl.get_where_clause ());
924 : :
925 : 6330 : std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)>
926 : : extractor
927 : 115 : = [] (AST::SingleASTNode node) { return node.take_assoc_item (); };
928 : :
929 : 6330 : expand_macro_children (MacroExpander::ContextType::TRAIT_IMPL,
930 : : impl.get_impl_items (), extractor);
931 : 6330 : }
932 : :
933 : : void
934 : 3 : ExpandVisitor::visit (AST::ExternalTypeItem &item)
935 : 3 : {}
936 : :
937 : : void
938 : 3 : ExpandVisitor::visit (AST::ExternalStaticItem &static_item)
939 : : {
940 : 3 : maybe_expand_type (static_item.get_type_ptr ());
941 : 3 : }
942 : :
943 : : void
944 : 1788 : ExpandVisitor::visit (AST::ExternBlock &block)
945 : : {
946 : 3576 : visit_inner_attrs (block);
947 : 1788 : std::function<std::unique_ptr<AST::ExternalItem> (AST::SingleASTNode)>
948 : : extractor
949 : 6 : = [] (AST::SingleASTNode node) { return node.take_external_item (); };
950 : :
951 : 1788 : expand_macro_children (MacroExpander::ContextType::EXTERN,
952 : : block.get_extern_items (), extractor);
953 : 1788 : }
954 : :
955 : : void
956 : 0 : ExpandVisitor::visit (AST::MacroMatchRepetition &)
957 : 0 : {}
958 : :
959 : : void
960 : 0 : ExpandVisitor::visit (AST::MacroMatcher &)
961 : 0 : {}
962 : :
963 : : void
964 : 4831 : ExpandVisitor::visit (AST::MacroRulesDefinition &rules_def)
965 : 4831 : {}
966 : :
967 : : void
968 : 0 : ExpandVisitor::visit (AST::MetaItemPath &)
969 : 0 : {}
970 : :
971 : : void
972 : 0 : ExpandVisitor::visit (AST::MetaItemSeq &)
973 : 0 : {}
974 : :
975 : : void
976 : 0 : ExpandVisitor::visit (AST::MetaListPaths &)
977 : 0 : {}
978 : :
979 : : void
980 : 0 : ExpandVisitor::visit (AST::MetaListNameValueStr &)
981 : 0 : {}
982 : :
983 : : void
984 : 135 : ExpandVisitor::visit (AST::StructPatternFieldIdent &field)
985 : 135 : {}
986 : :
987 : : void
988 : 3 : ExpandVisitor::visit (AST::GroupedPattern &pattern)
989 : : {
990 : 3 : visit (pattern.get_pattern_in_parens ());
991 : 3 : }
992 : :
993 : : void
994 : 16427 : ExpandVisitor::visit (AST::LetStmt &stmt)
995 : : {
996 : 16427 : visit (stmt.get_pattern ());
997 : :
998 : 16427 : if (stmt.has_type ())
999 : 2974 : maybe_expand_type (stmt.get_type_ptr ());
1000 : :
1001 : 16427 : if (stmt.has_init_expr ())
1002 : 14954 : maybe_expand_expr (stmt.get_init_expr_ptr ());
1003 : 16427 : }
1004 : :
1005 : : void
1006 : 10379 : ExpandVisitor::visit (AST::ExprStmt &stmt)
1007 : : {
1008 : 10379 : maybe_expand_expr (stmt.get_expr_ptr ());
1009 : 10379 : }
1010 : :
1011 : : void
1012 : 95 : ExpandVisitor::visit (AST::BareFunctionType &type)
1013 : : {
1014 : 189 : for (auto ¶m : type.get_function_params ())
1015 : : {
1016 : 94 : maybe_expand_type (param.get_type_ptr ());
1017 : : }
1018 : :
1019 : 95 : if (type.has_return_type ())
1020 : 62 : visit (type.get_return_type ());
1021 : 95 : }
1022 : :
1023 : : void
1024 : 15283 : ExpandVisitor::visit (AST::FunctionParam ¶m)
1025 : : {
1026 : 15283 : maybe_expand_type (param.get_type_ptr ());
1027 : 15283 : }
1028 : :
1029 : : void
1030 : 9846 : ExpandVisitor::visit (AST::SelfParam ¶m)
1031 : : {
1032 : : /* TODO: maybe check for invariants being violated - e.g. both type and
1033 : : * lifetime? */
1034 : 9846 : if (param.has_type ())
1035 : 3 : maybe_expand_type (param.get_type_ptr ());
1036 : 9846 : }
1037 : :
1038 : : template <typename T>
1039 : : void
1040 : 0 : ExpandVisitor::expand_inner_attribute (T &item, AST::SimplePath &path)
1041 : : {
1042 : : // FIXME: Retrieve path from segments + local use statements instead of string
1043 : 0 : expander.expand_attribute_proc_macro (item, path);
1044 : 0 : }
1045 : :
1046 : : template <typename T>
1047 : : void
1048 : 31212 : ExpandVisitor::visit_inner_using_attrs (T &item,
1049 : : std::vector<AST::Attribute> &attrs)
1050 : : {
1051 : 31212 : for (auto it = attrs.begin (); it != attrs.end (); /* erase => No increment*/)
1052 : : {
1053 : 0 : auto current = *it;
1054 : :
1055 : 0 : if (!is_builtin (current) && !current.is_derive ())
1056 : : {
1057 : 0 : it = attrs.erase (it);
1058 : 0 : expand_inner_attribute (item, current.get_path ());
1059 : : }
1060 : : else
1061 : : {
1062 : 0 : it++;
1063 : : }
1064 : : }
1065 : 31212 : }
1066 : :
1067 : : template <typename T>
1068 : : void
1069 : 1788 : ExpandVisitor::visit_inner_attrs (T &item)
1070 : : {
1071 : 9560 : visit_inner_using_attrs (item, item.get_inner_attrs ());
1072 : : }
1073 : :
1074 : : } // namespace Rust
|