LCOV - code coverage report
Current view: top level - gcc/rust/expand - rust-expand-visitor.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.5 % 483 418
Test Date: 2026-10-24 16:24:59 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      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>> &params)
     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> &params)
     494              : {
     495        24193 :   for (auto &param : 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 &macro_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 &param)
     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 &param : 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 &param : 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 &param : 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 &param)
     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 &param)
     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 &param)
     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
        

Generated by: LCOV version 2.5.0-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.