Line data Source code
1 : // Copyright (C) 2020-2026 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-hir-map.h"
22 : #include "rust-item.h"
23 : #include "rust-proc-macro.h"
24 : #include "rust-attributes.h"
25 : #include "rust-ast.h"
26 : #include "rust-type.h"
27 : #include "rust-derive.h"
28 :
29 : namespace Rust {
30 :
31 : bool
32 13363 : is_builtin (AST::Attribute &attr)
33 : {
34 13363 : auto &segments = attr.get_path ().get_segments ();
35 13363 : return !segments.empty ()
36 13363 : && !Analysis::BuiltinAttributeMappings::get ()
37 13363 : ->lookup_builtin (segments[0].get_segment_name ())
38 13363 : .is_error ();
39 : }
40 :
41 : /* Expand all of the macro invocations currently contained in a crate */
42 : void
43 10913 : ExpandVisitor::go (AST::Crate &crate)
44 : {
45 10913 : visit (crate);
46 10913 : }
47 :
48 : static std::vector<std::unique_ptr<AST::Item>>
49 297 : builtin_derive_item (AST::Item &item, const AST::Attribute &derive,
50 : BuiltinMacro to_derive)
51 : {
52 297 : auto items = AST::DeriveVisitor::derive (item, derive, to_derive);
53 730 : for (auto &item : items)
54 433 : Analysis::Mappings::get ().add_derived_node (item->get_node_id ());
55 297 : return items;
56 : }
57 :
58 : static std::vector<std::unique_ptr<AST::Item>>
59 5 : derive_item (AST::Item &item, AST::SimplePath &to_derive,
60 : MacroExpander &expander)
61 : {
62 5 : std::vector<std::unique_ptr<AST::Item>> result;
63 5 : auto frag = expander.expand_derive_proc_macro (item, to_derive);
64 5 : if (!frag.is_error ())
65 : {
66 0 : for (auto &node : frag.get_nodes ())
67 : {
68 0 : switch (node.get_kind ())
69 : {
70 0 : case AST::SingleASTNode::Kind::Item:
71 0 : Analysis::Mappings::get ().add_derived_node (
72 0 : node.get_item ()->get_node_id ());
73 0 : result.push_back (node.take_item ());
74 0 : break;
75 0 : default:
76 0 : rust_unreachable ();
77 : }
78 : }
79 : }
80 5 : return result;
81 5 : }
82 :
83 : static std::vector<std::unique_ptr<AST::Item>>
84 0 : expand_item_attribute (AST::Item &item, AST::SimplePath &name,
85 : MacroExpander &expander)
86 : {
87 0 : std::vector<std::unique_ptr<AST::Item>> result;
88 0 : auto frag = expander.expand_attribute_proc_macro (item, name);
89 0 : if (!frag.is_error ())
90 : {
91 0 : for (auto &node : frag.get_nodes ())
92 : {
93 0 : switch (node.get_kind ())
94 : {
95 0 : case AST::SingleASTNode::Kind::Item:
96 0 : result.push_back (node.take_item ());
97 0 : break;
98 0 : default:
99 0 : rust_unreachable ();
100 : }
101 : }
102 : }
103 0 : return result;
104 0 : }
105 :
106 : /* Helper function to expand a given attribute on a statement and collect back
107 : * statements.
108 : * T should be anything that can be used as a statement accepting outer
109 : * attributes.
110 : */
111 : template <typename T>
112 : static std::vector<std::unique_ptr<AST::Stmt>>
113 1 : expand_stmt_attribute (T &statement, AST::SimplePath &attribute,
114 : MacroExpander &expander)
115 : {
116 1 : std::vector<std::unique_ptr<AST::Stmt>> result;
117 1 : auto frag = expander.expand_attribute_proc_macro (statement, attribute);
118 1 : if (!frag.is_error ())
119 : {
120 0 : for (auto &node : frag.get_nodes ())
121 : {
122 0 : switch (node.get_kind ())
123 : {
124 0 : case AST::SingleASTNode::Kind::Stmt:
125 0 : result.push_back (node.take_stmt ());
126 : break;
127 0 : default:
128 0 : rust_unreachable ();
129 : }
130 : }
131 : }
132 1 : return result;
133 1 : }
134 :
135 : void
136 55590 : expand_tail_expr (AST::BlockExpr &block_expr, MacroExpander &expander)
137 : {
138 55590 : if (block_expr.has_tail_expr ())
139 : {
140 40905 : auto tail = block_expr.take_tail_expr ();
141 40905 : auto attrs = tail->get_outer_attrs ();
142 40905 : bool changed = false;
143 41783 : for (auto it = attrs.begin (); it != attrs.end ();)
144 : {
145 878 : auto current = *it;
146 878 : if (is_builtin (current))
147 : {
148 878 : it++;
149 : }
150 : else
151 : {
152 0 : it = attrs.erase (it);
153 0 : changed = true;
154 0 : auto new_stmts
155 : = expand_stmt_attribute (block_expr, current.get_path (),
156 0 : expander);
157 0 : auto &stmts = block_expr.get_statements ();
158 0 : std::move (new_stmts.begin (), new_stmts.end (),
159 : std::inserter (stmts, stmts.end ()));
160 0 : }
161 878 : }
162 40905 : if (changed)
163 0 : block_expr.normalize_tail_expr ();
164 : else
165 40905 : block_expr.set_tail_expr (std::move (tail));
166 40905 : }
167 55590 : }
168 :
169 : void
170 14144 : ExpandVisitor::expand_inner_items (
171 : std::vector<std::unique_ptr<AST::Item>> &items)
172 : {
173 14144 : expander.push_context (MacroExpander::ContextType::ITEM);
174 :
175 73103 : for (auto it = items.begin (); it != items.end (); it++)
176 : {
177 58959 : Rust::AST::Item &item = **it;
178 58959 : if (item.has_outer_attrs ())
179 : {
180 9497 : auto &attrs = item.get_outer_attrs ();
181 :
182 22140 : for (auto attr_it = attrs.begin (); attr_it != attrs.end ();
183 : /* erase => No increment*/)
184 : {
185 12643 : auto current = *attr_it;
186 :
187 12643 : if (current.is_derive ())
188 : {
189 168 : current.parse_attr_to_meta_item ();
190 168 : attr_it = attrs.erase (attr_it);
191 : // Get traits to derive in the current attribute
192 168 : auto traits_to_derive = current.get_traits_to_derive ();
193 470 : for (auto &to_derive : traits_to_derive)
194 : {
195 302 : auto maybe_builtin = MacroBuiltin::builtins.lookup (
196 302 : to_derive.get ().as_string ());
197 302 : if (maybe_builtin.has_value ())
198 : {
199 297 : auto new_items
200 : = builtin_derive_item (item, current,
201 297 : maybe_builtin.value ());
202 :
203 730 : for (auto &&new_item : new_items)
204 433 : it = items.insert (it, std::move (new_item));
205 297 : }
206 : else
207 : {
208 : // Macro is not a builtin, so it must be a
209 : // user-defined derive macro.
210 5 : auto new_items
211 5 : = derive_item (item, to_derive, expander);
212 5 : std::move (new_items.begin (), new_items.end (),
213 : std::inserter (items, it));
214 5 : }
215 : }
216 168 : }
217 : else /* Attribute */
218 : {
219 12475 : if (is_builtin (current))
220 : {
221 12475 : visit (*attr_it);
222 12475 : attr_it++;
223 : }
224 : else
225 : {
226 0 : attr_it = attrs.erase (attr_it);
227 0 : auto new_items
228 : = expand_item_attribute (item, current.get_path (),
229 0 : expander);
230 0 : it = items.erase (it);
231 0 : std::move (new_items.begin (), new_items.end (),
232 : std::inserter (items, it));
233 : // TODO: Improve this ?
234 : // item is invalid since it refers to now deleted,
235 : // cancel the loop increment and break.
236 0 : it--;
237 0 : break;
238 0 : }
239 : }
240 12643 : }
241 : }
242 : }
243 :
244 14144 : expand_macro_children (items, &AST::SingleASTNode::take_item);
245 :
246 14144 : expander.pop_context ();
247 14144 : }
248 :
249 : void
250 55590 : ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr)
251 : {
252 55590 : auto &stmts = expr.get_statements ();
253 55590 : expander.push_context (MacroExpander::ContextType::STMT);
254 :
255 107764 : for (auto it = stmts.begin (); it != stmts.end (); it++)
256 : {
257 52174 : auto &stmt = *it;
258 :
259 : // skip all non-item statements
260 52174 : if (stmt->get_stmt_kind () != AST::Stmt::Kind::Item)
261 50546 : continue;
262 :
263 1628 : auto &item = static_cast<AST::Item &> (*stmt.get ());
264 :
265 1628 : if (item.has_outer_attrs ())
266 : {
267 10 : auto &attrs = item.get_outer_attrs ();
268 :
269 19 : for (auto attr_it = attrs.begin (); attr_it != attrs.end ();
270 : /* erase => No increment*/)
271 : {
272 10 : auto current = *attr_it;
273 :
274 10 : if (current.is_derive ())
275 : {
276 0 : attr_it = attrs.erase (attr_it);
277 : // Get traits to derive in the current attribute
278 0 : auto traits_to_derive = current.get_traits_to_derive ();
279 0 : for (auto &to_derive : traits_to_derive)
280 : {
281 0 : auto maybe_builtin = MacroBuiltin::builtins.lookup (
282 0 : to_derive.get ().as_string ());
283 0 : if (maybe_builtin.has_value ())
284 : {
285 0 : auto new_items
286 : = builtin_derive_item (item, current,
287 0 : maybe_builtin.value ());
288 :
289 : // this inserts the derive *before* the item - is it a
290 : // problem?
291 0 : for (auto &&new_item : new_items)
292 0 : it = stmts.insert (it, std::move (new_item));
293 0 : }
294 : else
295 : {
296 0 : auto new_items
297 0 : = derive_item (item, to_derive, expander);
298 0 : std::move (new_items.begin (), new_items.end (),
299 : std::inserter (stmts, it));
300 0 : }
301 : }
302 0 : }
303 : else /* Attribute */
304 : {
305 10 : if (is_builtin (current))
306 : {
307 9 : visit (*attr_it);
308 9 : attr_it++;
309 : }
310 : else
311 : {
312 1 : attr_it = attrs.erase (attr_it);
313 1 : auto new_items
314 : = expand_stmt_attribute (item, current.get_path (),
315 1 : expander);
316 1 : it = stmts.erase (it);
317 1 : std::move (new_items.begin (), new_items.end (),
318 : std::inserter (stmts, it));
319 : // TODO: Improve this ?
320 : // item is invalid since it refers to now deleted,
321 : // cancel the loop increment and break.
322 1 : it--;
323 1 : break;
324 1 : }
325 : }
326 10 : }
327 : }
328 : }
329 :
330 55590 : if (!expr.has_tail_expr ())
331 14744 : expr.normalize_tail_expr ();
332 :
333 55590 : expand_macro_children (stmts, &AST::SingleASTNode::take_stmt);
334 :
335 55590 : expander.pop_context ();
336 55590 : }
337 :
338 : void
339 13340 : ExpandVisitor::visit (AST::Attribute &attr)
340 : {
341 : // An attribute input containing a macro may have been expanded to a literal
342 13340 : if (attr.has_attr_input ()
343 13340 : && attr.get_attr_input ().get_attr_input_type ()
344 : == AST::AttrInput::AttrInputType::EXPR)
345 : {
346 6 : auto &expr = static_cast<AST::AttrInputExpr &> (attr.get_attr_input ());
347 6 : if (expr.get_expr ().is_literal ())
348 : {
349 2 : auto &lit = static_cast<AST::LiteralExpr &> (expr.get_expr ());
350 2 : attr.set_attr_input (std::make_unique<AST::AttrInputLiteral> (lit));
351 : }
352 : }
353 13340 : AST::DefaultASTVisitor::visit (attr);
354 13340 : }
355 :
356 : void
357 1328184 : ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
358 : {
359 1328184 : NodeId old_expect = expr->get_node_id ();
360 1328184 : std::swap (macro_invoc_expect_id, old_expect);
361 :
362 1328184 : expander.push_context (MacroExpander::ContextType::EXPR);
363 1328184 : expr->accept_vis (*this);
364 1328184 : expander.pop_context ();
365 :
366 1328184 : std::swap (macro_invoc_expect_id, old_expect);
367 :
368 1328184 : auto final_fragment = expander.take_expanded_fragment ();
369 1328184 : if (final_fragment.should_expand ()
370 1328184 : && final_fragment.is_expression_fragment ())
371 1903 : expr = final_fragment.take_expression_fragment ();
372 1328184 : }
373 :
374 : void
375 106682 : ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
376 : {
377 106682 : NodeId old_expect = type->get_node_id ();
378 106682 : std::swap (macro_invoc_expect_id, old_expect);
379 :
380 213364 : expander.push_context (MacroExpander::ContextType::TYPE);
381 106682 : type->accept_vis (*this);
382 106682 : expander.pop_context ();
383 :
384 106682 : std::swap (macro_invoc_expect_id, old_expect);
385 :
386 106682 : auto final_fragment = expander.take_expanded_fragment ();
387 106682 : if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
388 28 : type = final_fragment.take_type_fragment ();
389 106682 : }
390 :
391 : // HACK: maybe we shouldn't have TypeNoBounds as a base class
392 : void
393 38002 : ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type)
394 : {
395 38002 : NodeId old_expect = type->get_node_id ();
396 38002 : std::swap (macro_invoc_expect_id, old_expect);
397 :
398 38002 : expander.push_context (MacroExpander::ContextType::TYPE);
399 38002 : type->accept_vis (*this);
400 38002 : expander.pop_context ();
401 :
402 38002 : std::swap (macro_invoc_expect_id, old_expect);
403 :
404 38002 : auto final_fragment = expander.take_expanded_fragment ();
405 38002 : if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
406 2 : type = std::make_unique<AST::ParenthesisedType> (
407 3 : final_fragment.take_type_fragment (), BUILTINS_LOCATION);
408 38002 : }
409 :
410 : void
411 69862 : ExpandVisitor::maybe_expand_pattern (std::unique_ptr<AST::Pattern> &pattern)
412 : {
413 69862 : NodeId old_expect = pattern->get_node_id ();
414 69862 : std::swap (macro_invoc_expect_id, old_expect);
415 :
416 69862 : expander.push_context (MacroExpander::ContextType::PATTERN);
417 69862 : pattern->accept_vis (*this);
418 69862 : expander.pop_context ();
419 :
420 69862 : std::swap (macro_invoc_expect_id, old_expect);
421 :
422 69862 : auto final_fragment = expander.take_expanded_fragment ();
423 69862 : if (final_fragment.should_expand () && final_fragment.is_pattern_fragment ())
424 1 : pattern = final_fragment.take_pattern_fragment ();
425 69862 : }
426 :
427 : void
428 4128 : ExpandVisitor::expand_struct_fields (std::vector<AST::StructField> &fields)
429 : {
430 4128 : expand_fields (fields);
431 4128 : }
432 :
433 : void
434 3204 : ExpandVisitor::expand_tuple_fields (std::vector<AST::TupleField> &fields)
435 : {
436 3204 : expand_fields (fields);
437 3204 : }
438 :
439 : // FIXME: This can definitely be refactored with the method above
440 : void
441 45527 : ExpandVisitor::expand_function_params (
442 : std::vector<std::unique_ptr<AST::Param>> ¶ms)
443 : {
444 95521 : for (auto &p : params)
445 49994 : visit (p);
446 45527 : }
447 :
448 : void
449 9185 : ExpandVisitor::expand_generic_args (AST::GenericArgs &args)
450 : {
451 18798 : for (auto &arg : args.get_generic_args ())
452 : {
453 9613 : switch (arg.get_kind ())
454 : {
455 3854 : case AST::GenericArg::Kind::Type:
456 3854 : maybe_expand_type (arg.get_type_ptr ());
457 3854 : break;
458 142 : case AST::GenericArg::Kind::Const:
459 142 : maybe_expand_expr (arg.get_expression_ptr ());
460 142 : break;
461 : default:
462 : break;
463 : // FIXME: Figure out what to do here if there is ambiguity. Since the
464 : // resolver comes after the expansion, we need to figure out a way to
465 : // strip ambiguous values here
466 : // TODO: ARTHUR: Probably add a `mark_as_strip` method to `GenericArg`
467 : // or something. This would clean up this whole thing
468 : }
469 : }
470 :
471 : // FIXME: Can we have macro invocations in generic type bindings?
472 : // expand binding args - strip sub-types only
473 : // FIXME: ARTHUR: This needs a test! Foo<Item = macro!()>
474 9379 : for (auto &binding : args.get_binding_args ())
475 194 : maybe_expand_type (binding.get_type_ptr ());
476 9185 : }
477 :
478 : void
479 982 : ExpandVisitor::expand_qualified_path_type (AST::QualifiedPathType &path_type)
480 : {
481 982 : maybe_expand_type (path_type.get_type_ptr ());
482 :
483 : // FIXME: ARTHUR: Can we do macro expansion in there? Needs a test!
484 982 : if (path_type.has_as_clause ())
485 888 : path_type.get_as_type_path ().accept_vis (*this);
486 982 : }
487 :
488 : void
489 134 : ExpandVisitor::expand_closure_params (std::vector<AST::ClosureParam> ¶ms)
490 : {
491 260 : for (auto ¶m : params)
492 : {
493 126 : maybe_expand_pattern (param.get_pattern_ptr ());
494 :
495 126 : if (param.has_type_given ())
496 116 : maybe_expand_type (param.get_type_ptr ());
497 : }
498 134 : }
499 :
500 : void
501 765 : ExpandVisitor::expand_where_clause (AST::WhereClause &where_clause)
502 : {
503 1550 : for (auto &item : where_clause.get_items ())
504 785 : visit (item);
505 765 : }
506 :
507 : void
508 10913 : ExpandVisitor::visit (AST::Crate &crate)
509 : {
510 10913 : expand_inner_items (crate.items);
511 10913 : }
512 :
513 : void
514 4510 : ExpandVisitor::visit (AST::DelimTokenTree &)
515 4510 : {}
516 :
517 : void
518 63 : ExpandVisitor::visit (AST::AttrInputMetaItemContainer &)
519 63 : {}
520 :
521 : void
522 55660 : ExpandVisitor::visit (AST::IdentifierExpr &ident_expr)
523 55660 : {}
524 :
525 : void
526 520 : ExpandVisitor::visit (AST::LifetimeParam &)
527 520 : {}
528 :
529 : void
530 206 : ExpandVisitor::visit (AST::ConstGenericParam &)
531 206 : {}
532 :
533 : void
534 2812 : ExpandVisitor::visit (AST::MacroInvocation ¯o_invoc)
535 : {
536 2812 : if (macro_invoc_expect_id != macro_invoc.get_node_id ())
537 : {
538 0 : rust_internal_error_at (
539 : macro_invoc.get_locus (),
540 : "attempting to expand node with id %d into position with node id %d",
541 0 : (int) macro_invoc.get_node_id (), (int) macro_invoc_expect_id);
542 : }
543 :
544 : // TODO: Can we do the AST fragment replacing here? Probably not, right?
545 4774 : expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ()
546 : ? AST::InvocKind::Semicoloned
547 : : AST::InvocKind::Expr);
548 2812 : }
549 :
550 : void
551 62372 : ExpandVisitor::visit (AST::PathInExpression &path)
552 : {
553 62372 : if (!path.is_lang_item ())
554 149395 : for (auto &segment : path.get_segments ())
555 174440 : if (segment.has_generic_args ())
556 2108 : expand_generic_args (segment.get_generic_args ());
557 62372 : }
558 :
559 : void
560 7079 : ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment)
561 : {
562 7079 : if (segment.has_generic_args ())
563 7077 : expand_generic_args (segment.get_generic_args ());
564 7079 : }
565 :
566 : void
567 60 : ExpandVisitor::visit (AST::TypePathSegmentFunction &segment)
568 : {
569 60 : auto &type_path_function = segment.get_type_path_function ();
570 :
571 124 : for (auto &type : type_path_function.get_params ())
572 64 : visit (type);
573 :
574 60 : if (type_path_function.has_return_type ())
575 56 : maybe_expand_type (type_path_function.get_return_type_ptr ());
576 60 : }
577 :
578 : void
579 273 : ExpandVisitor::visit (AST::QualifiedPathInExpression &path)
580 : {
581 273 : expand_qualified_path_type (path.get_qualified_path_type ());
582 :
583 546 : for (auto &segment : path.get_segments ())
584 546 : if (segment.has_generic_args ())
585 0 : expand_generic_args (segment.get_generic_args ());
586 273 : }
587 :
588 : void
589 709 : ExpandVisitor::visit (AST::QualifiedPathInType &path)
590 : {
591 709 : expand_qualified_path_type (path.get_qualified_path_type ());
592 :
593 : // this shouldn't strip any segments, but can strip inside them
594 709 : for (auto &segment : path.get_segments ())
595 0 : visit (segment);
596 709 : }
597 :
598 : void
599 566696 : ExpandVisitor::visit (AST::LiteralExpr &expr)
600 566696 : {}
601 :
602 : void
603 8315 : ExpandVisitor::visit (AST::AttrInputLiteral &)
604 8315 : {}
605 :
606 : void
607 4 : ExpandVisitor::visit (AST::AttrInputExpr &attr_input)
608 : {
609 4 : maybe_expand_expr (attr_input.get_expr_ptr ());
610 4 : }
611 :
612 : void
613 0 : ExpandVisitor::visit (AST::MetaItemLitExpr &)
614 0 : {}
615 :
616 : void
617 0 : ExpandVisitor::visit (AST::MetaItemPathExpr &)
618 0 : {}
619 :
620 : void
621 166 : ExpandVisitor::visit (AST::StructExprStruct &expr)
622 166 : {}
623 :
624 : void
625 74 : ExpandVisitor::visit (AST::ClosureExprInner &expr)
626 : {
627 74 : expand_closure_params (expr.get_params ());
628 :
629 74 : maybe_expand_expr (expr.get_definition_expr_ptr ());
630 74 : }
631 :
632 : void
633 55590 : ExpandVisitor::visit (AST::BlockExpr &expr)
634 : {
635 55590 : expand_inner_stmts (expr);
636 :
637 55590 : expand_tail_expr (expr, expander);
638 55590 : if (expr.has_tail_expr ())
639 40905 : maybe_expand_expr (expr.get_tail_expr_ptr ());
640 55590 : }
641 :
642 : void
643 60 : ExpandVisitor::visit (AST::ClosureExprInnerTyped &expr)
644 : {
645 60 : expand_closure_params (expr.get_params ());
646 :
647 60 : maybe_expand_type (expr.get_return_type_ptr ());
648 :
649 60 : visit (expr.get_definition_expr ());
650 60 : }
651 :
652 : void
653 2577 : ExpandVisitor::visit (AST::IfExpr &expr)
654 : {
655 2577 : maybe_expand_expr (expr.get_condition_expr_ptr ());
656 :
657 2577 : visit (expr.get_if_block ());
658 2577 : }
659 :
660 : void
661 3274 : ExpandVisitor::visit (AST::IfExprConseqElse &expr)
662 : {
663 3274 : maybe_expand_expr (expr.get_condition_expr_ptr ());
664 :
665 3274 : visit (expr.get_if_block ());
666 3274 : visit (expr.get_else_block ());
667 3274 : }
668 :
669 : void
670 36 : ExpandVisitor::visit (AST::IfLetExpr &expr)
671 : {
672 36 : maybe_expand_expr (expr.get_value_expr_ptr ());
673 :
674 36 : visit (expr.get_if_block ());
675 36 : }
676 :
677 : void
678 24 : ExpandVisitor::visit (AST::IfLetExprConseqElse &expr)
679 : {
680 24 : maybe_expand_expr (expr.get_value_expr_ptr ());
681 :
682 24 : visit (expr.get_if_block ());
683 24 : visit (expr.get_else_block ());
684 24 : }
685 :
686 : void
687 11303 : ExpandVisitor::visit (AST::TypeParam ¶m)
688 : {
689 13299 : for (auto &bound : param.get_type_param_bounds ())
690 1996 : visit (bound);
691 :
692 11303 : if (param.has_type ())
693 925 : maybe_expand_type (param.get_type_ptr ());
694 11303 : }
695 :
696 : void
697 4 : ExpandVisitor::visit (AST::LifetimeWhereClauseItem &)
698 4 : {}
699 :
700 : void
701 781 : ExpandVisitor::visit (AST::TypeBoundWhereClauseItem &item)
702 : {
703 781 : maybe_expand_type (item.get_type_ptr ());
704 :
705 1562 : for (auto &bound : item.get_type_param_bounds ())
706 781 : visit (bound);
707 781 : }
708 :
709 : void
710 3231 : ExpandVisitor::visit (AST::Module &module)
711 : {
712 3231 : expand_inner_items (module.get_items ());
713 3231 : }
714 :
715 : void
716 50 : ExpandVisitor::visit (AST::ExternCrate &crate)
717 50 : {}
718 :
719 : void
720 0 : ExpandVisitor::visit (AST::UseTreeGlob &)
721 0 : {}
722 :
723 : void
724 0 : ExpandVisitor::visit (AST::UseTreeList &)
725 0 : {}
726 :
727 : void
728 0 : ExpandVisitor::visit (AST::UseTreeRebind &)
729 0 : {}
730 :
731 : void
732 1870 : ExpandVisitor::visit (AST::UseDeclaration &use_decl)
733 1870 : {}
734 :
735 : void
736 45527 : ExpandVisitor::visit (AST::Function &function)
737 : {
738 45527 : if (function.has_body ())
739 35103 : visit_inner_using_attrs (
740 35103 : function, function.get_definition ().value ()->get_inner_attrs ());
741 50255 : for (auto ¶m : function.get_generic_params ())
742 4728 : visit (param);
743 :
744 45527 : expand_function_params (function.get_function_params ());
745 :
746 45527 : if (function.has_return_type ())
747 33448 : maybe_expand_type (function.get_return_type_ptr ());
748 :
749 45527 : if (function.has_where_clause ())
750 522 : expand_where_clause (function.get_where_clause ());
751 :
752 45527 : if (function.has_body ())
753 35103 : visit (*function.get_definition ());
754 45527 : }
755 :
756 : void
757 3695 : ExpandVisitor::visit (AST::StructStruct &struct_item)
758 : {
759 4900 : for (auto &generic : struct_item.get_generic_params ())
760 1205 : visit (generic);
761 :
762 3695 : if (struct_item.has_where_clause ())
763 4 : expand_where_clause (struct_item.get_where_clause ());
764 :
765 3695 : expand_struct_fields (struct_item.get_fields ());
766 3695 : }
767 :
768 : void
769 2086 : ExpandVisitor::visit (AST::TupleStruct &tuple_struct)
770 : {
771 2833 : for (auto &generic : tuple_struct.get_generic_params ())
772 747 : visit (generic);
773 :
774 2086 : if (tuple_struct.has_where_clause ())
775 0 : expand_where_clause (tuple_struct.get_where_clause ());
776 :
777 2086 : expand_tuple_fields (tuple_struct.get_fields ());
778 2086 : }
779 :
780 : void
781 1052 : ExpandVisitor::visit (AST::EnumItem &item)
782 1052 : {}
783 :
784 : void
785 1118 : ExpandVisitor::visit (AST::EnumItemTuple &item)
786 : {
787 1118 : expand_tuple_fields (item.get_tuple_fields ());
788 1118 : }
789 :
790 : void
791 208 : ExpandVisitor::visit (AST::EnumItemStruct &item)
792 : {
793 208 : expand_struct_fields (item.get_struct_fields ());
794 208 : }
795 :
796 : void
797 687 : ExpandVisitor::visit (AST::EnumItemDiscriminant &item)
798 : {
799 687 : maybe_expand_expr (item.get_expr_ptr ());
800 687 : }
801 :
802 : void
803 225 : ExpandVisitor::visit (AST::Union &union_item)
804 : {
805 382 : for (auto &generic : union_item.get_generic_params ())
806 157 : visit (generic);
807 :
808 225 : expand_struct_fields (union_item.get_variants ());
809 225 : }
810 :
811 : void
812 9142 : ExpandVisitor::visit (AST::Trait &trait)
813 : {
814 10775 : for (auto &generic : trait.get_generic_params ())
815 1633 : visit (generic);
816 :
817 10828 : for (auto &bound : trait.get_type_param_bounds ())
818 1686 : visit (bound);
819 :
820 9142 : if (trait.has_where_clause ())
821 21 : expand_where_clause (trait.get_where_clause ());
822 :
823 9142 : expander.push_context (MacroExpander::ContextType::TRAIT);
824 :
825 9142 : expand_macro_children (MacroExpander::ContextType::TRAIT,
826 : trait.get_trait_items (),
827 : &AST::SingleASTNode::take_assoc_item);
828 :
829 9142 : expander.pop_context ();
830 9142 : }
831 :
832 : void
833 2245 : ExpandVisitor::visit (AST::InherentImpl &impl)
834 : {
835 4490 : visit_inner_attrs (impl);
836 : // just expand sub-stuff - can't actually strip generic params themselves
837 3037 : for (auto &generic : impl.get_generic_params ())
838 792 : visit (generic);
839 :
840 : // FIXME: Is that correct? How do we test that?
841 2245 : expander.push_context (MacroExpander::ContextType::ITEM);
842 :
843 2245 : maybe_expand_type (impl.get_type_ptr ());
844 :
845 2245 : expander.pop_context ();
846 :
847 2245 : if (impl.has_where_clause ())
848 2 : expand_where_clause (impl.get_where_clause ());
849 :
850 2245 : expand_macro_children (MacroExpander::ContextType::IMPL,
851 : impl.get_impl_items (),
852 : &AST::SingleASTNode::take_assoc_item);
853 2245 : }
854 :
855 : void
856 11720 : ExpandVisitor::visit (AST::TraitImpl &impl)
857 : {
858 23440 : visit_inner_attrs (impl);
859 : // just expand sub-stuff - can't actually strip generic params themselves
860 13628 : for (auto ¶m : impl.get_generic_params ())
861 1908 : visit (param);
862 :
863 : // FIXME: Is that correct? How do we test that?
864 11720 : expander.push_context (MacroExpander::ContextType::ITEM);
865 :
866 11720 : maybe_expand_type (impl.get_type_ptr ());
867 :
868 11720 : expander.pop_context ();
869 :
870 11720 : visit (impl.get_trait_path ());
871 :
872 11720 : if (impl.has_where_clause ())
873 216 : expand_where_clause (impl.get_where_clause ());
874 :
875 11720 : expand_macro_children (MacroExpander::ContextType::TRAIT_IMPL,
876 : impl.get_impl_items (),
877 : &AST::SingleASTNode::take_assoc_item);
878 11720 : }
879 :
880 : void
881 2 : ExpandVisitor::visit (AST::ExternalTypeItem &item)
882 2 : {}
883 :
884 : void
885 2 : ExpandVisitor::visit (AST::ExternalStaticItem &static_item)
886 : {
887 2 : maybe_expand_type (static_item.get_type_ptr ());
888 2 : }
889 :
890 : void
891 3660 : ExpandVisitor::visit (AST::ExternBlock &block)
892 : {
893 7320 : visit_inner_attrs (block);
894 :
895 3660 : expand_macro_children (MacroExpander::ContextType::EXTERN,
896 : block.get_extern_items (),
897 : &AST::SingleASTNode::take_external_item);
898 3660 : }
899 :
900 : void
901 0 : ExpandVisitor::visit (AST::MacroMatchRepetition &)
902 0 : {}
903 :
904 : void
905 0 : ExpandVisitor::visit (AST::MacroMatcher &)
906 0 : {}
907 :
908 : void
909 3806 : ExpandVisitor::visit (AST::MacroRulesDefinition &rules_def)
910 3806 : {}
911 :
912 : void
913 0 : ExpandVisitor::visit (AST::MetaItemPath &)
914 0 : {}
915 :
916 : void
917 0 : ExpandVisitor::visit (AST::MetaItemSeq &)
918 0 : {}
919 :
920 : void
921 0 : ExpandVisitor::visit (AST::MetaListPaths &)
922 0 : {}
923 :
924 : void
925 0 : ExpandVisitor::visit (AST::MetaListNameValueStr &)
926 0 : {}
927 :
928 : void
929 219 : ExpandVisitor::visit (AST::StructPatternFieldIdent &field)
930 219 : {}
931 :
932 : void
933 137 : ExpandVisitor::visit (AST::BareFunctionType &type)
934 : {
935 243 : for (auto ¶m : type.get_function_params ())
936 : {
937 106 : maybe_expand_type (param.get_type_ptr ());
938 : }
939 :
940 137 : if (type.has_return_type ())
941 97 : visit (type.get_return_type ());
942 137 : }
943 :
944 : void
945 27869 : ExpandVisitor::visit (AST::FunctionParam ¶m)
946 : {
947 27869 : maybe_expand_pattern (param.get_pattern_ptr ());
948 27869 : maybe_expand_type (param.get_type_ptr ());
949 27869 : }
950 :
951 : void
952 1795 : ExpandVisitor::visit (AST::VariadicParam ¶m)
953 : {
954 1795 : if (param.has_pattern ())
955 22 : maybe_expand_pattern (param.get_pattern_ptr ());
956 1795 : }
957 :
958 : void
959 20330 : ExpandVisitor::visit (AST::SelfParam ¶m)
960 : {
961 : /* TODO: maybe check for invariants being violated - e.g. both type and
962 : * lifetime? */
963 20330 : if (param.has_type ())
964 2 : maybe_expand_type (param.get_type_ptr ());
965 20330 : }
966 :
967 : template <typename T>
968 : void
969 0 : ExpandVisitor::expand_inner_attribute (T &item, AST::SimplePath &path)
970 : {
971 : // FIXME: Retrieve path from segments + local use statements instead of string
972 0 : expander.expand_attribute_proc_macro (item, path);
973 0 : }
974 :
975 : template <typename T>
976 : void
977 52728 : ExpandVisitor::visit_inner_using_attrs (T &item,
978 : std::vector<AST::Attribute> &attrs)
979 : {
980 52728 : for (auto it = attrs.begin (); it != attrs.end (); /* erase => No increment*/)
981 : {
982 0 : auto current = *it;
983 :
984 0 : if (!is_builtin (current) && !current.is_derive ())
985 : {
986 0 : it = attrs.erase (it);
987 0 : expand_inner_attribute (item, current.get_path ());
988 : }
989 : else
990 : {
991 0 : it++;
992 : }
993 : }
994 52728 : }
995 :
996 : template <typename T>
997 : void
998 3660 : ExpandVisitor::visit_inner_attrs (T &item)
999 : {
1000 17625 : visit_inner_using_attrs (item, item.get_inner_attrs ());
1001 : }
1002 :
1003 : } // namespace Rust
|