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