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 13182 : is_builtin (AST::Attribute &attr)
33 : {
34 13182 : auto &segments = attr.get_path ().get_segments ();
35 13182 : return !segments.empty ()
36 13182 : && !Analysis::BuiltinAttributeMappings::get ()
37 13182 : ->lookup_builtin (segments[0].get_segment_name ())
38 13182 : .is_error ();
39 : }
40 :
41 : /* Expand all of the macro invocations currently contained in a crate */
42 : void
43 10738 : ExpandVisitor::go (AST::Crate &crate)
44 : {
45 10738 : visit (crate);
46 10738 : }
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 54876 : expand_tail_expr (AST::BlockExpr &block_expr, MacroExpander &expander)
137 : {
138 54876 : if (block_expr.has_tail_expr ())
139 : {
140 40346 : auto tail = block_expr.take_tail_expr ();
141 40346 : auto attrs = tail->get_outer_attrs ();
142 40346 : bool changed = false;
143 41224 : 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 40346 : if (changed)
163 0 : block_expr.normalize_tail_expr ();
164 : else
165 40346 : block_expr.set_tail_expr (std::move (tail));
166 40346 : }
167 54876 : }
168 :
169 : void
170 13927 : ExpandVisitor::expand_inner_items (
171 : std::vector<std::unique_ptr<AST::Item>> &items)
172 : {
173 13927 : expander.push_context (MacroExpander::ContextType::ITEM);
174 :
175 71990 : for (auto it = items.begin (); it != items.end (); it++)
176 : {
177 58063 : Rust::AST::Item &item = **it;
178 58063 : if (item.has_outer_attrs ())
179 : {
180 9320 : auto &attrs = item.get_outer_attrs ();
181 :
182 21782 : for (auto attr_it = attrs.begin (); attr_it != attrs.end ();
183 : /* erase => No increment*/)
184 : {
185 12462 : auto current = *attr_it;
186 :
187 12462 : 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 12294 : if (is_builtin (current))
220 : {
221 12294 : visit (*attr_it);
222 12294 : 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 12462 : }
241 : }
242 : }
243 :
244 13927 : expand_macro_children (items, &AST::SingleASTNode::take_item);
245 :
246 13927 : expander.pop_context ();
247 13927 : }
248 :
249 : void
250 54876 : ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr)
251 : {
252 54876 : auto &stmts = expr.get_statements ();
253 54876 : expander.push_context (MacroExpander::ContextType::STMT);
254 :
255 106477 : for (auto it = stmts.begin (); it != stmts.end (); it++)
256 : {
257 51601 : auto &stmt = *it;
258 :
259 : // skip all non-item statements
260 51601 : if (stmt->get_stmt_kind () != AST::Stmt::Kind::Item)
261 49986 : continue;
262 :
263 1615 : auto &item = static_cast<AST::Item &> (*stmt.get ());
264 :
265 1615 : 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 54876 : if (!expr.has_tail_expr ())
331 14589 : expr.normalize_tail_expr ();
332 :
333 54876 : expand_macro_children (stmts, &AST::SingleASTNode::take_stmt);
334 :
335 54876 : expander.pop_context ();
336 54876 : }
337 :
338 : void
339 13157 : ExpandVisitor::visit (AST::Attribute &attr)
340 : {
341 : // An attribute input containing a macro may have been expanded to a literal
342 13157 : if (attr.has_attr_input ()
343 13157 : && 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 13157 : AST::DefaultASTVisitor::visit (attr);
354 13157 : }
355 :
356 : void
357 1325232 : ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
358 : {
359 1325232 : NodeId old_expect = expr->get_node_id ();
360 1325232 : std::swap (macro_invoc_expect_id, old_expect);
361 :
362 1325232 : expander.push_context (MacroExpander::ContextType::EXPR);
363 1325232 : expr->accept_vis (*this);
364 1325232 : expander.pop_context ();
365 :
366 1325232 : std::swap (macro_invoc_expect_id, old_expect);
367 :
368 1325232 : auto final_fragment = expander.take_expanded_fragment ();
369 1325232 : if (final_fragment.should_expand ()
370 1325232 : && final_fragment.is_expression_fragment ())
371 1900 : expr = final_fragment.take_expression_fragment ();
372 1325232 : }
373 :
374 : void
375 105489 : ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
376 : {
377 105489 : NodeId old_expect = type->get_node_id ();
378 105489 : std::swap (macro_invoc_expect_id, old_expect);
379 :
380 210978 : expander.push_context (MacroExpander::ContextType::TYPE);
381 105489 : type->accept_vis (*this);
382 105489 : expander.pop_context ();
383 :
384 105489 : std::swap (macro_invoc_expect_id, old_expect);
385 :
386 105489 : auto final_fragment = expander.take_expanded_fragment ();
387 105489 : if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
388 28 : type = final_fragment.take_type_fragment ();
389 105489 : }
390 :
391 : // HACK: maybe we shouldn't have TypeNoBounds as a base class
392 : void
393 37316 : ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type)
394 : {
395 37316 : NodeId old_expect = type->get_node_id ();
396 37316 : std::swap (macro_invoc_expect_id, old_expect);
397 :
398 37316 : expander.push_context (MacroExpander::ContextType::TYPE);
399 37316 : type->accept_vis (*this);
400 37316 : expander.pop_context ();
401 :
402 37316 : std::swap (macro_invoc_expect_id, old_expect);
403 :
404 37316 : auto final_fragment = expander.take_expanded_fragment ();
405 37316 : 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 37316 : }
409 :
410 : void
411 69184 : ExpandVisitor::maybe_expand_pattern (std::unique_ptr<AST::Pattern> &pattern)
412 : {
413 69184 : NodeId old_expect = pattern->get_node_id ();
414 69184 : std::swap (macro_invoc_expect_id, old_expect);
415 :
416 69184 : expander.push_context (MacroExpander::ContextType::PATTERN);
417 69184 : pattern->accept_vis (*this);
418 69184 : expander.pop_context ();
419 :
420 69184 : std::swap (macro_invoc_expect_id, old_expect);
421 :
422 69184 : auto final_fragment = expander.take_expanded_fragment ();
423 69184 : if (final_fragment.should_expand () && final_fragment.is_pattern_fragment ())
424 1 : pattern = final_fragment.take_pattern_fragment ();
425 69184 : }
426 :
427 : void
428 3996 : ExpandVisitor::expand_struct_fields (std::vector<AST::StructField> &fields)
429 : {
430 3996 : expand_fields (fields);
431 3996 : }
432 :
433 : void
434 3194 : ExpandVisitor::expand_tuple_fields (std::vector<AST::TupleField> &fields)
435 : {
436 3194 : expand_fields (fields);
437 3194 : }
438 :
439 : // FIXME: This can definitely be refactored with the method above
440 : void
441 44967 : ExpandVisitor::expand_function_params (
442 : std::vector<std::unique_ptr<AST::Param>> ¶ms)
443 : {
444 94461 : for (auto &p : params)
445 49494 : visit (p);
446 44967 : }
447 :
448 : void
449 9103 : ExpandVisitor::expand_generic_args (AST::GenericArgs &args)
450 : {
451 18614 : for (auto &arg : args.get_generic_args ())
452 : {
453 9511 : switch (arg.get_kind ())
454 : {
455 3842 : case AST::GenericArg::Kind::Type:
456 3842 : maybe_expand_type (arg.get_type_ptr ());
457 3842 : break;
458 138 : case AST::GenericArg::Kind::Const:
459 138 : maybe_expand_expr (arg.get_expression_ptr ());
460 138 : 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 9297 : for (auto &binding : args.get_binding_args ())
475 194 : maybe_expand_type (binding.get_type_ptr ());
476 9103 : }
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 761 : ExpandVisitor::expand_where_clause (AST::WhereClause &where_clause)
502 : {
503 1542 : for (auto &item : where_clause.get_items ())
504 781 : visit (item);
505 761 : }
506 :
507 : void
508 10738 : ExpandVisitor::visit (AST::Crate &crate)
509 : {
510 10738 : expand_inner_items (crate.items);
511 10738 : }
512 :
513 : void
514 4503 : ExpandVisitor::visit (AST::DelimTokenTree &)
515 4503 : {}
516 :
517 : void
518 63 : ExpandVisitor::visit (AST::AttrInputMetaItemContainer &)
519 63 : {}
520 :
521 : void
522 55154 : ExpandVisitor::visit (AST::IdentifierExpr &ident_expr)
523 55154 : {}
524 :
525 : void
526 542 : ExpandVisitor::visit (AST::LifetimeParam &)
527 542 : {}
528 :
529 : void
530 200 : ExpandVisitor::visit (AST::ConstGenericParam &)
531 200 : {}
532 :
533 : void
534 2802 : ExpandVisitor::visit (AST::MacroInvocation ¯o_invoc)
535 : {
536 2802 : 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 4759 : expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ()
546 : ? AST::InvocKind::Semicoloned
547 : : AST::InvocKind::Expr);
548 2802 : }
549 :
550 : void
551 61978 : ExpandVisitor::visit (AST::PathInExpression &path)
552 : {
553 61978 : if (!path.is_lang_item ())
554 148571 : for (auto &segment : path.get_segments ())
555 173580 : if (segment.has_generic_args ())
556 2102 : expand_generic_args (segment.get_generic_args ());
557 61978 : }
558 :
559 : void
560 7003 : ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment)
561 : {
562 7003 : if (segment.has_generic_args ())
563 7001 : expand_generic_args (segment.get_generic_args ());
564 7003 : }
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 565972 : ExpandVisitor::visit (AST::LiteralExpr &expr)
600 565972 : {}
601 :
602 : void
603 8155 : ExpandVisitor::visit (AST::AttrInputLiteral &)
604 8155 : {}
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 54876 : ExpandVisitor::visit (AST::BlockExpr &expr)
634 : {
635 54876 : expand_inner_stmts (expr);
636 :
637 54876 : expand_tail_expr (expr, expander);
638 54876 : if (expr.has_tail_expr ())
639 40346 : maybe_expand_expr (expr.get_tail_expr_ptr ());
640 54876 : }
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 2571 : ExpandVisitor::visit (AST::IfExpr &expr)
654 : {
655 2571 : maybe_expand_expr (expr.get_condition_expr_ptr ());
656 :
657 2571 : visit (expr.get_if_block ());
658 2571 : }
659 :
660 : void
661 3162 : ExpandVisitor::visit (AST::IfExprConseqElse &expr)
662 : {
663 3162 : maybe_expand_expr (expr.get_condition_expr_ptr ());
664 :
665 3162 : visit (expr.get_if_block ());
666 3162 : visit (expr.get_else_block ());
667 3162 : }
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 11129 : ExpandVisitor::visit (AST::TypeParam ¶m)
688 : {
689 13105 : for (auto &bound : param.get_type_param_bounds ())
690 1976 : visit (bound);
691 :
692 11129 : if (param.has_type ())
693 923 : maybe_expand_type (param.get_type_ptr ());
694 11129 : }
695 :
696 : void
697 4 : ExpandVisitor::visit (AST::LifetimeWhereClauseItem &)
698 4 : {}
699 :
700 : void
701 777 : ExpandVisitor::visit (AST::TypeBoundWhereClauseItem &item)
702 : {
703 777 : maybe_expand_type (item.get_type_ptr ());
704 :
705 1554 : for (auto &bound : item.get_type_param_bounds ())
706 777 : visit (bound);
707 777 : }
708 :
709 : void
710 3189 : ExpandVisitor::visit (AST::Module &module)
711 : {
712 3189 : expand_inner_items (module.get_items ());
713 3189 : }
714 :
715 : void
716 48 : ExpandVisitor::visit (AST::ExternCrate &crate)
717 48 : {}
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 1842 : ExpandVisitor::visit (AST::UseDeclaration &use_decl)
733 1842 : {}
734 :
735 : void
736 44967 : ExpandVisitor::visit (AST::Function &function)
737 : {
738 44967 : if (function.has_body ())
739 34715 : visit_inner_using_attrs (
740 34715 : function, function.get_definition ().value ()->get_inner_attrs ());
741 49609 : for (auto ¶m : function.get_generic_params ())
742 4642 : visit (param);
743 :
744 44967 : expand_function_params (function.get_function_params ());
745 :
746 44967 : if (function.has_return_type ())
747 33074 : maybe_expand_type (function.get_return_type_ptr ());
748 :
749 44967 : if (function.has_where_clause ())
750 520 : expand_where_clause (function.get_where_clause ());
751 :
752 44967 : if (function.has_body ())
753 34715 : visit (*function.get_definition ());
754 44967 : }
755 :
756 : void
757 3563 : ExpandVisitor::visit (AST::StructStruct &struct_item)
758 : {
759 4752 : for (auto &generic : struct_item.get_generic_params ())
760 1189 : visit (generic);
761 :
762 3563 : if (struct_item.has_where_clause ())
763 4 : expand_where_clause (struct_item.get_where_clause ());
764 :
765 3563 : expand_struct_fields (struct_item.get_fields ());
766 3563 : }
767 :
768 : void
769 2080 : ExpandVisitor::visit (AST::TupleStruct &tuple_struct)
770 : {
771 2819 : for (auto &generic : tuple_struct.get_generic_params ())
772 739 : visit (generic);
773 :
774 2080 : if (tuple_struct.has_where_clause ())
775 0 : expand_where_clause (tuple_struct.get_where_clause ());
776 :
777 2080 : expand_tuple_fields (tuple_struct.get_fields ());
778 2080 : }
779 :
780 : void
781 1042 : ExpandVisitor::visit (AST::EnumItem &item)
782 1042 : {}
783 :
784 : void
785 1114 : ExpandVisitor::visit (AST::EnumItemTuple &item)
786 : {
787 1114 : expand_tuple_fields (item.get_tuple_fields ());
788 1114 : }
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 685 : ExpandVisitor::visit (AST::EnumItemDiscriminant &item)
798 : {
799 685 : maybe_expand_expr (item.get_expr_ptr ());
800 685 : }
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 8972 : ExpandVisitor::visit (AST::Trait &trait)
813 : {
814 10613 : for (auto &generic : trait.get_generic_params ())
815 1641 : visit (generic);
816 :
817 10648 : for (auto &bound : trait.get_type_param_bounds ())
818 1676 : visit (bound);
819 :
820 8972 : if (trait.has_where_clause ())
821 21 : expand_where_clause (trait.get_where_clause ());
822 :
823 8972 : expander.push_context (MacroExpander::ContextType::TRAIT);
824 :
825 8972 : expand_macro_children (MacroExpander::ContextType::TRAIT,
826 : trait.get_trait_items (),
827 : &AST::SingleASTNode::take_assoc_item);
828 :
829 8972 : expander.pop_context ();
830 8972 : }
831 :
832 : void
833 2193 : ExpandVisitor::visit (AST::InherentImpl &impl)
834 : {
835 4386 : visit_inner_attrs (impl);
836 : // just expand sub-stuff - can't actually strip generic params themselves
837 2967 : for (auto &generic : impl.get_generic_params ())
838 774 : visit (generic);
839 :
840 : // FIXME: Is that correct? How do we test that?
841 2193 : expander.push_context (MacroExpander::ContextType::ITEM);
842 :
843 2193 : maybe_expand_type (impl.get_type_ptr ());
844 :
845 2193 : expander.pop_context ();
846 :
847 2193 : if (impl.has_where_clause ())
848 2 : expand_where_clause (impl.get_where_clause ());
849 :
850 2193 : expand_macro_children (MacroExpander::ContextType::IMPL,
851 : impl.get_impl_items (),
852 : &AST::SingleASTNode::take_assoc_item);
853 2193 : }
854 :
855 : void
856 11580 : ExpandVisitor::visit (AST::TraitImpl &impl)
857 : {
858 23160 : visit_inner_attrs (impl);
859 : // just expand sub-stuff - can't actually strip generic params themselves
860 13478 : for (auto ¶m : impl.get_generic_params ())
861 1898 : visit (param);
862 :
863 : // FIXME: Is that correct? How do we test that?
864 11580 : expander.push_context (MacroExpander::ContextType::ITEM);
865 :
866 11580 : maybe_expand_type (impl.get_type_ptr ());
867 :
868 11580 : expander.pop_context ();
869 :
870 11580 : visit (impl.get_trait_path ());
871 :
872 11580 : if (impl.has_where_clause ())
873 214 : expand_where_clause (impl.get_where_clause ());
874 :
875 11580 : expand_macro_children (MacroExpander::ContextType::TRAIT_IMPL,
876 : impl.get_impl_items (),
877 : &AST::SingleASTNode::take_assoc_item);
878 11580 : }
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 3580 : ExpandVisitor::visit (AST::ExternBlock &block)
892 : {
893 7160 : visit_inner_attrs (block);
894 :
895 3580 : expand_macro_children (MacroExpander::ContextType::EXTERN,
896 : block.get_extern_items (),
897 : &AST::SingleASTNode::take_external_item);
898 3580 : }
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 3799 : ExpandVisitor::visit (AST::MacroRulesDefinition &rules_def)
910 3799 : {}
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 131 : ExpandVisitor::visit (AST::BareFunctionType &type)
934 : {
935 229 : for (auto ¶m : type.get_function_params ())
936 : {
937 98 : maybe_expand_type (param.get_type_ptr ());
938 : }
939 :
940 131 : if (type.has_return_type ())
941 97 : visit (type.get_return_type ());
942 131 : }
943 :
944 : void
945 27671 : ExpandVisitor::visit (AST::FunctionParam ¶m)
946 : {
947 27671 : maybe_expand_pattern (param.get_pattern_ptr ());
948 27671 : maybe_expand_type (param.get_type_ptr ());
949 27671 : }
950 :
951 : void
952 1751 : ExpandVisitor::visit (AST::VariadicParam ¶m)
953 : {
954 1751 : if (param.has_pattern ())
955 22 : maybe_expand_pattern (param.get_pattern_ptr ());
956 1751 : }
957 :
958 : void
959 20072 : ExpandVisitor::visit (AST::SelfParam ¶m)
960 : {
961 : /* TODO: maybe check for invariants being violated - e.g. both type and
962 : * lifetime? */
963 20072 : if (param.has_type ())
964 2 : maybe_expand_type (param.get_type_ptr ());
965 20072 : }
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 52068 : ExpandVisitor::visit_inner_using_attrs (T &item,
978 : std::vector<AST::Attribute> &attrs)
979 : {
980 52068 : 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 52068 : }
995 :
996 : template <typename T>
997 : void
998 3580 : ExpandVisitor::visit_inner_attrs (T &item)
999 : {
1000 17353 : visit_inner_using_attrs (item, item.get_inner_attrs ());
1001 : }
1002 :
1003 : } // namespace Rust
|