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 1197961 : is_builtin (AST::Attribute &attr)
33 : {
34 1197961 : auto &segments = attr.get_path ().get_segments ();
35 1197961 : return !segments.empty ()
36 1197961 : && !Analysis::BuiltinAttributeMappings::get ()
37 1197961 : ->lookup_builtin (segments[0].get_segment_name ())
38 1197961 : .is_error ();
39 : }
40 :
41 : /* Expand all of the macro invocations currently contained in a crate */
42 : void
43 11235 : ExpandVisitor::go (AST::Crate &crate)
44 : {
45 11235 : visit (crate);
46 11235 : }
47 :
48 : static std::vector<std::unique_ptr<AST::Item>>
49 1056 : builtin_derive_item (AST::Item &item, const AST::Attribute &derive,
50 : BuiltinMacro to_derive, MacroExpander &expander)
51 : {
52 1056 : auto item_source = AST::Builder::get_item_source (expander.crate);
53 :
54 1056 : auto items
55 1056 : = AST::DeriveVisitor::derive (item, derive, to_derive, item_source);
56 :
57 2416 : for (auto &item : items)
58 1360 : Analysis::Mappings::get ().add_derived_node (item->get_node_id ());
59 :
60 1056 : 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 612918 : expand_tail_expr (AST::BlockExpr &block_expr, MacroExpander &expander)
142 : {
143 612918 : if (block_expr.has_tail_expr ())
144 : {
145 533786 : auto tail = block_expr.take_tail_expr ();
146 533786 : auto attrs = tail->get_outer_attrs ();
147 533786 : bool changed = false;
148 536353 : for (auto it = attrs.begin (); it != attrs.end ();)
149 : {
150 2567 : auto current = *it;
151 2567 : if (is_builtin (current))
152 : {
153 2567 : 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 2567 : }
167 533786 : if (changed)
168 0 : block_expr.normalize_tail_expr ();
169 : else
170 533786 : block_expr.set_tail_expr (std::move (tail));
171 533786 : }
172 612918 : }
173 :
174 : void
175 22658 : ExpandVisitor::expand_inner_items (
176 : std::vector<std::unique_ptr<AST::Item>> &items)
177 : {
178 22658 : expander.push_context (MacroExpander::ContextType::ITEM);
179 :
180 462948 : for (auto it = items.begin (); it != items.end (); it++)
181 : {
182 440290 : Rust::AST::Item &item = **it;
183 440290 : if (item.has_outer_attrs ())
184 : {
185 297704 : auto &attrs = item.get_outer_attrs ();
186 :
187 1479134 : for (auto attr_it = attrs.begin (); attr_it != attrs.end ();
188 : /* erase => No increment*/)
189 : {
190 1181431 : auto current = *attr_it;
191 :
192 1181431 : if (current.is_derive ())
193 : {
194 403 : current.parse_attr_to_meta_item ();
195 403 : attr_it = attrs.erase (attr_it);
196 : // Get traits to derive in the current attribute
197 403 : auto traits_to_derive = current.get_traits_to_derive ();
198 1464 : for (auto &to_derive : traits_to_derive)
199 : {
200 1061 : auto maybe_builtin = MacroBuiltin::builtins.lookup (
201 1061 : to_derive.get ().as_string ());
202 1061 : if (maybe_builtin.has_value ())
203 : {
204 1056 : auto new_items
205 : = builtin_derive_item (item, current,
206 1056 : maybe_builtin.value (),
207 1056 : expander);
208 :
209 2416 : for (auto &&new_item : new_items)
210 1360 : it = items.insert (it, std::move (new_item));
211 1056 : }
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 403 : }
223 : else /* Attribute */
224 : {
225 1181028 : if (is_builtin (current))
226 : {
227 1181027 : visit (*attr_it);
228 1181027 : 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 1181431 : }
247 : }
248 : }
249 :
250 22658 : expand_macro_children (items, &AST::SingleASTNode::take_item);
251 :
252 22658 : expander.pop_context ();
253 22658 : }
254 :
255 : void
256 612918 : ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr)
257 : {
258 612918 : auto &stmts = expr.get_statements ();
259 612918 : expander.push_context (MacroExpander::ContextType::STMT);
260 :
261 958071 : for (auto it = stmts.begin (); it != stmts.end (); it++)
262 : {
263 345153 : auto &stmt = *it;
264 :
265 : // skip all non-item statements
266 345153 : if (stmt->get_stmt_kind () != AST::Stmt::Kind::Item)
267 306432 : continue;
268 :
269 38721 : auto &item = static_cast<AST::Item &> (*stmt.get ());
270 :
271 38721 : if (item.has_outer_attrs ())
272 : {
273 13561 : auto &attrs = item.get_outer_attrs ();
274 :
275 27891 : for (auto attr_it = attrs.begin (); attr_it != attrs.end ();
276 : /* erase => No increment*/)
277 : {
278 14331 : auto current = *attr_it;
279 :
280 14331 : if (current.is_derive ())
281 : {
282 0 : attr_it = attrs.erase (attr_it);
283 : // Get traits to derive in the current attribute
284 0 : auto traits_to_derive = current.get_traits_to_derive ();
285 0 : for (auto &to_derive : traits_to_derive)
286 : {
287 0 : auto maybe_builtin = MacroBuiltin::builtins.lookup (
288 0 : to_derive.get ().as_string ());
289 0 : if (maybe_builtin.has_value ())
290 : {
291 0 : auto new_items
292 : = builtin_derive_item (item, current,
293 0 : maybe_builtin.value (),
294 0 : expander);
295 :
296 : // this inserts the derive *before* the item - is it a
297 : // problem?
298 0 : for (auto &&new_item : new_items)
299 0 : it = stmts.insert (it, std::move (new_item));
300 0 : }
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 0 : }
310 : else /* Attribute */
311 : {
312 14331 : if (is_builtin (current))
313 : {
314 14330 : visit (*attr_it);
315 14330 : 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 14331 : }
334 : }
335 : }
336 :
337 612918 : if (!expr.has_tail_expr ())
338 79217 : expr.normalize_tail_expr ();
339 :
340 612918 : expand_macro_children (stmts, &AST::SingleASTNode::take_stmt);
341 :
342 612918 : expander.pop_context ();
343 612918 : }
344 :
345 : void
346 3178241 : ExpandVisitor::visit (AST::Attribute &attr)
347 : {
348 : // An attribute input containing a macro may have been expanded to a literal
349 3178241 : if (attr.has_attr_input ()
350 3178241 : && 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 3178241 : AST::DefaultASTVisitor::visit (attr);
361 3178241 : }
362 :
363 : void
364 18937104 : ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
365 : {
366 18937104 : NodeId old_expect = expr->get_node_id ();
367 18937104 : std::swap (macro_invoc_expect_id, old_expect);
368 :
369 18937104 : expander.push_context (MacroExpander::ContextType::EXPR);
370 18937104 : expr->accept_vis (*this);
371 18937104 : expander.pop_context ();
372 :
373 18937104 : std::swap (macro_invoc_expect_id, old_expect);
374 :
375 18937104 : auto final_fragment = expander.take_expanded_fragment ();
376 18937104 : if (final_fragment.should_expand ()
377 18937104 : && final_fragment.is_expression_fragment ())
378 52320 : expr = final_fragment.take_expression_fragment ();
379 18937104 : }
380 :
381 : void
382 1890255 : ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
383 : {
384 1890255 : NodeId old_expect = type->get_node_id ();
385 1890255 : std::swap (macro_invoc_expect_id, old_expect);
386 :
387 1890255 : expander.push_context (MacroExpander::ContextType::TYPE);
388 1890255 : type->accept_vis (*this);
389 1890255 : expander.pop_context ();
390 :
391 1890255 : std::swap (macro_invoc_expect_id, old_expect);
392 :
393 1890255 : auto final_fragment = expander.take_expanded_fragment ();
394 1890255 : if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
395 496 : type = final_fragment.take_type_fragment ();
396 1890255 : }
397 :
398 : // HACK: maybe we shouldn't have TypeNoBounds as a base class
399 : void
400 447112 : ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type)
401 : {
402 447112 : NodeId old_expect = type->get_node_id ();
403 447112 : std::swap (macro_invoc_expect_id, old_expect);
404 :
405 447112 : expander.push_context (MacroExpander::ContextType::TYPE);
406 447112 : type->accept_vis (*this);
407 447112 : expander.pop_context ();
408 :
409 447112 : std::swap (macro_invoc_expect_id, old_expect);
410 :
411 447112 : auto final_fragment = expander.take_expanded_fragment ();
412 447112 : 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 447112 : }
416 :
417 : void
418 2545561 : ExpandVisitor::maybe_expand_pattern (std::unique_ptr<AST::Pattern> &pattern)
419 : {
420 2545561 : NodeId old_expect = pattern->get_node_id ();
421 2545561 : std::swap (macro_invoc_expect_id, old_expect);
422 :
423 2545561 : expander.push_context (MacroExpander::ContextType::PATTERN);
424 2545561 : pattern->accept_vis (*this);
425 2545561 : expander.pop_context ();
426 :
427 2545561 : std::swap (macro_invoc_expect_id, old_expect);
428 :
429 2545561 : auto final_fragment = expander.take_expanded_fragment ();
430 2545561 : if (final_fragment.should_expand () && final_fragment.is_pattern_fragment ())
431 1 : pattern = final_fragment.take_pattern_fragment ();
432 2545561 : }
433 :
434 : // FIXME: This can definitely be refactored with the method above
435 : void
436 459942 : ExpandVisitor::expand_function_params (
437 : std::vector<std::unique_ptr<AST::Param>> ¶ms)
438 : {
439 1283322 : for (auto &p : params)
440 823380 : visit (p);
441 459942 : }
442 :
443 : void
444 495493 : ExpandVisitor::expand_generic_args (AST::GenericArgs &args)
445 : {
446 982027 : for (auto &arg : args.get_generic_args ())
447 : {
448 486534 : switch (arg.get_kind ())
449 : {
450 153808 : case AST::GenericArg::Kind::Type:
451 153808 : maybe_expand_type (arg.get_type_ptr ());
452 153808 : 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 504514 : for (auto &binding : args.get_binding_args ())
470 9021 : maybe_expand_type (binding.get_type_ptr ());
471 495493 : }
472 :
473 : void
474 106688 : ExpandVisitor::expand_qualified_path_type (AST::QualifiedPathType &path_type)
475 : {
476 106688 : maybe_expand_type (path_type.get_type_ptr ());
477 :
478 : // FIXME: ARTHUR: Can we do macro expansion in there? Needs a test!
479 106688 : if (path_type.has_as_clause ())
480 104057 : path_type.get_as_type_path ().accept_vis (*this);
481 106688 : }
482 :
483 : void
484 10459 : ExpandVisitor::expand_closure_params (std::vector<AST::ClosureParam> ¶ms)
485 : {
486 22975 : for (auto ¶m : params)
487 : {
488 12516 : maybe_expand_pattern (param.get_pattern_ptr ());
489 :
490 12516 : if (param.has_type_given ())
491 711 : maybe_expand_type (param.get_type_ptr ());
492 : }
493 10459 : }
494 :
495 : void
496 27676 : ExpandVisitor::expand_where_clause (AST::WhereClause &where_clause)
497 : {
498 65182 : for (auto &item : where_clause.get_items ())
499 37506 : visit (item);
500 27676 : }
501 :
502 : void
503 11235 : ExpandVisitor::visit (AST::Crate &crate)
504 : {
505 11235 : expand_inner_items (crate.items);
506 11235 : }
507 :
508 : void
509 623748 : ExpandVisitor::visit (AST::DelimTokenTree &)
510 623748 : {}
511 :
512 : void
513 3801 : ExpandVisitor::visit (AST::AttrInputMetaItemContainer &)
514 3801 : {}
515 :
516 : void
517 4025530 : ExpandVisitor::visit (AST::IdentifierExpr &ident_expr)
518 4025530 : {}
519 :
520 : void
521 40387 : ExpandVisitor::visit (AST::LifetimeParam &)
522 40387 : {}
523 :
524 : void
525 2844 : ExpandVisitor::visit (AST::ConstGenericParam &)
526 2844 : {}
527 :
528 : void
529 58709 : ExpandVisitor::visit (AST::MacroInvocation ¯o_invoc)
530 : {
531 58709 : 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 111620 : expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ()
541 : ? AST::InvocKind::Semicoloned
542 : : AST::InvocKind::Expr);
543 58709 : }
544 :
545 : void
546 2499638 : ExpandVisitor::visit (AST::PathInExpression &path)
547 : {
548 2499638 : if (!path.is_lang_item ())
549 5367125 : for (auto &segment : path.get_segments ())
550 5747932 : if (segment.has_generic_args ())
551 16525 : expand_generic_args (segment.get_generic_args ());
552 2499638 : }
553 :
554 : void
555 478970 : ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment)
556 : {
557 478970 : if (segment.has_generic_args ())
558 478968 : expand_generic_args (segment.get_generic_args ());
559 478970 : }
560 :
561 : void
562 17671 : ExpandVisitor::visit (AST::TypePathSegmentFunction &segment)
563 : {
564 17671 : auto &type_path_function = segment.get_type_path_function ();
565 :
566 42234 : for (auto &type : type_path_function.get_params ())
567 24563 : visit (type);
568 :
569 17671 : if (type_path_function.has_return_type ())
570 17074 : maybe_expand_type (type_path_function.get_return_type_ptr ());
571 17671 : }
572 :
573 : void
574 3644 : ExpandVisitor::visit (AST::QualifiedPathInExpression &path)
575 : {
576 3644 : expand_qualified_path_type (path.get_qualified_path_type ());
577 :
578 7288 : for (auto &segment : path.get_segments ())
579 7288 : if (segment.has_generic_args ())
580 0 : expand_generic_args (segment.get_generic_args ());
581 3644 : }
582 :
583 : void
584 103044 : ExpandVisitor::visit (AST::QualifiedPathInType &path)
585 : {
586 103044 : expand_qualified_path_type (path.get_qualified_path_type ());
587 :
588 : // this shouldn't strip any segments, but can strip inside them
589 103044 : for (auto &segment : path.get_segments ())
590 0 : visit (segment);
591 103044 : }
592 :
593 : void
594 6314430 : ExpandVisitor::visit (AST::LiteralExpr &expr)
595 6314430 : {}
596 :
597 : void
598 2147704 : ExpandVisitor::visit (AST::AttrInputLiteral &)
599 2147704 : {}
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 997 : ExpandVisitor::visit (AST::StructExprStruct &expr)
617 997 : {}
618 :
619 : void
620 10364 : ExpandVisitor::visit (AST::ClosureExprInner &expr)
621 : {
622 10364 : expand_closure_params (expr.get_params ());
623 :
624 10364 : maybe_expand_expr (expr.get_definition_expr_ptr ());
625 10364 : }
626 :
627 : void
628 612918 : ExpandVisitor::visit (AST::BlockExpr &expr)
629 : {
630 612918 : expand_inner_stmts (expr);
631 :
632 612918 : expand_tail_expr (expr, expander);
633 612918 : if (expr.has_tail_expr ())
634 533786 : maybe_expand_expr (expr.get_tail_expr_ptr ());
635 612918 : }
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 24314 : ExpandVisitor::visit (AST::IfExpr &expr)
649 : {
650 24314 : maybe_expand_expr (expr.get_condition_expr_ptr ());
651 :
652 24314 : visit (expr.get_if_block ());
653 24314 : }
654 :
655 : void
656 39707 : ExpandVisitor::visit (AST::IfExprConseqElse &expr)
657 : {
658 39707 : maybe_expand_expr (expr.get_condition_expr_ptr ());
659 :
660 39707 : visit (expr.get_if_block ());
661 39707 : visit (expr.get_else_block ());
662 39707 : }
663 :
664 : void
665 2169 : ExpandVisitor::visit (AST::IfLetExpr &expr)
666 : {
667 2169 : maybe_expand_expr (expr.get_value_expr_ptr ());
668 :
669 2169 : visit (expr.get_if_block ());
670 2169 : }
671 :
672 : void
673 1074 : ExpandVisitor::visit (AST::IfLetExprConseqElse &expr)
674 : {
675 1074 : maybe_expand_expr (expr.get_value_expr_ptr ());
676 :
677 1074 : visit (expr.get_if_block ());
678 1074 : visit (expr.get_else_block ());
679 1074 : }
680 :
681 : void
682 263660 : ExpandVisitor::visit (AST::TypeParam ¶m)
683 : {
684 340925 : for (auto &bound : param.get_type_param_bounds ())
685 77265 : visit (bound);
686 :
687 263660 : if (param.has_type ())
688 1873 : maybe_expand_type (param.get_type_ptr ());
689 263660 : }
690 :
691 : void
692 39 : ExpandVisitor::visit (AST::LifetimeWhereClauseItem &)
693 39 : {}
694 :
695 : void
696 37895 : ExpandVisitor::visit (AST::TypeBoundWhereClauseItem &item)
697 : {
698 37895 : maybe_expand_type (item.get_type_ptr ());
699 :
700 77536 : for (auto &bound : item.get_type_param_bounds ())
701 39641 : visit (bound);
702 37895 : }
703 :
704 : void
705 11423 : ExpandVisitor::visit (AST::Module &module)
706 : {
707 11423 : expand_inner_items (module.get_items ());
708 11423 : }
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 25556 : ExpandVisitor::visit (AST::UseDeclaration &use_decl)
728 25556 : {}
729 :
730 : void
731 459942 : ExpandVisitor::visit (AST::Function &function)
732 : {
733 459942 : visit_outer_attrs (function);
734 : // TODO: handle body inner attributes more regularly?
735 : // apparently, they should be applied to this function
736 459942 : if (function.has_body ())
737 415079 : visit_inner_using_attrs (
738 415079 : function, function.get_definition ().value ()->get_inner_attrs ());
739 516088 : for (auto ¶m : function.get_generic_params ())
740 56146 : visit (param);
741 :
742 459942 : expand_function_params (function.get_function_params ());
743 :
744 459942 : if (function.has_return_type ())
745 394275 : maybe_expand_type (function.get_return_type_ptr ());
746 :
747 459942 : if (function.has_where_clause ())
748 15137 : expand_where_clause (function.get_where_clause ());
749 :
750 459942 : if (function.has_body ())
751 415079 : visit (*function.get_definition ());
752 459942 : }
753 :
754 : void
755 3149 : ExpandVisitor::visit (AST::EnumItem &item)
756 3149 : {}
757 :
758 : void
759 798 : ExpandVisitor::visit (AST::EnumItemDiscriminant &item)
760 : {
761 798 : maybe_expand_expr (item.get_expr_ptr ());
762 798 : }
763 :
764 : void
765 13942 : ExpandVisitor::visit (AST::Trait &trait)
766 : {
767 17660 : for (auto &generic : trait.get_generic_params ())
768 3718 : visit (generic);
769 :
770 18113 : for (auto &bound : trait.get_type_param_bounds ())
771 4171 : visit (bound);
772 :
773 13942 : if (trait.has_where_clause ())
774 21 : expand_where_clause (trait.get_where_clause ());
775 :
776 13942 : expander.push_context (MacroExpander::ContextType::TRAIT);
777 :
778 13942 : expand_macro_children (MacroExpander::ContextType::TRAIT,
779 : trait.get_trait_items (),
780 : &AST::SingleASTNode::take_assoc_item);
781 :
782 13942 : expander.pop_context ();
783 13942 : }
784 :
785 : void
786 12363 : ExpandVisitor::visit (AST::InherentImpl &impl)
787 : {
788 24726 : visit_inner_attrs (impl);
789 : // just expand sub-stuff - can't actually strip generic params themselves
790 22352 : for (auto &generic : impl.get_generic_params ())
791 9989 : visit (generic);
792 :
793 : // FIXME: Is that correct? How do we test that?
794 12363 : expander.push_context (MacroExpander::ContextType::ITEM);
795 :
796 12363 : maybe_expand_type (impl.get_type_ptr ());
797 :
798 12363 : expander.pop_context ();
799 :
800 12363 : if (impl.has_where_clause ())
801 107 : expand_where_clause (impl.get_where_clause ());
802 :
803 12363 : expand_macro_children (MacroExpander::ContextType::IMPL,
804 : impl.get_impl_items (),
805 : &AST::SingleASTNode::take_assoc_item);
806 12363 : }
807 :
808 : void
809 235048 : ExpandVisitor::visit (AST::TraitImpl &impl)
810 : {
811 470096 : visit_inner_attrs (impl);
812 : // just expand sub-stuff - can't actually strip generic params themselves
813 458171 : for (auto ¶m : impl.get_generic_params ())
814 223123 : visit (param);
815 :
816 : // FIXME: Is that correct? How do we test that?
817 235048 : expander.push_context (MacroExpander::ContextType::ITEM);
818 :
819 235048 : maybe_expand_type (impl.get_type_ptr ());
820 :
821 235048 : expander.pop_context ();
822 :
823 235048 : visit (impl.get_trait_path ());
824 :
825 235048 : if (impl.has_where_clause ())
826 12411 : expand_where_clause (impl.get_where_clause ());
827 :
828 235048 : expand_macro_children (MacroExpander::ContextType::TRAIT_IMPL,
829 : impl.get_impl_items (),
830 : &AST::SingleASTNode::take_assoc_item);
831 235048 : }
832 :
833 : void
834 39 : ExpandVisitor::visit (AST::ExternalTypeItem &item)
835 39 : {}
836 :
837 : void
838 5264 : ExpandVisitor::visit (AST::ExternBlock &block)
839 : {
840 10528 : visit_inner_attrs (block);
841 :
842 5264 : expand_macro_children (MacroExpander::ContextType::EXTERN,
843 : block.get_extern_items (),
844 : &AST::SingleASTNode::take_external_item);
845 5264 : }
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 28913 : ExpandVisitor::visit (AST::MacroRulesDefinition &rules_def)
857 28913 : {}
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 651 : ExpandVisitor::visit (AST::StructPatternFieldIdent &field)
877 651 : {}
878 :
879 : void
880 18218 : ExpandVisitor::visit (AST::BareFunctionType &type)
881 : {
882 127062 : for (auto ¶m : type.get_function_params ())
883 : {
884 108844 : maybe_expand_type (param.get_type_ptr ());
885 : }
886 :
887 18218 : if (type.has_return_type ())
888 17898 : visit (type.get_return_type ());
889 18218 : }
890 :
891 : void
892 527905 : ExpandVisitor::visit (AST::FunctionParam ¶m)
893 : {
894 527905 : maybe_expand_pattern (param.get_pattern_ptr ());
895 527905 : maybe_expand_type (param.get_type_ptr ());
896 527905 : }
897 :
898 : void
899 1867 : ExpandVisitor::visit (AST::VariadicParam ¶m)
900 : {
901 1867 : if (param.has_pattern ())
902 22 : maybe_expand_pattern (param.get_pattern_ptr ());
903 1867 : }
904 :
905 : void
906 293608 : ExpandVisitor::visit (AST::SelfParam ¶m)
907 : {
908 : /* TODO: maybe check for invariants being violated - e.g. both type and
909 : * lifetime? */
910 293608 : if (param.has_type ())
911 461 : maybe_expand_type (param.get_type_ptr ());
912 293608 : }
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 667754 : ExpandVisitor::visit_inner_using_attrs (T &item,
925 : std::vector<AST::Attribute> &attrs)
926 : {
927 667824 : 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 667754 : }
942 :
943 : template <typename T>
944 : void
945 5264 : ExpandVisitor::visit_inner_attrs (T &item)
946 : {
947 252675 : visit_inner_using_attrs (item, item.get_inner_attrs ());
948 : }
949 :
950 : } // namespace Rust
|