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