LCOV - code coverage report
Current view: top level - gcc/rust/expand - rust-expand-visitor.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 83.7 % 479 401
Test Date: 2026-09-12 16:25:28 Functions: 80.5 % 82 66
Legend: Lines:     hit not hit

            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>> &params)
     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> &params)
     485              : {
     486        22975 :   for (auto &param : 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 &macro_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 &param)
     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 &param : 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 &param : 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 &param : 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 &param)
     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 &param)
     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 &param)
     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
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.