LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-ast.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 33.1 % 2493 826
Test Date: 2026-04-20 14:57:17 Functions: 49.8 % 329 164
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* General AST-related method implementations for Rust frontend.
       2              :    Copyright (C) 2009-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : #include "rust-ast.h"
      21              : #include "optional.h"
      22              : #include "rust-builtin-ast-nodes.h"
      23              : #include "rust-common.h"
      24              : #include "rust-expr.h"
      25              : #include "rust-system.h"
      26              : #include "rust-ast-full.h"
      27              : #include "rust-diagnostics.h"
      28              : #include "rust-ast-visitor.h"
      29              : #include "rust-macro.h"
      30              : #include "rust-session-manager.h"
      31              : #include "rust-lex.h"
      32              : #include "rust-parse.h"
      33              : #include "rust-operators.h"
      34              : #include "rust-dir-owner.h"
      35              : #include "rust-attribute-values.h"
      36              : #include "rust-macro-invoc-lexer.h"
      37              : 
      38              : /* Compilation unit used for various AST-related functions that would make
      39              :  * the headers too long if they were defined inline and don't receive any
      40              :  * benefits from being defined inline because they are virtual. Also used
      41              :  * for various other stuff. */
      42              : 
      43              : namespace Rust {
      44              : namespace AST {
      45              : 
      46        23258 : SingleASTNode::SingleASTNode (SingleASTNode const &other)
      47              : {
      48        23258 :   kind = other.kind;
      49        23258 :   switch (kind)
      50              :     {
      51        10374 :     case Kind::Expr:
      52        10374 :       expr = other.expr->clone_expr ();
      53        10374 :       break;
      54              : 
      55        10376 :     case Kind::Item:
      56        10376 :       item = other.item->clone_item ();
      57        10376 :       break;
      58              : 
      59         1918 :     case Kind::Stmt:
      60         1918 :       stmt = other.stmt->clone_stmt ();
      61         1918 :       break;
      62              : 
      63           12 :     case Kind::Extern:
      64           12 :       external_item = other.external_item->clone_external_item ();
      65           12 :       break;
      66              : 
      67          428 :     case Kind::Assoc:
      68          428 :       assoc_item = other.assoc_item->clone_associated_item ();
      69          428 :       break;
      70              : 
      71          145 :     case Kind::Type:
      72          145 :       type = other.type->clone_type ();
      73          145 :       break;
      74              : 
      75            5 :     case Kind::Pattern:
      76            5 :       pattern = other.pattern->clone_pattern ();
      77            5 :       break;
      78              :     }
      79        23258 : }
      80              : 
      81              : SingleASTNode
      82            0 : SingleASTNode::operator= (SingleASTNode const &other)
      83              : {
      84            0 :   kind = other.kind;
      85            0 :   switch (kind)
      86              :     {
      87            0 :     case Kind::Expr:
      88            0 :       expr = other.expr->clone_expr ();
      89            0 :       break;
      90              : 
      91            0 :     case Kind::Item:
      92            0 :       item = other.item->clone_item ();
      93            0 :       break;
      94              : 
      95            0 :     case Kind::Stmt:
      96            0 :       stmt = other.stmt->clone_stmt ();
      97            0 :       break;
      98              : 
      99            0 :     case Kind::Extern:
     100            0 :       external_item = other.external_item->clone_external_item ();
     101            0 :       break;
     102              : 
     103            0 :     case Kind::Assoc:
     104            0 :       assoc_item = other.assoc_item->clone_associated_item ();
     105            0 :       break;
     106              : 
     107            0 :     case Kind::Type:
     108            0 :       type = other.type->clone_type ();
     109            0 :       break;
     110              : 
     111            0 :     case Kind::Pattern:
     112            0 :       pattern = other.pattern->clone_pattern ();
     113            0 :       break;
     114              :     }
     115            0 :   return *this;
     116              : }
     117              : 
     118              : void
     119            0 : SingleASTNode::accept_vis (ASTVisitor &vis)
     120              : {
     121            0 :   switch (kind)
     122              :     {
     123            0 :     case Kind::Expr:
     124            0 :       expr->accept_vis (vis);
     125            0 :       break;
     126              : 
     127            0 :     case Kind::Item:
     128            0 :       item->accept_vis (vis);
     129            0 :       break;
     130              : 
     131            0 :     case Kind::Stmt:
     132            0 :       stmt->accept_vis (vis);
     133            0 :       break;
     134              : 
     135            0 :     case Kind::Extern:
     136            0 :       external_item->accept_vis (vis);
     137            0 :       break;
     138              : 
     139            0 :     case Kind::Assoc:
     140            0 :       assoc_item->accept_vis (vis);
     141            0 :       break;
     142              : 
     143            0 :     case Kind::Type:
     144            0 :       type->accept_vis (vis);
     145            0 :       break;
     146              : 
     147            0 :     case Kind::Pattern:
     148            0 :       pattern->accept_vis (vis);
     149            0 :       break;
     150              :     }
     151            0 : }
     152              : 
     153              : bool
     154         8254 : SingleASTNode::is_error ()
     155              : {
     156         8254 :   switch (kind)
     157              :     {
     158         1917 :     case Kind::Expr:
     159         1917 :       return expr == nullptr;
     160         5182 :     case Kind::Item:
     161         5182 :       return item == nullptr;
     162          905 :     case Kind::Stmt:
     163          905 :       return stmt == nullptr;
     164            6 :     case Kind::Extern:
     165            6 :       return external_item == nullptr;
     166          214 :     case Kind::Assoc:
     167          214 :       return assoc_item == nullptr;
     168           29 :     case Kind::Type:
     169           29 :       return type == nullptr;
     170            1 :     case Kind::Pattern:
     171            1 :       return pattern == nullptr;
     172              :     }
     173              : 
     174            0 :   rust_unreachable ();
     175              :   return true;
     176              : }
     177              : 
     178              : std::string
     179            0 : SingleASTNode::as_string () const
     180              : {
     181            0 :   switch (kind)
     182              :     {
     183            0 :     case Kind::Expr:
     184            0 :       return "Expr: " + expr->as_string ();
     185            0 :     case Kind::Item:
     186            0 :       return "Item: " + item->as_string ();
     187            0 :     case Kind::Stmt:
     188            0 :       return "Stmt: " + stmt->as_string ();
     189            0 :     case Kind::Extern:
     190            0 :       return "External Item: " + external_item->as_string ();
     191            0 :     case Kind::Assoc:
     192            0 :       return "Associated Item: " + assoc_item->as_string ();
     193            0 :     case Kind::Type:
     194            0 :       return "Type: " + type->as_string ();
     195            0 :     case Kind::Pattern:
     196            0 :       return "Pattern: " + pattern->as_string ();
     197              :     }
     198              : 
     199            0 :   rust_unreachable ();
     200              :   return "";
     201              : }
     202              : 
     203              : std::string
     204            0 : Crate::as_string () const
     205              : {
     206            0 :   rust_debug ("beginning crate recursive as-string");
     207              : 
     208            0 :   std::string str ("Crate: ");
     209              : 
     210              :   // inner attributes
     211            0 :   str += append_attributes (inner_attrs, INNER);
     212              : 
     213              :   // items
     214            0 :   str += "\n items: ";
     215            0 :   if (items.empty ())
     216              :     {
     217            0 :       str += "none";
     218              :     }
     219              :   else
     220              :     {
     221            0 :       for (const auto &item : items)
     222              :         {
     223              :           // DEBUG: null pointer check
     224            0 :           if (item == nullptr)
     225              :             {
     226            0 :               rust_debug ("something really terrible has gone wrong - "
     227              :                           "null pointer item in crate.");
     228            0 :               return "NULL_POINTER_MARK";
     229              :             }
     230              : 
     231            0 :           str += "\n  " + item->as_string ();
     232              :         }
     233              :     }
     234              : 
     235            0 :   return str + "\n";
     236            0 : }
     237              : 
     238              : void
     239            0 : Crate::inject_extern_crate (std::string name)
     240              : {
     241            0 :   items.push_back (std::make_unique<AST::ExternCrate> (
     242            0 :     AST::ExternCrate (name, AST::Visibility::create_public (UNKNOWN_LOCATION),
     243            0 :                       {}, UNKNOWN_LOCATION)));
     244            0 : }
     245              : 
     246              : void
     247            1 : Crate::inject_inner_attribute (Attribute attribute)
     248              : {
     249            1 :   inner_attrs.push_back (attribute);
     250            1 : }
     251              : 
     252              : std::string
     253        11480 : Attribute::as_string () const
     254              : {
     255        11480 :   std::string path_str = path.as_string ();
     256        11480 :   if (attr_input == nullptr)
     257         4670 :     return path_str;
     258              :   else
     259         6810 :     return path_str + attr_input->as_string ();
     260        11480 : }
     261              : 
     262              : void
     263            0 : Attribute::accept_vis (ASTVisitor &vis)
     264              : {
     265            0 :   vis.visit (*this);
     266            0 : }
     267              : 
     268              : bool
     269        83871 : Attribute::is_derive () const
     270              : {
     271       152322 :   return has_attr_input () && get_path () == Values::Attributes::DERIVE_ATTR;
     272              : }
     273              : 
     274              : /**
     275              :  * Returns a list of traits to derive from within a given attribute.
     276              :  *
     277              :  * @param attrs The attributes on the item to derive
     278              :  */
     279              : std::vector<std::reference_wrapper<AST::SimplePath>>
     280          338 : Attribute::get_traits_to_derive ()
     281              : {
     282          338 :   rust_assert (this->is_derive ());
     283              : 
     284          338 :   this->parse_attr_to_meta_item ();
     285          338 :   std::vector<std::reference_wrapper<AST::SimplePath>> result;
     286          338 :   auto &input = get_attr_input ();
     287          338 :   switch (input.get_attr_input_type ())
     288              :     {
     289          338 :     case AST::AttrInput::META_ITEM:
     290          338 :       {
     291          338 :         auto &meta = static_cast<AST::AttrInputMetaItemContainer &> (input);
     292          946 :         for (auto &current : meta.get_items ())
     293              :           {
     294              :             // HACK: Find a better way to achieve the downcast.
     295          608 :             switch (current->get_kind ())
     296              :               {
     297          608 :               case AST::MetaItemInner::Kind::MetaItem:
     298          608 :                 {
     299              :                   // Let raw pointer go out of scope without freeing, it doesn't
     300              :                   // own the data anyway
     301          608 :                   auto meta_item
     302          608 :                     = static_cast<AST::MetaItem *> (current.get ());
     303          608 :                   switch (meta_item->get_item_kind ())
     304              :                     {
     305          304 :                     case AST::MetaItem::ItemKind::Path:
     306          304 :                       {
     307          304 :                         auto path
     308              :                           = static_cast<AST::MetaItemPath *> (meta_item);
     309          304 :                         result.push_back (path->get_path ());
     310              :                       }
     311          304 :                       break;
     312          304 :                     case AST::MetaItem::ItemKind::Word:
     313          304 :                       {
     314          304 :                         auto word = static_cast<AST::MetaWord *> (meta_item);
     315              :                         // Convert current word to path
     316          304 :                         current = std::make_unique<AST::MetaItemPath> (
     317          608 :                           AST::MetaItemPath (AST::SimplePath::from_str (
     318          304 :                             word->get_ident ().as_string (),
     319          608 :                             word->get_locus ())));
     320          304 :                         auto path
     321          304 :                           = static_cast<AST::MetaItemPath *> (current.get ());
     322              : 
     323          304 :                         result.push_back (path->get_path ());
     324              :                       }
     325          304 :                       break;
     326            0 :                     case AST::MetaItem::ItemKind::ListPaths:
     327            0 :                     case AST::MetaItem::ItemKind::NameValueStr:
     328            0 :                     case AST::MetaItem::ItemKind::PathExpr:
     329            0 :                     case AST::MetaItem::ItemKind::Seq:
     330            0 :                     case AST::MetaItem::ItemKind::ListNameValueStr:
     331            0 :                     default:
     332            0 :                       gcc_unreachable ();
     333          608 :                       break;
     334              :                     }
     335              :                 }
     336          608 :                 break;
     337            0 :               case AST::MetaItemInner::Kind::LitExpr:
     338            0 :               default:
     339            0 :                 gcc_unreachable ();
     340          608 :                 break;
     341              :               }
     342              :           }
     343              :       }
     344              :       break;
     345            0 :     case AST::AttrInput::TOKEN_TREE:
     346            0 :     case AST::AttrInput::LITERAL:
     347            0 :     case AST::AttrInput::EXPR:
     348            0 :       rust_unreachable ();
     349          338 :       break;
     350              :     }
     351          338 :   return result;
     352              : }
     353              : 
     354              : // Copy constructor must deep copy attr_input as unique pointer
     355       129034 : Attribute::Attribute (Attribute const &other)
     356       129034 :   : path (other.path), locus (other.locus),
     357       129034 :     inner_attribute (other.inner_attribute)
     358              : {
     359              :   // guard to protect from null pointer dereference
     360       129034 :   if (other.attr_input != nullptr)
     361       109254 :     attr_input = other.attr_input->clone_attr_input ();
     362       129034 : }
     363              : 
     364              : // overload assignment operator to use custom clone method
     365              : Attribute &
     366           65 : Attribute::operator= (Attribute const &other)
     367              : {
     368           65 :   path = other.path;
     369           65 :   locus = other.locus;
     370           65 :   inner_attribute = other.inner_attribute;
     371              :   // guard to protect from null pointer dereference
     372           65 :   if (other.attr_input != nullptr)
     373           58 :     attr_input = other.attr_input->clone_attr_input ();
     374              :   else
     375            7 :     attr_input = nullptr;
     376              : 
     377           65 :   return *this;
     378              : }
     379              : 
     380              : std::string
     381         4694 : DelimTokenTree::as_string () const
     382              : {
     383         4694 :   std::string start_delim;
     384         4694 :   std::string end_delim;
     385         4694 :   switch (delim_type)
     386              :     {
     387         4694 :     case PARENS:
     388         4694 :       start_delim = "(";
     389         4694 :       end_delim = ")";
     390         4694 :       break;
     391            0 :     case SQUARE:
     392            0 :       start_delim = "[";
     393            0 :       end_delim = "]";
     394            0 :       break;
     395            0 :     case CURLY:
     396            0 :       start_delim = "{";
     397            0 :       end_delim = "}";
     398            0 :       break;
     399            0 :     default:
     400            0 :       rust_debug ("Invalid delimiter type, "
     401              :                   "Should be PARENS, SQUARE, or CURLY.");
     402            0 :       return "Invalid delimiter type";
     403              :     }
     404         9388 :   std::string str = start_delim;
     405         4694 :   if (!token_trees.empty ())
     406              :     {
     407        18802 :       for (const auto &tree : token_trees)
     408              :         {
     409              :           // DEBUG: null pointer check
     410        14108 :           if (tree == nullptr)
     411              :             {
     412            0 :               rust_debug (
     413              :                 "something really terrible has gone wrong - null pointer "
     414              :                 "token tree in delim token tree.");
     415            0 :               return "NULL_POINTER_MARK";
     416              :             }
     417              : 
     418        28216 :           str += tree->as_string ();
     419              :         }
     420              :     }
     421         4694 :   str += end_delim;
     422              : 
     423         4694 :   return str;
     424         4694 : }
     425              : 
     426              : std::string
     427       147574 : Token::as_string () const
     428              : {
     429       147574 :   if (tok_ref->should_have_str ())
     430              :     {
     431        42610 :       std::string str = tok_ref->get_str ();
     432              : 
     433        42610 :       std::string quote = is_string_lit () ? "\"" : "";
     434        42610 :       return quote + str + quote;
     435        42610 :     }
     436              :   else
     437              :     {
     438       104964 :       return tok_ref->get_token_description ();
     439              :     }
     440              : }
     441              : 
     442              : std::string
     443       817154 : SimplePathSegment::as_string () const
     444              : {
     445       817154 :   return segment_name;
     446              : }
     447              : 
     448              : const std::string
     449       318818 : SimplePath::as_string () const
     450              : {
     451       318818 :   std::string path;
     452       318818 :   if (opening_scope_resolution)
     453            0 :     path = "::";
     454              : 
     455              :   // crappy hack because doing proper for loop would be more code
     456       318818 :   bool first_time = true;
     457       637672 :   for (const auto &segment : segments)
     458              :     {
     459       318854 :       if (first_time)
     460              :         {
     461       637636 :           path += segment.as_string ();
     462       318818 :           first_time = false;
     463              :         }
     464              :       else
     465              :         {
     466           72 :           path += "::" + segment.as_string ();
     467              :         }
     468              : 
     469              :       // DEBUG: remove later. Checks for path error.
     470       318854 :       if (segment.is_error ())
     471              :         {
     472            0 :           rust_debug ("segment in path is error - this should've been filtered "
     473              :                       "out. first segment "
     474              :                       "was '%s'",
     475              :                       segments.at (0).as_string ().c_str ());
     476              :         }
     477              :     }
     478              : 
     479       318818 :   return path;
     480              : }
     481              : 
     482              : std::string
     483           10 : Visibility::as_string () const
     484              : {
     485           10 :   switch (vis_type)
     486              :     {
     487            0 :     case PRIV:
     488            0 :       return std::string ("");
     489           10 :     case PUB:
     490           10 :       return std::string ("pub");
     491            0 :     case PUB_CRATE:
     492            0 :       return std::string ("pub(crate)");
     493            0 :     case PUB_SELF:
     494            0 :       return std::string ("pub(self)");
     495            0 :     case PUB_SUPER:
     496            0 :       return std::string ("pub(super)");
     497            0 :     case PUB_IN_PATH:
     498            0 :       return std::string ("pub(in ") + in_path.as_string () + std::string (")");
     499            0 :     default:
     500            0 :       rust_unreachable ();
     501              :     }
     502              : }
     503              : 
     504              : // Creates a string that reflects the visibility stored.
     505              : std::string
     506            0 : VisItem::as_string () const
     507              : {
     508              :   // FIXME: can't do formatting on string to make identation occur.
     509            0 :   std::string str;
     510              : 
     511            0 :   if (!outer_attrs.empty ())
     512              :     {
     513            0 :       for (const auto &attr : outer_attrs)
     514            0 :         str += attr.as_string () + "\n";
     515              :     }
     516              : 
     517            0 :   if (has_visibility ())
     518            0 :     str += visibility.as_string () + " ";
     519              : 
     520            0 :   return str;
     521              : }
     522              : 
     523              : std::string
     524            0 : Module::as_string () const
     525              : {
     526            0 :   std::string str = VisItem::as_string () + "mod " + module_name.as_string ();
     527              : 
     528              :   // Return early if we're dealing with an unloaded module as their body resides
     529              :   // in a different file
     530            0 :   if (kind == ModuleKind::UNLOADED)
     531            0 :     return str + "\n no body (reference to external file)\n";
     532              : 
     533              :   // inner attributes
     534            0 :   str += append_attributes (inner_attrs, INNER);
     535              : 
     536              :   // items
     537            0 :   str += "\n items: ";
     538              : 
     539              :   // This can still happen if the module is loaded but empty, i.e. `mod foo {}`
     540            0 :   if (items.empty ())
     541              :     {
     542            0 :       str += "none";
     543              :     }
     544              :   else
     545              :     {
     546            0 :       for (const auto &item : items)
     547              :         {
     548              :           // DEBUG: null pointer check
     549            0 :           if (item == nullptr)
     550              :             {
     551            0 :               rust_debug ("something really terrible has gone wrong - "
     552              :                           "null pointer item in crate.");
     553            0 :               return "NULL_POINTER_MARK";
     554              :             }
     555              : 
     556            0 :           str += "\n  " + item->as_string ();
     557              :         }
     558              :     }
     559              : 
     560            0 :   return str + "\n";
     561            0 : }
     562              : 
     563              : std::string
     564            0 : StaticItem::as_string () const
     565              : {
     566            0 :   std::string str = VisItem::as_string ();
     567              : 
     568            0 :   str += indent_spaces (stay) + "static";
     569              : 
     570            0 :   if (has_mut)
     571            0 :     str += " mut";
     572              : 
     573            0 :   str += " " + name.as_string ();
     574              : 
     575              :   // DEBUG: null pointer check
     576            0 :   if (type == nullptr)
     577              :     {
     578            0 :       rust_debug ("something really terrible has gone wrong - null "
     579              :                   "pointer type in static item.");
     580            0 :       return "NULL_POINTER_MARK";
     581              :     }
     582            0 :   str += "\n" + indent_spaces (stay) + "Type: " + type->as_string ();
     583              : 
     584              :   // DEBUG: null pointer check
     585            0 :   if (expr == nullptr)
     586              :     {
     587            0 :       rust_debug ("something really terrible has gone wrong - null "
     588              :                   "pointer expr in static item.");
     589            0 :       return "NULL_POINTER_MARK";
     590              :     }
     591            0 :   str += "\n" + indent_spaces (stay) + "Expression: " + expr->as_string ();
     592              : 
     593            0 :   return str + "\n";
     594            0 : }
     595              : 
     596              : std::string
     597            0 : ExternCrate::as_string () const
     598              : {
     599            0 :   std::string str = VisItem::as_string ();
     600              : 
     601            0 :   str += "extern crate " + referenced_crate;
     602              : 
     603            0 :   if (has_as_clause ())
     604            0 :     str += " as " + as_clause_name;
     605              : 
     606            0 :   return str;
     607              : }
     608              : 
     609              : std::string
     610            0 : TupleStruct::as_string () const
     611              : {
     612            0 :   std::string str = VisItem::as_string ();
     613              : 
     614            0 :   str += "struct " + struct_name.as_string ();
     615              : 
     616              :   // generic params
     617            0 :   str += "\n Generic params: ";
     618            0 :   if (generic_params.empty ())
     619              :     {
     620            0 :       str += "none";
     621              :     }
     622              :   else
     623              :     {
     624            0 :       for (const auto &param : generic_params)
     625              :         {
     626              :           // DEBUG: null pointer check
     627            0 :           if (param == nullptr)
     628              :             {
     629            0 :               rust_debug (
     630              :                 "something really terrible has gone wrong - null pointer "
     631              :                 "generic param in enum.");
     632            0 :               return "NULL_POINTER_MARK";
     633              :             }
     634              : 
     635            0 :           str += "\n  " + param->as_string ();
     636              :         }
     637              :     }
     638              : 
     639              :   // tuple fields
     640            0 :   str += "\n Tuple fields: ";
     641            0 :   if (fields.empty ())
     642              :     {
     643            0 :       str += "none";
     644              :     }
     645              :   else
     646              :     {
     647            0 :       for (const auto &field : fields)
     648            0 :         str += "\n  " + field.as_string ();
     649              :     }
     650              : 
     651            0 :   str += "\n Where clause: ";
     652            0 :   if (has_where_clause ())
     653            0 :     str += where_clause.as_string ();
     654              :   else
     655            0 :     str += "none";
     656              : 
     657            0 :   return str;
     658            0 : }
     659              : 
     660              : std::string
     661            0 : ConstantItem::as_string () const
     662              : {
     663            0 :   std::string str = VisItem::as_string ();
     664              : 
     665            0 :   str += "const " + identifier.as_string ();
     666              : 
     667              :   // DEBUG: null pointer check
     668            0 :   if (type == nullptr)
     669              :     {
     670            0 :       rust_debug ("something really terrible has gone wrong - null "
     671              :                   "pointer type in const item.");
     672            0 :       return "NULL_POINTER_MARK";
     673              :     }
     674            0 :   str += "\n  Type: " + type->as_string ();
     675              : 
     676            0 :   if (has_expr ())
     677            0 :     str += "\n  Expression: " + const_expr->as_string ();
     678              : 
     679            0 :   return str + "\n";
     680            0 : }
     681              : 
     682              : std::string
     683            0 : InherentImpl::as_string () const
     684              : {
     685            0 :   std::string str = VisItem::as_string ();
     686              : 
     687            0 :   str += "impl ";
     688              : 
     689              :   // generic params
     690            0 :   str += "\n Generic params: ";
     691            0 :   if (generic_params.empty ())
     692              :     {
     693            0 :       str += "none";
     694              :     }
     695              :   else
     696              :     {
     697            0 :       for (const auto &param : generic_params)
     698              :         {
     699              :           // DEBUG: null pointer check
     700            0 :           if (param == nullptr)
     701              :             {
     702            0 :               rust_debug (
     703              :                 "something really terrible has gone wrong - null pointer "
     704              :                 "generic param in inherent impl.");
     705            0 :               return "NULL_POINTER_MARK";
     706              :             }
     707              : 
     708            0 :           str += "\n  " + param->as_string ();
     709              :         }
     710              :     }
     711              : 
     712            0 :   str += "\n Type: " + trait_type->as_string ();
     713              : 
     714            0 :   str += "\n Where clause: ";
     715            0 :   if (has_where_clause ())
     716            0 :     str += where_clause.as_string ();
     717              :   else
     718            0 :     str += "none";
     719              : 
     720              :   // inner attributes
     721            0 :   str += append_attributes (inner_attrs, INNER);
     722              : 
     723              :   // inherent impl items
     724            0 :   str += "\n Inherent impl items: ";
     725            0 :   if (!has_impl_items ())
     726              :     {
     727            0 :       str += "none";
     728              :     }
     729              :   else
     730              :     {
     731            0 :       for (const auto &item : impl_items)
     732            0 :         str += "\n  " + item->as_string ();
     733              :     }
     734              : 
     735            0 :   return str;
     736            0 : }
     737              : 
     738              : std::string
     739            0 : StructStruct::as_string () const
     740              : {
     741            0 :   std::string str = VisItem::as_string ();
     742              : 
     743            0 :   str += "struct " + struct_name.as_string ();
     744              : 
     745              :   // generic params
     746            0 :   str += "\n Generic params: ";
     747            0 :   if (generic_params.empty ())
     748              :     {
     749            0 :       str += "none";
     750              :     }
     751              :   else
     752              :     {
     753            0 :       for (const auto &param : generic_params)
     754              :         {
     755              :           // DEBUG: null pointer check
     756            0 :           if (param == nullptr)
     757              :             {
     758            0 :               rust_debug (
     759              :                 "something really terrible has gone wrong - null pointer "
     760              :                 "generic param in enum.");
     761            0 :               return "NULL_POINTER_MARK";
     762              :             }
     763              : 
     764            0 :           str += "\n  " + param->as_string ();
     765              :         }
     766              :     }
     767              : 
     768            0 :   str += "\n Where clause: ";
     769            0 :   if (has_where_clause ())
     770            0 :     str += where_clause.as_string ();
     771              :   else
     772            0 :     str += "none";
     773              : 
     774              :   // struct fields
     775            0 :   str += "\n Struct fields: ";
     776            0 :   if (is_unit)
     777              :     {
     778            0 :       str += "none (unit)";
     779              :     }
     780            0 :   else if (fields.empty ())
     781              :     {
     782            0 :       str += "none (non-unit)";
     783              :     }
     784              :   else
     785              :     {
     786            0 :       for (const auto &field : fields)
     787            0 :         str += "\n  " + field.as_string ();
     788              :     }
     789              : 
     790            0 :   return str;
     791            0 : }
     792              : 
     793              : std::string
     794            0 : UseDeclaration::as_string () const
     795              : {
     796            0 :   std::string str = VisItem::as_string ();
     797              : 
     798              :   // DEBUG: null pointer check
     799            0 :   if (use_tree == nullptr)
     800              :     {
     801            0 :       rust_debug (
     802              :         "something really terrible has gone wrong - null pointer use tree in "
     803              :         "use declaration.");
     804            0 :       return "NULL_POINTER_MARK";
     805              :     }
     806              : 
     807            0 :   str += "use " + use_tree->as_string ();
     808              : 
     809            0 :   return str;
     810            0 : }
     811              : 
     812              : std::string
     813            0 : UseTreeGlob::as_string () const
     814              : {
     815            0 :   switch (glob_type)
     816              :     {
     817            0 :     case NO_PATH:
     818            0 :       return "*";
     819            0 :     case GLOBAL:
     820            0 :       return "::*";
     821            0 :     case PATH_PREFIXED:
     822            0 :       {
     823            0 :         std::string path_str = path.as_string ();
     824            0 :         return path_str + "::*";
     825            0 :       }
     826            0 :     default:
     827              :       // some kind of error
     828            0 :       return "ERROR-PATH";
     829              :     }
     830              :   rust_unreachable ();
     831              : }
     832              : 
     833              : std::string
     834            0 : UseTreeList::as_string () const
     835              : {
     836            0 :   std::string path_str;
     837            0 :   switch (path_type)
     838              :     {
     839            0 :     case NO_PATH:
     840            0 :       path_str = "{";
     841            0 :       break;
     842            0 :     case GLOBAL:
     843            0 :       path_str = "::{";
     844            0 :       break;
     845            0 :     case PATH_PREFIXED:
     846            0 :       {
     847            0 :         path_str = path.as_string () + "::{";
     848            0 :         break;
     849              :       }
     850            0 :     default:
     851              :       // some kind of error
     852            0 :       return "ERROR-PATH-LIST";
     853              :     }
     854              : 
     855            0 :   if (has_trees ())
     856              :     {
     857            0 :       auto i = trees.begin ();
     858            0 :       auto e = trees.end ();
     859              : 
     860              :       // DEBUG: null pointer check
     861            0 :       if (*i == nullptr)
     862              :         {
     863            0 :           rust_debug ("something really terrible has gone wrong - null pointer "
     864              :                       "tree in use tree list.");
     865            0 :           return "NULL_POINTER_MARK";
     866              :         }
     867              : 
     868            0 :       for (; i != e; i++)
     869              :         {
     870            0 :           path_str += (*i)->as_string ();
     871            0 :           if (e != i + 1)
     872            0 :             path_str += ", ";
     873              :         }
     874              :     }
     875              :   else
     876              :     {
     877            0 :       path_str += "none";
     878              :     }
     879              : 
     880            0 :   return path_str + "}";
     881            0 : }
     882              : 
     883              : std::string
     884            0 : UseTreeRebind::as_string () const
     885              : {
     886            0 :   std::string path_str = path.as_string ();
     887              : 
     888            0 :   switch (bind_type)
     889              :     {
     890              :     case NONE:
     891              :       // nothing to add, just path
     892              :       break;
     893            0 :     case IDENTIFIER:
     894            0 :       path_str += " as " + identifier.as_string ();
     895            0 :       break;
     896            0 :     case WILDCARD:
     897            0 :       path_str += " as _";
     898            0 :       break;
     899            0 :     default:
     900              :       // error
     901            0 :       return "ERROR-PATH-REBIND";
     902              :     }
     903              : 
     904            0 :   return path_str;
     905            0 : }
     906              : 
     907              : std::string
     908            0 : Enum::as_string () const
     909              : {
     910            0 :   std::string str = VisItem::as_string ();
     911            0 :   str += enum_name.as_string ();
     912              : 
     913              :   // generic params
     914            0 :   str += "\n Generic params: ";
     915            0 :   if (generic_params.empty ())
     916              :     {
     917            0 :       str += "none";
     918              :     }
     919              :   else
     920              :     {
     921            0 :       for (const auto &param : generic_params)
     922              :         {
     923              :           // DEBUG: null pointer check
     924            0 :           if (param == nullptr)
     925              :             {
     926            0 :               rust_debug (
     927              :                 "something really terrible has gone wrong - null pointer "
     928              :                 "generic param in enum.");
     929            0 :               return "NULL_POINTER_MARK";
     930              :             }
     931              : 
     932            0 :           str += "\n  " + param->as_string ();
     933              :         }
     934              :     }
     935              : 
     936            0 :   str += "\n Where clause: ";
     937            0 :   if (has_where_clause ())
     938            0 :     str += where_clause.as_string ();
     939              :   else
     940            0 :     str += "none";
     941              : 
     942              :   // items
     943            0 :   str += "\n Items: ";
     944            0 :   if (items.empty ())
     945              :     {
     946            0 :       str += "none";
     947              :     }
     948              :   else
     949              :     {
     950            0 :       for (const auto &item : items)
     951              :         {
     952              :           // DEBUG: null pointer check
     953            0 :           if (item == nullptr)
     954              :             {
     955            0 :               rust_debug (
     956              :                 "something really terrible has gone wrong - null pointer "
     957              :                 "enum item in enum.");
     958            0 :               return "NULL_POINTER_MARK";
     959              :             }
     960              : 
     961            0 :           str += "\n  " + item->as_string ();
     962              :         }
     963              :     }
     964              : 
     965            0 :   return str;
     966            0 : }
     967              : 
     968              : std::string
     969            0 : Trait::as_string () const
     970              : {
     971            0 :   std::string str = VisItem::as_string ();
     972              : 
     973            0 :   if (has_unsafe)
     974            0 :     str += "unsafe ";
     975              : 
     976            0 :   str += "trait " + name.as_string ();
     977              : 
     978              :   // generic params
     979            0 :   str += "\n Generic params: ";
     980            0 :   if (generic_params.empty ())
     981              :     {
     982            0 :       str += "none";
     983              :     }
     984              :   else
     985              :     {
     986            0 :       for (const auto &param : generic_params)
     987              :         {
     988              :           // DEBUG: null pointer check
     989            0 :           if (param == nullptr)
     990              :             {
     991            0 :               rust_debug (
     992              :                 "something really terrible has gone wrong - null pointer "
     993              :                 "generic param in trait.");
     994            0 :               return "NULL_POINTER_MARK";
     995              :             }
     996              : 
     997            0 :           str += "\n  " + param->as_string ();
     998              :         }
     999              :     }
    1000              : 
    1001            0 :   str += "\n Type param bounds: ";
    1002            0 :   if (!has_type_param_bounds ())
    1003              :     {
    1004            0 :       str += "none";
    1005              :     }
    1006              :   else
    1007              :     {
    1008            0 :       for (const auto &bound : type_param_bounds)
    1009              :         {
    1010              :           // DEBUG: null pointer check
    1011            0 :           if (bound == nullptr)
    1012              :             {
    1013            0 :               rust_debug (
    1014              :                 "something really terrible has gone wrong - null pointer "
    1015              :                 "type param bound in trait.");
    1016            0 :               return "NULL_POINTER_MARK";
    1017              :             }
    1018              : 
    1019            0 :           str += "\n  " + bound->as_string ();
    1020              :         }
    1021              :     }
    1022              : 
    1023            0 :   str += "\n Where clause: ";
    1024            0 :   if (!has_where_clause ())
    1025            0 :     str += "none";
    1026              :   else
    1027            0 :     str += where_clause.as_string ();
    1028              : 
    1029            0 :   str += "\n Trait items: ";
    1030            0 :   if (!has_trait_items ())
    1031              :     {
    1032            0 :       str += "none";
    1033              :     }
    1034              :   else
    1035              :     {
    1036            0 :       for (const auto &item : trait_items)
    1037              :         {
    1038              :           // DEBUG: null pointer check
    1039            0 :           if (item == nullptr)
    1040              :             {
    1041            0 :               rust_debug (
    1042              :                 "something really terrible has gone wrong - null pointer "
    1043              :                 "trait item in trait.");
    1044            0 :               return "NULL_POINTER_MARK";
    1045              :             }
    1046              : 
    1047            0 :           str += "\n  " + item->as_string ();
    1048              :         }
    1049              :     }
    1050              : 
    1051            0 :   return str;
    1052            0 : }
    1053              : 
    1054              : std::string
    1055            0 : Union::as_string () const
    1056              : {
    1057            0 :   std::string str = VisItem::as_string ();
    1058              : 
    1059            0 :   str += "union " + union_name.as_string ();
    1060              : 
    1061              :   // generic params
    1062            0 :   str += "\n Generic params: ";
    1063            0 :   if (generic_params.empty ())
    1064              :     {
    1065            0 :       str += "none";
    1066              :     }
    1067              :   else
    1068              :     {
    1069            0 :       for (const auto &param : generic_params)
    1070              :         {
    1071              :           // DEBUG: null pointer check
    1072            0 :           if (param == nullptr)
    1073              :             {
    1074            0 :               rust_debug (
    1075              :                 "something really terrible has gone wrong - null pointer "
    1076              :                 "generic param in union.");
    1077            0 :               return "NULL_POINTER_MARK";
    1078              :             }
    1079              : 
    1080            0 :           str += "\n  " + param->as_string ();
    1081              :         }
    1082              :     }
    1083              : 
    1084            0 :   str += "\n Where clause: ";
    1085            0 :   if (has_where_clause ())
    1086            0 :     str += where_clause.as_string ();
    1087              :   else
    1088            0 :     str += "none";
    1089              : 
    1090              :   // struct fields
    1091            0 :   str += "\n Struct fields (variants): ";
    1092            0 :   if (variants.empty ())
    1093              :     {
    1094            0 :       str += "none";
    1095              :     }
    1096              :   else
    1097              :     {
    1098            0 :       for (const auto &field : variants)
    1099            0 :         str += "\n  " + field.as_string ();
    1100              :     }
    1101              : 
    1102            0 :   return str;
    1103            0 : }
    1104              : 
    1105        44333 : Function::Function (Function const &other)
    1106        44333 :   : VisItem (other), ExternalItem (other.get_node_id ()),
    1107        44333 :     qualifiers (other.qualifiers), function_name (other.function_name),
    1108        44333 :     where_clause (other.where_clause), locus (other.locus),
    1109        88666 :     is_external_function (other.is_external_function)
    1110              : {
    1111              :   // guard to prevent null dereference (always required)
    1112        44333 :   if (other.return_type != nullptr)
    1113        36248 :     return_type = other.return_type->clone_type ();
    1114              : 
    1115              :   // guard to prevent null dereference (only required if error state)
    1116        44333 :   if (other.has_body ())
    1117        34621 :     function_body = other.function_body.value ()->clone_block_expr ();
    1118              :   else
    1119         9712 :     function_body = tl::nullopt;
    1120              : 
    1121        44333 :   generic_params.reserve (other.generic_params.size ());
    1122        48172 :   for (const auto &e : other.generic_params)
    1123         3839 :     generic_params.push_back (e->clone_generic_param ());
    1124              : 
    1125        44333 :   function_params.reserve (other.function_params.size ());
    1126       102266 :   for (const auto &e : other.function_params)
    1127        57933 :     function_params.push_back (e->clone_param ());
    1128        44333 : }
    1129              : 
    1130              : Function &
    1131            0 : Function::operator= (Function const &other)
    1132              : {
    1133            0 :   VisItem::operator= (other);
    1134            0 :   function_name = other.function_name;
    1135            0 :   qualifiers = other.qualifiers;
    1136            0 :   where_clause = other.where_clause;
    1137              :   // visibility = other.visibility->clone_visibility();
    1138              :   // outer_attrs = other.outer_attrs;
    1139            0 :   locus = other.locus;
    1140            0 :   is_external_function = other.is_external_function;
    1141              : 
    1142              :   // guard to prevent null dereference (always required)
    1143            0 :   if (other.return_type != nullptr)
    1144            0 :     return_type = other.return_type->clone_type ();
    1145              :   else
    1146            0 :     return_type = nullptr;
    1147              : 
    1148              :   // guard to prevent null dereference (only required if error state)
    1149            0 :   if (other.has_body ())
    1150            0 :     function_body = other.function_body.value ()->clone_block_expr ();
    1151              :   else
    1152            0 :     function_body = tl::nullopt;
    1153              : 
    1154            0 :   generic_params.reserve (other.generic_params.size ());
    1155            0 :   for (const auto &e : other.generic_params)
    1156            0 :     generic_params.push_back (e->clone_generic_param ());
    1157              : 
    1158            0 :   function_params.reserve (other.function_params.size ());
    1159            0 :   for (const auto &e : other.function_params)
    1160            0 :     function_params.push_back (e->clone_param ());
    1161              : 
    1162            0 :   return *this;
    1163              : }
    1164              : std::string
    1165            0 : Function::as_string () const
    1166              : {
    1167            0 :   std::string str = VisItem::as_string () + "\n";
    1168            0 :   std::string qstr = qualifiers.as_string ();
    1169            0 :   if ("" != qstr)
    1170            0 :     str += qstr + " ";
    1171              : 
    1172            0 :   if (has_return_type ())
    1173              :     {
    1174              :       // DEBUG: null pointer check
    1175            0 :       if (return_type == nullptr)
    1176              :         {
    1177              :           rust_debug (
    1178              :             "something really terrible has gone wrong - null pointer return "
    1179              :             "type in function.");
    1180              :           return "NULL_POINTER_MARK";
    1181              :         }
    1182              : 
    1183            0 :       str += return_type->as_string () + " ";
    1184              :     }
    1185              :   else
    1186              :     {
    1187            0 :       str += "void ";
    1188              :     }
    1189              : 
    1190            0 :   str += function_name.as_string ();
    1191              : 
    1192            0 :   if (has_generics ())
    1193              :     {
    1194            0 :       str += "<";
    1195              : 
    1196            0 :       auto i = generic_params.begin ();
    1197            0 :       auto e = generic_params.end ();
    1198              : 
    1199              :       // DEBUG: null pointer check
    1200            0 :       if (i == e)
    1201              :         {
    1202            0 :           rust_debug ("something really terrible has gone wrong - null pointer "
    1203              :                       "generic param in function item.");
    1204            0 :           return "NULL_POINTER_MARK";
    1205              :         }
    1206              : 
    1207            0 :       for (; i != e; i++)
    1208              :         {
    1209            0 :           str += (*i)->as_string ();
    1210            0 :           if (e != i + 1)
    1211            0 :             str += ", ";
    1212              :         }
    1213            0 :       str += ">";
    1214              :     }
    1215              : 
    1216            0 :   if (has_function_params ())
    1217              :     {
    1218            0 :       auto i = function_params.begin ();
    1219            0 :       auto e = function_params.end ();
    1220            0 :       str += "(";
    1221            0 :       for (; i != e; i++)
    1222              :         {
    1223            0 :           str += (*i)->as_string ();
    1224            0 :           if (e != i + 1)
    1225            0 :             str += ", ";
    1226              :         }
    1227            0 :       str += ")";
    1228              :     }
    1229              :   else
    1230              :     {
    1231            0 :       str += "()";
    1232              :     }
    1233              : 
    1234            0 :   if (has_where_clause ())
    1235            0 :     str += " where " + where_clause.as_string ();
    1236              : 
    1237            0 :   str += "\n";
    1238              : 
    1239            0 :   if (has_body ())
    1240            0 :     str += function_body.value ()->as_string () + "\n";
    1241              : 
    1242            0 :   return str;
    1243            0 : }
    1244              : 
    1245              : std::string
    1246            0 : WhereClause::as_string () const
    1247              : {
    1248              :   // just print where clause items, don't mention "where" or "where clause"
    1249            0 :   std::string str;
    1250              : 
    1251            0 :   if (where_clause_items.empty ())
    1252              :     {
    1253            0 :       str = "none";
    1254              :     }
    1255              :   else
    1256              :     {
    1257            0 :       for (const auto &item : where_clause_items)
    1258            0 :         str += "\n  " + item->as_string ();
    1259              :     }
    1260              : 
    1261            0 :   return str;
    1262              : }
    1263              : 
    1264              : std::string
    1265            0 : BlockExpr::as_string () const
    1266              : {
    1267            0 :   std::string istr = indent_spaces (enter);
    1268            0 :   std::string str = istr + "BlockExpr:\n" + istr;
    1269              : 
    1270              :   // get outer attributes
    1271            0 :   str += append_attributes (outer_attrs, OUTER);
    1272              : 
    1273              :   // inner attributes
    1274            0 :   str += append_attributes (inner_attrs, INNER);
    1275              : 
    1276              :   // statements
    1277            0 :   str += "\n" + indent_spaces (stay) + "statements: ";
    1278            0 :   if (statements.empty ())
    1279              :     {
    1280            0 :       str += "none";
    1281              :     }
    1282              :   else
    1283              :     {
    1284            0 :       for (const auto &stmt : statements)
    1285              :         {
    1286              :           // DEBUG: null pointer check
    1287            0 :           if (stmt == nullptr)
    1288              :             {
    1289            0 :               rust_debug (
    1290              :                 "something really terrible has gone wrong - null pointer "
    1291              :                 "stmt in block expr.");
    1292            0 :               return "NULL_POINTER_MARK";
    1293              :             }
    1294              : 
    1295            0 :           str += "\n" + indent_spaces (stay) + stmt->as_string ();
    1296              :         }
    1297              :     }
    1298              : 
    1299              :   // final expression
    1300            0 :   str += "\n" + indent_spaces (stay) + "final expression: ";
    1301            0 :   if (expr == nullptr)
    1302            0 :     str += "none";
    1303              :   else
    1304            0 :     str += "\n" + expr->as_string ();
    1305              : 
    1306            0 :   str += "\n" + indent_spaces (out);
    1307            0 :   return str;
    1308            0 : }
    1309              : 
    1310              : std::string
    1311            0 : AnonConst::as_string () const
    1312              : {
    1313            0 :   std::string str = "AnonConst: ";
    1314              : 
    1315            0 :   if (kind == AnonConst::Kind::DeferredInference)
    1316            0 :     str += "_";
    1317              :   else
    1318            0 :     str += expr.value ()->as_string ();
    1319              : 
    1320            0 :   return str;
    1321              : }
    1322              : 
    1323              : std::string
    1324            0 : ConstBlock::as_string () const
    1325              : {
    1326            0 :   return "ConstBlock: " + expr.as_string ();
    1327              : }
    1328              : 
    1329              : std::string
    1330            0 : TraitImpl::as_string () const
    1331              : {
    1332            0 :   std::string str = VisItem::as_string ();
    1333              : 
    1334            0 :   if (has_unsafe)
    1335            0 :     str += "unsafe ";
    1336              : 
    1337            0 :   str += "impl ";
    1338              : 
    1339              :   // generic params
    1340            0 :   str += "\n Generic params: ";
    1341            0 :   if (!has_generics ())
    1342              :     {
    1343            0 :       str += "none";
    1344              :     }
    1345              :   else
    1346              :     {
    1347            0 :       for (const auto &param : generic_params)
    1348            0 :         str += "\n  " + param->as_string ();
    1349              :     }
    1350              : 
    1351            0 :   str += "\n Has exclam: ";
    1352            0 :   if (has_exclam)
    1353            0 :     str += "true";
    1354              :   else
    1355            0 :     str += "false";
    1356              : 
    1357            0 :   str += "\n TypePath (to trait): " + trait_path.as_string ();
    1358              : 
    1359            0 :   str += "\n Type (struct to impl on): " + trait_type->as_string ();
    1360              : 
    1361            0 :   str += "\n Where clause: ";
    1362            0 :   if (!has_where_clause ())
    1363            0 :     str += "none";
    1364              :   else
    1365            0 :     str += where_clause.as_string ();
    1366              : 
    1367              :   // inner attributes
    1368            0 :   str += append_attributes (inner_attrs, INNER);
    1369              : 
    1370            0 :   str += "\n trait impl items: ";
    1371            0 :   if (!has_impl_items ())
    1372              :     {
    1373            0 :       str += "none";
    1374              :     }
    1375              :   else
    1376              :     {
    1377            0 :       for (const auto &item : impl_items)
    1378            0 :         str += "\n  " + item->as_string ();
    1379              :     }
    1380              : 
    1381            0 :   return str;
    1382              : }
    1383              : 
    1384              : std::string
    1385            0 : TypeAlias::as_string () const
    1386              : {
    1387            0 :   std::string str = VisItem::as_string ();
    1388              : 
    1389            0 :   str += " " + new_type_name.as_string ();
    1390              : 
    1391              :   // generic params
    1392            0 :   str += "\n Generic params: ";
    1393            0 :   if (!has_generics ())
    1394              :     {
    1395            0 :       str += "none";
    1396              :     }
    1397              :   else
    1398              :     {
    1399              :       auto i = generic_params.begin ();
    1400              :       auto e = generic_params.end ();
    1401              : 
    1402            0 :       for (; i != e; i++)
    1403              :         {
    1404            0 :           str += (*i)->as_string ();
    1405            0 :           if (e != i + 1)
    1406            0 :             str += ", ";
    1407              :         }
    1408              :     }
    1409              : 
    1410            0 :   str += "\n Where clause: ";
    1411            0 :   if (!has_where_clause ())
    1412            0 :     str += "none";
    1413              :   else
    1414            0 :     str += where_clause.as_string ();
    1415              : 
    1416            0 :   str += "\n Type: " + existing_type->as_string ();
    1417              : 
    1418            0 :   return str;
    1419              : }
    1420              : 
    1421              : std::string
    1422            0 : ExternBlock::as_string () const
    1423              : {
    1424            0 :   std::string str = VisItem::as_string ();
    1425              : 
    1426            0 :   str += "extern ";
    1427            0 :   if (has_abi ())
    1428            0 :     str += "\"" + abi + "\" ";
    1429              : 
    1430            0 :   str += append_attributes (inner_attrs, INNER);
    1431              : 
    1432            0 :   str += "\n external items: ";
    1433            0 :   if (!has_extern_items ())
    1434              :     {
    1435            0 :       str += "none";
    1436              :     }
    1437              :   else
    1438              :     {
    1439            0 :       for (const auto &item : extern_items)
    1440            0 :         str += "\n  " + item->as_string ();
    1441              :     }
    1442              : 
    1443            0 :   return str;
    1444              : }
    1445              : 
    1446              : std::string
    1447            0 : MacroRule::as_string () const
    1448              : {
    1449            0 :   std::string str ("Macro rule: ");
    1450              : 
    1451            0 :   str += "\n Matcher: \n  ";
    1452            0 :   str += matcher.as_string ();
    1453              : 
    1454            0 :   str += "\n Transcriber: \n  ";
    1455            0 :   str += transcriber.as_string ();
    1456              : 
    1457            0 :   return str;
    1458              : }
    1459              : 
    1460              : std::string
    1461            0 : MacroRulesDefinition::as_string () const
    1462              : {
    1463            0 :   std::string str;
    1464              : 
    1465              :   // get outer attrs
    1466            0 :   str += append_attributes (outer_attrs, OUTER);
    1467              : 
    1468              :   // TODO: deal with macro_2_0
    1469            0 :   str += "macro_rules!";
    1470              : 
    1471            0 :   str += rule_name.as_string ();
    1472              : 
    1473            0 :   str += "\n Macro rules: ";
    1474            0 :   if (rules.empty ())
    1475              :     {
    1476            0 :       str += "none";
    1477              :     }
    1478              :   else
    1479              :     {
    1480            0 :       for (const auto &rule : rules)
    1481            0 :         str += "\n  " + rule.as_string ();
    1482              :     }
    1483              : 
    1484            0 :   str += "\n Delim type: ";
    1485            0 :   switch (delim_type)
    1486              :     {
    1487            0 :     case PARENS:
    1488            0 :       str += "parentheses";
    1489            0 :       break;
    1490            0 :     case SQUARE:
    1491            0 :       str += "square";
    1492            0 :       break;
    1493            0 :     case CURLY:
    1494            0 :       str += "curly";
    1495            0 :       break;
    1496            0 :     default:
    1497            0 :       return "ERROR_MARK_STRING - delim type in macro invocation";
    1498              :     }
    1499              : 
    1500            0 :   return str;
    1501            0 : }
    1502              : 
    1503              : std::string
    1504            0 : MacroInvocation::as_string () const
    1505              : {
    1506            0 :   std::string str = "MacroInvocation: ";
    1507            0 :   auto is_builtin = kind == InvocKind::Builtin;
    1508              : 
    1509            0 :   if (is_builtin)
    1510            0 :     str += "[builtin] ";
    1511              :   else
    1512            0 :     str += "[regular] ";
    1513              : 
    1514            0 :   str += append_attributes (outer_attrs, OUTER);
    1515              : 
    1516            0 :   str += "\n " + invoc_data.as_string ();
    1517              : 
    1518            0 :   str += "\n has semicolon: ";
    1519            0 :   str += has_semicolon () ? "true" : "false";
    1520              : 
    1521            0 :   if (is_builtin)
    1522              :     {
    1523            0 :       str += "[PENDING EAGER INVOCATIONS]: ";
    1524            0 :       for (auto &pending : pending_eager_invocs)
    1525              :         {
    1526            0 :           str += pending->as_string ();
    1527            0 :           str += "\n";
    1528              :         }
    1529              :     }
    1530              : 
    1531            0 :   return str;
    1532              : }
    1533              : 
    1534              : std::string
    1535            0 : MacroInvocData::as_string () const
    1536              : {
    1537            0 :   return path.as_string () + "!" + token_tree.as_string ();
    1538              : }
    1539              : 
    1540              : std::string
    1541            0 : ExprStmt::as_string () const
    1542              : {
    1543            0 :   std::string str = indent_spaces (enter) + "ExprStmt: \n";
    1544              : 
    1545            0 :   if (expr == nullptr)
    1546              :     {
    1547            0 :       str += "none (this should not happen and is an error)";
    1548              :     }
    1549              :   else
    1550              :     {
    1551            0 :       indent_spaces (enter);
    1552            0 :       str += expr->as_string ();
    1553            0 :       if (semicolon_followed)
    1554            0 :         str += ";";
    1555            0 :       indent_spaces (out);
    1556              :     }
    1557              : 
    1558            0 :   indent_spaces (out);
    1559            0 :   return str;
    1560              : }
    1561              : 
    1562              : std::string
    1563            0 : ClosureParam::as_string () const
    1564              : {
    1565            0 :   std::string str (pattern->as_string ());
    1566              : 
    1567            0 :   if (has_type_given ())
    1568            0 :     str += " : " + type->as_string ();
    1569              : 
    1570            0 :   return str;
    1571              : }
    1572              : 
    1573              : std::string
    1574            0 : ClosureExpr::as_string () const
    1575              : {
    1576            0 :   std::string str = "ClosureExpr:";
    1577              : 
    1578            0 :   str += append_attributes (outer_attrs, OUTER);
    1579              : 
    1580            0 :   str += "\n Has move: ";
    1581            0 :   if (has_move)
    1582            0 :     str += "true";
    1583              :   else
    1584            0 :     str += "false";
    1585              : 
    1586            0 :   str += "\n Params: ";
    1587            0 :   if (params.empty ())
    1588              :     {
    1589            0 :       str += "none";
    1590              :     }
    1591              :   else
    1592              :     {
    1593            0 :       for (const auto &param : params)
    1594            0 :         str += "\n  " + param.as_string ();
    1595              :     }
    1596              : 
    1597            0 :   return str;
    1598              : }
    1599              : 
    1600              : std::string
    1601            0 : ClosureExprInnerTyped::as_string () const
    1602              : {
    1603            0 :   std::string str = ClosureExpr::as_string ();
    1604              : 
    1605            0 :   str += "\n Return type: " + return_type->as_string ();
    1606              : 
    1607            0 :   str += "\n Body: " + expr->as_string ();
    1608              : 
    1609            0 :   return str;
    1610              : }
    1611              : 
    1612              : std::string
    1613            0 : QualifiedPathType::as_string () const
    1614              : {
    1615            0 :   std::string str ("<");
    1616            0 :   str += type_to_invoke_on->as_string ();
    1617              : 
    1618            0 :   if (has_as_clause ())
    1619            0 :     str += " as " + trait_path.as_string ();
    1620              : 
    1621            0 :   return str + ">";
    1622            0 : }
    1623              : 
    1624              : std::string
    1625            0 : BorrowExpr::as_string () const
    1626              : {
    1627              :   /* TODO: find way to incorporate outer attrs - may have to represent in
    1628              :    * different style (i.e. something more like BorrowExpr: \n outer attrs) */
    1629              : 
    1630            0 :   std::string str ("&");
    1631              : 
    1632            0 :   if (raw_borrow)
    1633              :     {
    1634            0 :       str += "raw ";
    1635            0 :       str += get_is_mut () ? "const " : "mut ";
    1636              :     }
    1637              :   else
    1638              :     {
    1639            0 :       if (double_borrow)
    1640            0 :         str += "&";
    1641              : 
    1642            0 :       if (get_is_mut ())
    1643            0 :         str += "mut ";
    1644              :     }
    1645            0 :   str += main_or_left_expr->as_string ();
    1646              : 
    1647            0 :   return str;
    1648              : }
    1649              : 
    1650              : std::string
    1651            0 : BoxExpr::as_string () const
    1652              : {
    1653            0 :   return "box " + expr->as_string ();
    1654              : }
    1655              : 
    1656              : void
    1657           20 : BoxExpr::accept_vis (ASTVisitor &vis)
    1658              : {
    1659           20 :   vis.visit (*this);
    1660           20 : }
    1661              : 
    1662              : std::string
    1663            0 : ReturnExpr::as_string () const
    1664              : {
    1665              :   /* TODO: find way to incorporate outer attrs - may have to represent in
    1666              :    * different style (i.e. something more like BorrowExpr: \n outer attrs) */
    1667              : 
    1668            0 :   std::string str ("return ");
    1669              : 
    1670            0 :   if (has_returned_expr ())
    1671            0 :     str += get_returned_expr ().as_string ();
    1672              : 
    1673            0 :   return str;
    1674              : }
    1675              : 
    1676              : std::string
    1677            0 : TryExpr::as_string () const
    1678              : {
    1679              :   /* TODO: find way to incorporate outer attrs - may have to represent in
    1680              :    * different style (i.e. something more like BorrowExpr: \n outer attrs) */
    1681              : 
    1682            0 :   std::string str ("try ");
    1683              : 
    1684            0 :   str += block_expr->as_string ();
    1685              : 
    1686            0 :   return str;
    1687              : }
    1688              : 
    1689              : std::string
    1690            0 : RangeToExpr::as_string () const
    1691              : {
    1692            0 :   return ".." + to->as_string ();
    1693              : }
    1694              : 
    1695              : std::string
    1696            0 : ContinueExpr::as_string () const
    1697              : {
    1698              :   // TODO: rewrite format to allow outer attributes
    1699            0 :   std::string str ("continue ");
    1700              : 
    1701            0 :   if (has_label ())
    1702            0 :     str += get_label_unchecked ().as_string ();
    1703              : 
    1704            0 :   return str;
    1705              : }
    1706              : 
    1707              : std::string
    1708            0 : NegationExpr::as_string () const
    1709              : {
    1710              :   // TODO: rewrite formula to allow outer attributes
    1711            0 :   std::string str;
    1712              : 
    1713            0 :   switch (expr_type)
    1714              :     {
    1715            0 :     case NegationOperator::NEGATE:
    1716            0 :       str = "-";
    1717            0 :       break;
    1718            0 :     case NegationOperator::NOT:
    1719            0 :       str = "!";
    1720            0 :       break;
    1721            0 :     default:
    1722            0 :       return "ERROR_MARK_STRING - negation expr";
    1723              :     }
    1724              : 
    1725            0 :   str += main_or_left_expr->as_string ();
    1726              : 
    1727            0 :   return str;
    1728            0 : }
    1729              : 
    1730              : std::string
    1731            0 : RangeFromExpr::as_string () const
    1732              : {
    1733            0 :   return from->as_string () + "..";
    1734              : }
    1735              : 
    1736              : std::string
    1737            0 : RangeFullExpr::as_string () const
    1738              : {
    1739            0 :   return "..";
    1740              : }
    1741              : 
    1742              : std::string
    1743            0 : ArrayIndexExpr::as_string () const
    1744              : {
    1745              :   // TODO: rewrite formula to allow outer attributes
    1746            0 :   return array_expr->as_string () + "[" + index_expr->as_string () + "]";
    1747              : }
    1748              : 
    1749              : std::string
    1750            0 : AssignmentExpr::as_string () const
    1751              : {
    1752            0 :   std::string str ("AssignmentExpr: ");
    1753              : 
    1754            0 :   if (main_or_left_expr == nullptr || right_expr == nullptr)
    1755              :     {
    1756            0 :       str += "error (either or both expressions are null)";
    1757              :     }
    1758              :   else
    1759              :     {
    1760              :       // left expr
    1761            0 :       str += "\n left: " + main_or_left_expr->as_string ();
    1762              : 
    1763              :       // right expr
    1764            0 :       str += "\n right: " + right_expr->as_string ();
    1765              :     }
    1766              : 
    1767            0 :   return str;
    1768              : }
    1769              : 
    1770              : std::string
    1771            0 : AsyncBlockExpr::as_string () const
    1772              : {
    1773            0 :   std::string str = "AsyncBlockExpr: ";
    1774              : 
    1775              :   // get outer attributes
    1776              :   // str += "\n " + Expr::as_string ();
    1777            0 :   str += append_attributes (outer_attrs, OUTER);
    1778              : 
    1779            0 :   str += "\n Has move: ";
    1780            0 :   str += has_move ? "true" : "false";
    1781              : 
    1782            0 :   return str + "\n" + block_expr->as_string ();
    1783            0 : }
    1784              : 
    1785              : std::string
    1786            0 : ComparisonExpr::as_string () const
    1787              : {
    1788              :   // TODO: rewrite to better reflect non-literal expressions
    1789            0 :   std::string str (main_or_left_expr->as_string ());
    1790              : 
    1791            0 :   switch (expr_type)
    1792              :     {
    1793            0 :     case ComparisonOperator::EQUAL:
    1794            0 :       str += " == ";
    1795            0 :       break;
    1796            0 :     case ComparisonOperator::NOT_EQUAL:
    1797            0 :       str += " != ";
    1798            0 :       break;
    1799            0 :     case ComparisonOperator::GREATER_THAN:
    1800            0 :       str += " > ";
    1801            0 :       break;
    1802            0 :     case ComparisonOperator::LESS_THAN:
    1803            0 :       str += " < ";
    1804            0 :       break;
    1805            0 :     case ComparisonOperator::GREATER_OR_EQUAL:
    1806            0 :       str += " >= ";
    1807            0 :       break;
    1808            0 :     case ComparisonOperator::LESS_OR_EQUAL:
    1809            0 :       str += " <= ";
    1810            0 :       break;
    1811            0 :     default:
    1812            0 :       return "ERROR_MARK_STRING - comparison expr";
    1813              :     }
    1814              : 
    1815            0 :   str += right_expr->as_string ();
    1816              : 
    1817            0 :   return str;
    1818            0 : }
    1819              : 
    1820              : std::string
    1821            0 : MethodCallExpr::as_string () const
    1822              : {
    1823            0 :   std::string str = "MethodCallExpr: ";
    1824              : 
    1825            0 :   str += append_attributes (outer_attrs, OUTER);
    1826              : 
    1827            0 :   str += "\n Object (receiver) expr: \n";
    1828            0 :   str += receiver->as_string ();
    1829              : 
    1830            0 :   str += "\n Method path segment: \n";
    1831            0 :   str += method_name.as_string ();
    1832              : 
    1833            0 :   str += "\n Call params:";
    1834            0 :   if (params.empty ())
    1835              :     {
    1836            0 :       str += "none";
    1837              :     }
    1838              :   else
    1839              :     {
    1840            0 :       for (const auto &param : params)
    1841              :         {
    1842            0 :           if (param == nullptr)
    1843            0 :             return "ERROR_MARK_STRING - method call expr param is null";
    1844              : 
    1845            0 :           str += "\n  " + param->as_string ();
    1846              :         }
    1847              :     }
    1848              : 
    1849            0 :   return str;
    1850            0 : }
    1851              : 
    1852              : std::string
    1853            0 : TupleIndexExpr::as_string () const
    1854              : {
    1855              :   // TODO: rewrite dump to better reflect non-literal exprs
    1856            0 :   return tuple_expr->as_string () + "." + std::to_string (tuple_index);
    1857              : }
    1858              : 
    1859              : std::string
    1860            0 : DereferenceExpr::as_string () const
    1861              : {
    1862              :   // TODO: rewrite dump to better reflect non-literal exprs
    1863            0 :   return "*" + main_or_left_expr->as_string ();
    1864              : }
    1865              : 
    1866              : std::string
    1867            0 : FieldAccessExpr::as_string () const
    1868              : {
    1869              :   // TODO: rewrite dump to better reflect non-literal exprs
    1870            0 :   return receiver->as_string () + "." + field.as_string ();
    1871              : }
    1872              : 
    1873              : std::string
    1874            0 : LazyBooleanExpr::as_string () const
    1875              : {
    1876              :   // TODO: rewrite dump to better reflect non-literal exprs
    1877            0 :   std::string str (main_or_left_expr->as_string ());
    1878              : 
    1879            0 :   switch (expr_type)
    1880              :     {
    1881            0 :     case LazyBooleanOperator::LOGICAL_OR:
    1882            0 :       str += " || ";
    1883            0 :       break;
    1884            0 :     case LazyBooleanOperator::LOGICAL_AND:
    1885            0 :       str += " && ";
    1886            0 :       break;
    1887            0 :     default:
    1888            0 :       return "ERROR_MARK_STRING - lazy boolean expr out of bounds";
    1889              :     }
    1890              : 
    1891            0 :   str += right_expr->as_string ();
    1892              : 
    1893            0 :   return str;
    1894            0 : }
    1895              : 
    1896              : std::string
    1897            0 : RangeFromToExpr::as_string () const
    1898              : {
    1899              :   // TODO: rewrite dump to better reflect non-literal exprs
    1900            0 :   return from->as_string () + ".." + to->as_string ();
    1901              : }
    1902              : 
    1903              : std::string
    1904            0 : RangeToInclExpr::as_string () const
    1905              : {
    1906              :   // TODO: rewrite dump to better reflect non-literal exprs
    1907            0 :   return "..=" + to->as_string ();
    1908              : }
    1909              : 
    1910              : std::string
    1911            0 : UnsafeBlockExpr::as_string () const
    1912              : {
    1913            0 :   std::string str = "UnsafeBlockExpr:" + indent_spaces (enter);
    1914              : 
    1915              :   // get outer attributes
    1916            0 :   str += append_attributes (outer_attrs, OUTER);
    1917              : 
    1918            0 :   str += indent_spaces (stay) + expr->as_string () + "\n" + indent_spaces (out);
    1919              : 
    1920            0 :   return str;
    1921              : }
    1922              : 
    1923              : std::string
    1924            0 : ClosureExprInner::as_string () const
    1925              : {
    1926            0 :   std::string str = ClosureExpr::as_string ();
    1927              : 
    1928            0 :   str += "\n Expression: " + closure_inner->as_string ();
    1929              : 
    1930            0 :   return str;
    1931              : }
    1932              : 
    1933              : std::string
    1934            0 : IfExpr::as_string () const
    1935              : {
    1936            0 :   std::string str = "IfExpr: ";
    1937              : 
    1938            0 :   str += append_attributes (outer_attrs, OUTER);
    1939              : 
    1940            0 :   str += "\n Condition expr: " + condition->as_string ();
    1941              : 
    1942            0 :   str += "\n If block expr: " + if_block->as_string ();
    1943              : 
    1944            0 :   return str;
    1945              : }
    1946              : 
    1947              : std::string
    1948            0 : IfExprConseqElse::as_string () const
    1949              : {
    1950            0 :   std::string str = IfExpr::as_string ();
    1951              : 
    1952            0 :   str += "\n Else expr: " + else_block->as_string ();
    1953              : 
    1954            0 :   return str;
    1955              : }
    1956              : 
    1957              : std::string
    1958            0 : IfLetExpr::as_string () const
    1959              : {
    1960            0 :   std::string str = "IfLetExpr: ";
    1961              : 
    1962            0 :   str += append_attributes (outer_attrs, OUTER);
    1963              : 
    1964            0 :   str += "\n Condition match arm patterns: ";
    1965            0 :   if (match_arm_pattern == nullptr)
    1966              :     {
    1967            0 :       str += "none";
    1968              :     }
    1969              :   else
    1970              :     {
    1971            0 :       str += "\n  " + match_arm_pattern->as_string ();
    1972              :     }
    1973              : 
    1974            0 :   str += "\n Scrutinee expr: " + value->as_string ();
    1975              : 
    1976            0 :   str += "\n If let block expr: " + if_block->as_string ();
    1977              : 
    1978            0 :   return str;
    1979              : }
    1980              : 
    1981              : std::string
    1982            0 : IfLetExprConseqElse::as_string () const
    1983              : {
    1984            0 :   std::string str = IfLetExpr::as_string ();
    1985              : 
    1986            0 :   str += "\n Else expr: " + else_block->as_string ();
    1987              : 
    1988            0 :   return str;
    1989              : }
    1990              : 
    1991              : std::string
    1992            0 : RangeFromToInclExpr::as_string () const
    1993              : {
    1994              :   // TODO: rewrite to allow dumps with non-literal exprs
    1995            0 :   return from->as_string () + "..=" + to->as_string ();
    1996              : }
    1997              : 
    1998              : std::string
    1999            0 : ErrorPropagationExpr::as_string () const
    2000              : {
    2001              :   // TODO: rewrite to allow dumps with non-literal exprs
    2002            0 :   return main_or_left_expr->as_string () + "?";
    2003              : }
    2004              : 
    2005              : std::string
    2006            0 : CompoundAssignmentExpr::as_string () const
    2007              : {
    2008            0 :   std::string operator_str;
    2009            0 :   operator_str.reserve (1);
    2010              : 
    2011              :   // get operator string
    2012            0 :   switch (expr_type)
    2013              :     {
    2014            0 :     case CompoundAssignmentOperator::ADD:
    2015            0 :       operator_str = "+";
    2016            0 :       break;
    2017            0 :     case CompoundAssignmentOperator::SUBTRACT:
    2018            0 :       operator_str = "-";
    2019            0 :       break;
    2020            0 :     case CompoundAssignmentOperator::MULTIPLY:
    2021            0 :       operator_str = "*";
    2022            0 :       break;
    2023            0 :     case CompoundAssignmentOperator::DIVIDE:
    2024            0 :       operator_str = "/";
    2025            0 :       break;
    2026            0 :     case CompoundAssignmentOperator::MODULUS:
    2027            0 :       operator_str = "%";
    2028            0 :       break;
    2029            0 :     case CompoundAssignmentOperator::BITWISE_AND:
    2030            0 :       operator_str = "&";
    2031            0 :       break;
    2032            0 :     case CompoundAssignmentOperator::BITWISE_OR:
    2033            0 :       operator_str = "|";
    2034            0 :       break;
    2035            0 :     case CompoundAssignmentOperator::BITWISE_XOR:
    2036            0 :       operator_str = "^";
    2037            0 :       break;
    2038            0 :     case CompoundAssignmentOperator::LEFT_SHIFT:
    2039            0 :       operator_str = "<<";
    2040            0 :       break;
    2041            0 :     case CompoundAssignmentOperator::RIGHT_SHIFT:
    2042            0 :       operator_str = ">>";
    2043            0 :       break;
    2044            0 :     default:
    2045            0 :       operator_str = "invalid operator. wtf";
    2046            0 :       break;
    2047              :     }
    2048              : 
    2049            0 :   operator_str += "=";
    2050              : 
    2051            0 :   std::string str ("CompoundAssignmentExpr: ");
    2052            0 :   if (main_or_left_expr == nullptr || right_expr == nullptr)
    2053              :     {
    2054            0 :       str += "error. this is probably a parsing failure.";
    2055              :     }
    2056              :   else
    2057              :     {
    2058            0 :       str += "\n left: " + main_or_left_expr->as_string ();
    2059            0 :       str += "\n right: " + right_expr->as_string ();
    2060            0 :       str += "\n operator: " + operator_str;
    2061              :     }
    2062              : 
    2063            0 :   return str;
    2064            0 : }
    2065              : 
    2066              : std::string
    2067            0 : ArithmeticOrLogicalExpr::as_string () const
    2068              : {
    2069            0 :   std::string operator_str;
    2070            0 :   operator_str.reserve (1);
    2071              : 
    2072              :   // get operator string
    2073            0 :   switch (expr_type)
    2074              :     {
    2075            0 :     case ArithmeticOrLogicalOperator::ADD:
    2076            0 :       operator_str = "+";
    2077            0 :       break;
    2078            0 :     case ArithmeticOrLogicalOperator::SUBTRACT:
    2079            0 :       operator_str = "-";
    2080            0 :       break;
    2081            0 :     case ArithmeticOrLogicalOperator::MULTIPLY:
    2082            0 :       operator_str = "*";
    2083            0 :       break;
    2084            0 :     case ArithmeticOrLogicalOperator::DIVIDE:
    2085            0 :       operator_str = "/";
    2086            0 :       break;
    2087            0 :     case ArithmeticOrLogicalOperator::MODULUS:
    2088            0 :       operator_str = "%";
    2089            0 :       break;
    2090            0 :     case ArithmeticOrLogicalOperator::BITWISE_AND:
    2091            0 :       operator_str = "&";
    2092            0 :       break;
    2093            0 :     case ArithmeticOrLogicalOperator::BITWISE_OR:
    2094            0 :       operator_str = "|";
    2095            0 :       break;
    2096            0 :     case ArithmeticOrLogicalOperator::BITWISE_XOR:
    2097            0 :       operator_str = "^";
    2098            0 :       break;
    2099            0 :     case ArithmeticOrLogicalOperator::LEFT_SHIFT:
    2100            0 :       operator_str = "<<";
    2101            0 :       break;
    2102            0 :     case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
    2103            0 :       operator_str = ">>";
    2104            0 :       break;
    2105            0 :     default:
    2106            0 :       operator_str = "invalid operator. wtf";
    2107            0 :       break;
    2108              :     }
    2109              : 
    2110            0 :   std::string str ("ArithmeticOrLogicalExpr: ");
    2111            0 :   if (main_or_left_expr == nullptr || right_expr == nullptr)
    2112              :     {
    2113            0 :       str += "error. this is probably a parsing failure.";
    2114              :     }
    2115              :   else
    2116              :     {
    2117            0 :       str += main_or_left_expr->as_string () + " ";
    2118            0 :       str += operator_str + " ";
    2119            0 :       str += right_expr->as_string ();
    2120              :     }
    2121              : 
    2122            0 :   return str;
    2123            0 : }
    2124              : 
    2125              : std::string
    2126            0 : CallExpr::as_string () const
    2127              : {
    2128            0 :   std::string str = "CallExpr: ";
    2129              : 
    2130            0 :   str += append_attributes (outer_attrs, OUTER);
    2131              : 
    2132            0 :   str += "\n Function expr: ";
    2133            0 :   str += function->as_string ();
    2134              : 
    2135            0 :   str += "\n Call params:";
    2136            0 :   if (!has_params ())
    2137              :     {
    2138            0 :       str += "none";
    2139              :     }
    2140              :   else
    2141              :     {
    2142            0 :       for (const auto &param : params)
    2143              :         {
    2144            0 :           if (param == nullptr)
    2145            0 :             return "ERROR_MARK_STRING - call expr param is null";
    2146              : 
    2147            0 :           str += "\n  " + param->as_string ();
    2148              :         }
    2149              :     }
    2150              : 
    2151            0 :   return str;
    2152            0 : }
    2153              : 
    2154              : std::string
    2155            0 : WhileLoopExpr::as_string () const
    2156              : {
    2157            0 :   std::string str = "WhileLoopExpr: ";
    2158              : 
    2159            0 :   str += append_attributes (outer_attrs, OUTER);
    2160              : 
    2161            0 :   str += "\n Label: ";
    2162            0 :   if (!has_loop_label ())
    2163            0 :     str += "none";
    2164              :   else
    2165            0 :     str += get_loop_label ().as_string ();
    2166              : 
    2167            0 :   str += "\n Conditional expr: " + condition->as_string ();
    2168              : 
    2169            0 :   str += "\n Loop block: " + loop_block->as_string ();
    2170              : 
    2171            0 :   return str;
    2172              : }
    2173              : 
    2174              : std::string
    2175            0 : WhileLetLoopExpr::as_string () const
    2176              : {
    2177            0 :   std::string str = "WhileLetLoopExpr: ";
    2178              : 
    2179            0 :   str += append_attributes (outer_attrs, OUTER);
    2180              : 
    2181            0 :   str += "\n Label: ";
    2182            0 :   if (!has_loop_label ())
    2183            0 :     str += "none";
    2184              :   else
    2185            0 :     str += get_loop_label ().as_string ();
    2186              : 
    2187            0 :   str += "\n Match arm patterns: ";
    2188            0 :   if (match_arm_pattern == nullptr)
    2189              :     {
    2190            0 :       str += "none";
    2191              :     }
    2192              :   else
    2193              :     {
    2194            0 :       str += "\n  " + match_arm_pattern->as_string ();
    2195              :     }
    2196              : 
    2197            0 :   str += "\n Scrutinee expr: " + scrutinee->as_string ();
    2198              : 
    2199            0 :   str += "\n Loop block: " + loop_block->as_string ();
    2200              : 
    2201            0 :   return str;
    2202              : }
    2203              : 
    2204              : std::string
    2205            0 : LoopExpr::as_string () const
    2206              : {
    2207            0 :   std::string str = "LoopExpr: (infinite loop)";
    2208              : 
    2209            0 :   str += append_attributes (outer_attrs, OUTER);
    2210              : 
    2211            0 :   str += "\n Label: ";
    2212            0 :   if (!has_loop_label ())
    2213            0 :     str += "none";
    2214              :   else
    2215            0 :     str += get_loop_label ().as_string ();
    2216              : 
    2217            0 :   str += "\n Loop block: " + loop_block->as_string ();
    2218              : 
    2219            0 :   return str;
    2220              : }
    2221              : 
    2222              : std::string
    2223            0 : ArrayExpr::as_string () const
    2224              : {
    2225            0 :   std::string str = "ArrayExpr:";
    2226              : 
    2227            0 :   str += append_attributes (outer_attrs, OUTER);
    2228              : 
    2229              :   // inner attributes
    2230            0 :   str += append_attributes (inner_attrs, INNER);
    2231              : 
    2232            0 :   str += "\n Array elems: ";
    2233            0 :   str += internal_elements->as_string ();
    2234              : 
    2235            0 :   return str;
    2236              : }
    2237              : 
    2238              : std::string
    2239            0 : AwaitExpr::as_string () const
    2240              : {
    2241              :   // TODO: rewrite dump to allow non-literal exprs
    2242            0 :   return awaited_expr->as_string () + ".await";
    2243              : }
    2244              : 
    2245              : std::string
    2246            0 : BreakExpr::as_string () const
    2247              : {
    2248              :   // TODO: rewrite dump to allow outer attrs, non-literal exprs
    2249            0 :   std::string str ("break ");
    2250              : 
    2251            0 :   if (has_label ())
    2252            0 :     str += get_label_unchecked ().as_string () + " ";
    2253              : 
    2254            0 :   if (has_break_expr ())
    2255            0 :     str += get_break_expr_unchecked ().as_string ();
    2256              : 
    2257            0 :   return str;
    2258              : }
    2259              : 
    2260              : std::string
    2261            0 : LoopLabel::as_string () const
    2262              : {
    2263            0 :   return label.as_string () + ": (label) ";
    2264              : }
    2265              : 
    2266              : std::string
    2267            0 : MatchArm::as_string () const
    2268              : {
    2269              :   // outer attributes
    2270            0 :   std::string str = append_attributes (outer_attrs, OUTER);
    2271              : 
    2272            0 :   str += "\nPatterns: ";
    2273            0 :   if (match_arm_pattern == nullptr)
    2274              :     {
    2275            0 :       str += "none";
    2276              :     }
    2277              :   else
    2278              :     {
    2279            0 :       str += "\n " + match_arm_pattern->as_string ();
    2280              :     }
    2281              : 
    2282            0 :   str += "\nGuard expr: ";
    2283            0 :   if (!has_match_arm_guard ())
    2284            0 :     str += "none";
    2285              :   else
    2286            0 :     str += guard_expr->as_string ();
    2287              : 
    2288            0 :   return str;
    2289              : }
    2290              : 
    2291              : std::string
    2292            0 : MatchCase::as_string () const
    2293              : {
    2294            0 :   std::string str ("MatchCase: (match arm) ");
    2295              : 
    2296            0 :   str += "\n Match arm matcher: \n" + arm.as_string ();
    2297            0 :   str += "\n Expr: " + expr->as_string ();
    2298              : 
    2299            0 :   return str;
    2300              : }
    2301              : 
    2302              : std::string
    2303            0 : MatchExpr::as_string () const
    2304              : {
    2305            0 :   std::string str ("MatchExpr:");
    2306              : 
    2307            0 :   str += append_attributes (outer_attrs, OUTER);
    2308              : 
    2309            0 :   str += "\n Scrutinee expr: " + branch_value->as_string ();
    2310              : 
    2311              :   // inner attributes
    2312            0 :   str += append_attributes (inner_attrs, INNER);
    2313              : 
    2314              :   // match arms
    2315            0 :   str += "\n Match arms: ";
    2316            0 :   if (match_arms.empty ())
    2317              :     {
    2318            0 :       str += "none";
    2319              :     }
    2320              :   else
    2321              :     {
    2322            0 :       for (const auto &arm : match_arms)
    2323            0 :         str += "\n  " + arm.as_string ();
    2324              :     }
    2325              : 
    2326            0 :   return str;
    2327              : }
    2328              : 
    2329              : std::string
    2330            0 : TupleExpr::as_string () const
    2331              : {
    2332            0 :   std::string str ("TupleExpr:");
    2333              : 
    2334            0 :   str += append_attributes (outer_attrs, OUTER);
    2335              : 
    2336              :   // inner attributes
    2337            0 :   str += append_attributes (inner_attrs, INNER);
    2338              : 
    2339            0 :   str += "\n Tuple elements: ";
    2340            0 :   if (tuple_elems.empty ())
    2341              :     {
    2342            0 :       str += "none";
    2343              :     }
    2344              :   else
    2345              :     {
    2346            0 :       for (const auto &elem : tuple_elems)
    2347            0 :         str += "\n  " + elem->as_string ();
    2348              :     }
    2349              : 
    2350            0 :   return str;
    2351              : }
    2352              : 
    2353              : std::string
    2354            0 : FunctionParam::as_string () const
    2355              : {
    2356              :   // TODO: rewrite dump to allow non-literal types
    2357            0 :   return param_name->as_string () + " : " + type->as_string ();
    2358              : }
    2359              : 
    2360              : void
    2361       239158 : FunctionParam::accept_vis (ASTVisitor &vis)
    2362              : {
    2363       239158 :   vis.visit (*this);
    2364       239158 : }
    2365              : 
    2366              : void
    2367       181243 : SelfParam::accept_vis (ASTVisitor &vis)
    2368              : {
    2369       181243 :   vis.visit (*this);
    2370       181243 : }
    2371              : 
    2372              : void
    2373        15469 : VariadicParam::accept_vis (ASTVisitor &vis)
    2374              : {
    2375        15469 :   vis.visit (*this);
    2376        15469 : }
    2377              : 
    2378              : std::string
    2379            0 : VariadicParam::as_string () const
    2380              : {
    2381            0 :   if (has_pattern ())
    2382            0 :     return get_pattern ().as_string () + " : ...";
    2383              :   else
    2384            0 :     return "...";
    2385              : }
    2386              : 
    2387              : std::string
    2388            0 : FunctionQualifiers::as_string () const
    2389              : {
    2390            0 :   std::string str;
    2391              : 
    2392            0 :   if (is_async ())
    2393            0 :     str += "async ";
    2394            0 :   if (is_const ())
    2395            0 :     str += "const ";
    2396            0 :   if (is_unsafe ())
    2397            0 :     str += "unsafe ";
    2398              : 
    2399            0 :   if (has_extern)
    2400              :     {
    2401            0 :       str += "extern";
    2402            0 :       if (extern_abi != "")
    2403            0 :         str += " \"" + extern_abi + "\"";
    2404              :     }
    2405              : 
    2406            0 :   return str;
    2407              : }
    2408              : 
    2409              : std::string
    2410            0 : TraitBound::as_string () const
    2411              : {
    2412            0 :   std::string str ("TraitBound:");
    2413              : 
    2414            0 :   str += "\n Has opening question mark: ";
    2415            0 :   if (opening_question_mark)
    2416            0 :     str += "true";
    2417              :   else
    2418            0 :     str += "false";
    2419              : 
    2420            0 :   str += "\n For lifetimes: ";
    2421            0 :   if (!has_for_lifetimes ())
    2422              :     {
    2423            0 :       str += "none";
    2424              :     }
    2425              :   else
    2426              :     {
    2427            0 :       for (const auto &lifetime : for_lifetimes)
    2428            0 :         str += "\n  " + lifetime.as_string ();
    2429              :     }
    2430              : 
    2431            0 :   str += "\n Type path: " + type_path.as_string ();
    2432              : 
    2433            0 :   return str;
    2434              : }
    2435              : 
    2436              : std::string
    2437            0 : MacroMatcher::as_string () const
    2438              : {
    2439            0 :   std::string str ("Macro matcher: ");
    2440              : 
    2441            0 :   str += "\n Delim type: ";
    2442              : 
    2443            0 :   switch (delim_type)
    2444              :     {
    2445            0 :     case PARENS:
    2446            0 :       str += "parentheses";
    2447            0 :       break;
    2448            0 :     case SQUARE:
    2449            0 :       str += "square";
    2450            0 :       break;
    2451            0 :     case CURLY:
    2452            0 :       str += "curly";
    2453            0 :       break;
    2454            0 :     default:
    2455            0 :       return "ERROR_MARK_STRING - macro matcher delim";
    2456              :     }
    2457              : 
    2458            0 :   str += "\n Matches: ";
    2459              : 
    2460            0 :   if (matches.empty ())
    2461              :     {
    2462            0 :       str += "none";
    2463              :     }
    2464              :   else
    2465              :     {
    2466            0 :       for (const auto &match : matches)
    2467            0 :         str += "\n  " + match->as_string ();
    2468              :     }
    2469              : 
    2470            0 :   return str;
    2471            0 : }
    2472              : 
    2473              : std::string
    2474            0 : LifetimeParam::as_string () const
    2475              : {
    2476            0 :   std::string str ("LifetimeParam: ");
    2477              : 
    2478            0 :   str += "\n Outer attribute:";
    2479            0 :   if (!has_outer_attribute ())
    2480            0 :     str += "none";
    2481            0 :   for (auto &attr : outer_attrs)
    2482            0 :     str += " " + attr.as_string ();
    2483              : 
    2484            0 :   str += "\n Lifetime: " + lifetime.as_string ();
    2485              : 
    2486            0 :   str += "\n Lifetime bounds: ";
    2487            0 :   if (!has_lifetime_bounds ())
    2488              :     {
    2489            0 :       str += "none";
    2490              :     }
    2491              :   else
    2492              :     {
    2493            0 :       for (const auto &bound : lifetime_bounds)
    2494            0 :         str += "\n  " + bound.as_string ();
    2495              :     }
    2496              : 
    2497            0 :   return str;
    2498              : }
    2499              : 
    2500              : std::string
    2501            0 : MacroMatchFragment::as_string () const
    2502              : {
    2503            0 :   return "$" + ident.as_string () + ": " + frag_spec.as_string ();
    2504              : }
    2505              : 
    2506              : std::string
    2507            0 : MacroMatchRepetition::as_string () const
    2508              : {
    2509            0 :   std::string str ("Macro match repetition: ");
    2510              : 
    2511            0 :   str += "\n Matches: ";
    2512            0 :   if (matches.empty ())
    2513              :     {
    2514            0 :       str += "none";
    2515              :     }
    2516              :   else
    2517              :     {
    2518            0 :       for (const auto &match : matches)
    2519            0 :         str += "\n  " + match->as_string ();
    2520              :     }
    2521              : 
    2522            0 :   str += "\n Sep: ";
    2523            0 :   if (!has_sep ())
    2524            0 :     str += "none";
    2525              :   else
    2526            0 :     str += sep->as_string ();
    2527              : 
    2528            0 :   str += "\n Op: ";
    2529            0 :   switch (op)
    2530              :     {
    2531            0 :     case ANY:
    2532            0 :       str += "*";
    2533            0 :       break;
    2534            0 :     case ONE_OR_MORE:
    2535            0 :       str += "+";
    2536            0 :       break;
    2537            0 :     case ZERO_OR_ONE:
    2538            0 :       str += "?";
    2539            0 :       break;
    2540            0 :     case NONE:
    2541            0 :       str += "no op? shouldn't be allowed";
    2542            0 :       break;
    2543            0 :     default:
    2544            0 :       return "ERROR_MARK_STRING - unknown op in macro match repetition";
    2545              :     }
    2546              : 
    2547            0 :   return str;
    2548            0 : }
    2549              : 
    2550              : std::string
    2551           94 : Lifetime::as_string () const
    2552              : {
    2553           94 :   switch (lifetime_type)
    2554              :     {
    2555           94 :     case NAMED:
    2556           94 :       return "'" + lifetime_name;
    2557            0 :     case STATIC:
    2558            0 :       return "'static";
    2559            0 :     case WILDCARD:
    2560            0 :       return "'_";
    2561            0 :     default:
    2562            0 :       return "ERROR-MARK-STRING: lifetime type failure";
    2563              :     }
    2564              : }
    2565              : 
    2566              : std::string
    2567            0 : TypeParam::as_string () const
    2568              : {
    2569            0 :   std::string str ("TypeParam: ");
    2570              : 
    2571            0 :   str += "\n Outer attribute:";
    2572            0 :   if (!has_outer_attribute ())
    2573            0 :     str += "none";
    2574            0 :   for (auto &attr : outer_attrs)
    2575            0 :     str += " " + attr.as_string ();
    2576              : 
    2577            0 :   str += "\n Identifier: " + type_representation.as_string ();
    2578              : 
    2579            0 :   str += "\n Type param bounds: ";
    2580            0 :   if (!has_type_param_bounds ())
    2581              :     {
    2582            0 :       str += "none";
    2583              :     }
    2584              :   else
    2585              :     {
    2586            0 :       for (const auto &bound : type_param_bounds)
    2587            0 :         str += "\n  " + bound->as_string ();
    2588              :     }
    2589              : 
    2590            0 :   str += "\n Type: ";
    2591            0 :   if (!has_type ())
    2592            0 :     str += "none";
    2593              :   else
    2594            0 :     str += type->as_string ();
    2595              : 
    2596            0 :   return str;
    2597              : }
    2598              : 
    2599              : std::string
    2600            0 : ForLoopExpr::as_string () const
    2601              : {
    2602            0 :   std::string str = "ForLoopExpr: ";
    2603              : 
    2604            0 :   str += append_attributes (outer_attrs, OUTER);
    2605              : 
    2606            0 :   str += "\n Label: ";
    2607            0 :   if (!has_loop_label ())
    2608            0 :     str += "none";
    2609              :   else
    2610            0 :     str += get_loop_label ().as_string ();
    2611              : 
    2612            0 :   str += "\n Pattern: " + pattern->as_string ();
    2613              : 
    2614            0 :   str += "\n Iterator expr: " + iterator_expr->as_string ();
    2615              : 
    2616            0 :   str += "\n Loop block: " + loop_block->as_string ();
    2617              : 
    2618            0 :   return str;
    2619              : }
    2620              : 
    2621              : std::string
    2622            0 : LetStmt::as_string () const
    2623              : {
    2624              :   // TODO: rewrite to work with non-linearisable types and exprs
    2625            0 :   std::string str = append_attributes (outer_attrs, OUTER);
    2626              : 
    2627            0 :   str += "\n" + indent_spaces (stay) + "let " + variables_pattern->as_string ();
    2628              : 
    2629            0 :   if (has_type ())
    2630            0 :     str += " : " + type->as_string ();
    2631              : 
    2632            0 :   if (has_init_expr ())
    2633            0 :     str += " = " + init_expr->as_string ();
    2634              : 
    2635            0 :   return str;
    2636              : }
    2637              : 
    2638              : std::string
    2639            0 : InferredType::as_string () const
    2640              : {
    2641            0 :   return "_ (inferred)";
    2642              : }
    2643              : 
    2644              : std::string
    2645            0 : TypeCastExpr::as_string () const
    2646              : {
    2647              :   // TODO: rewrite to work with non-linearisable exprs and types
    2648            0 :   return main_or_left_expr->as_string () + " as "
    2649            0 :          + type_to_convert_to->as_string ();
    2650              : }
    2651              : 
    2652              : std::string
    2653            0 : ImplTraitType::as_string () const
    2654              : {
    2655            0 :   std::string str ("ImplTraitType: \n TypeParamBounds: ");
    2656              : 
    2657            0 :   if (type_param_bounds.empty ())
    2658              :     {
    2659            0 :       str += "none";
    2660              :     }
    2661              :   else
    2662              :     {
    2663            0 :       for (const auto &bound : type_param_bounds)
    2664            0 :         str += "\n  " + bound->as_string ();
    2665              :     }
    2666              : 
    2667            0 :   return str;
    2668              : }
    2669              : 
    2670              : std::string
    2671            0 : ReferenceType::as_string () const
    2672              : {
    2673              :   // TODO: rewrite to work with non-linearisable types
    2674            0 :   std::string str ("&");
    2675              : 
    2676            0 :   if (has_lifetime ())
    2677            0 :     str += get_lifetime ().as_string () + " ";
    2678              : 
    2679            0 :   if (has_mut)
    2680            0 :     str += "mut ";
    2681              : 
    2682            0 :   str += type->as_string ();
    2683              : 
    2684            0 :   return str;
    2685              : }
    2686              : 
    2687              : std::string
    2688            0 : RawPointerType::as_string () const
    2689              : {
    2690              :   // TODO: rewrite to work with non-linearisable types
    2691            0 :   std::string str ("*");
    2692              : 
    2693            0 :   switch (pointer_type)
    2694              :     {
    2695            0 :     case MUT:
    2696            0 :       str += "mut ";
    2697            0 :       break;
    2698            0 :     case CONST:
    2699            0 :       str += "const ";
    2700            0 :       break;
    2701            0 :     default:
    2702            0 :       return "ERROR_MARK_STRING - unknown pointer type in raw pointer type";
    2703              :     }
    2704              : 
    2705            0 :   str += type->as_string ();
    2706              : 
    2707            0 :   return str;
    2708            0 : }
    2709              : 
    2710              : std::string
    2711            0 : TraitObjectType::as_string () const
    2712              : {
    2713            0 :   std::string str ("TraitObjectType: \n Has dyn dispatch: ");
    2714              : 
    2715            0 :   if (has_dyn)
    2716            0 :     str += "true";
    2717              :   else
    2718            0 :     str += "false";
    2719              : 
    2720            0 :   str += "\n TypeParamBounds: ";
    2721            0 :   if (type_param_bounds.empty ())
    2722              :     {
    2723            0 :       str += "none";
    2724              :     }
    2725              :   else
    2726              :     {
    2727            0 :       for (const auto &bound : type_param_bounds)
    2728            0 :         str += "\n  " + bound->as_string ();
    2729              :     }
    2730              : 
    2731            0 :   return str;
    2732              : }
    2733              : 
    2734              : std::string
    2735            0 : BareFunctionType::as_string () const
    2736              : {
    2737            0 :   std::string str ("BareFunctionType: \n For lifetimes: ");
    2738              : 
    2739            0 :   if (!has_for_lifetimes ())
    2740              :     {
    2741            0 :       str += "none";
    2742              :     }
    2743              :   else
    2744              :     {
    2745            0 :       for (const auto &for_lifetime : for_lifetimes)
    2746            0 :         str += "\n  " + for_lifetime.as_string ();
    2747              :     }
    2748              : 
    2749            0 :   str += "\n Qualifiers: " + function_qualifiers.as_string ();
    2750              : 
    2751            0 :   str += "\n Params: ";
    2752            0 :   if (params.empty ())
    2753              :     {
    2754            0 :       str += "none";
    2755              :     }
    2756              :   else
    2757              :     {
    2758            0 :       for (const auto &param : params)
    2759            0 :         str += "\n  " + param.as_string ();
    2760              :     }
    2761              : 
    2762            0 :   str += "\n Is variadic: ";
    2763            0 :   if (_is_variadic)
    2764            0 :     str += "true";
    2765              :   else
    2766            0 :     str += "false";
    2767              : 
    2768            0 :   str += "\n Return type: ";
    2769            0 :   if (!has_return_type ())
    2770            0 :     str += "none (void)";
    2771              :   else
    2772            0 :     str += return_type->as_string ();
    2773              : 
    2774            0 :   return str;
    2775              : }
    2776              : 
    2777              : std::string
    2778            0 : ImplTraitTypeOneBound::as_string () const
    2779              : {
    2780            0 :   std::string str ("ImplTraitTypeOneBound: \n TraitBound: ");
    2781              : 
    2782            0 :   return str + trait_bound->as_string ();
    2783            0 : }
    2784              : 
    2785              : std::string
    2786            0 : TraitObjectTypeOneBound::as_string () const
    2787              : {
    2788            0 :   std::string str ("TraitObjectTypeOneBound: \n Has dyn dispatch: ");
    2789              : 
    2790            0 :   if (has_dyn)
    2791            0 :     str += "true";
    2792              :   else
    2793            0 :     str += "false";
    2794              : 
    2795            0 :   str += "\n TraitBound: " + trait_bound.as_string ();
    2796              : 
    2797            0 :   return str;
    2798              : }
    2799              : 
    2800              : std::string
    2801            0 : ArrayType::as_string () const
    2802              : {
    2803              :   // TODO: rewrite to work with non-linearisable types and exprs
    2804            0 :   return "[" + elem_type->as_string () + "; " + size.as_string () + "]";
    2805              : }
    2806              : 
    2807              : std::string
    2808            0 : SliceType::as_string () const
    2809              : {
    2810              :   // TODO: rewrite to work with non-linearisable types
    2811            0 :   return "[" + elem_type->as_string () + "]";
    2812              : }
    2813              : 
    2814              : std::string
    2815            0 : TupleType::as_string () const
    2816              : {
    2817              :   // TODO: rewrite to work with non-linearisable types
    2818            0 :   std::string str ("(");
    2819              : 
    2820            0 :   if (!is_unit_type ())
    2821              :     {
    2822              :       auto i = elems.begin ();
    2823              :       auto e = elems.end ();
    2824              : 
    2825            0 :       for (; i != e; i++)
    2826              :         {
    2827            0 :           str += (*i)->as_string ();
    2828            0 :           if (e != i + 1)
    2829            0 :             str += ", ";
    2830              :         }
    2831              :     }
    2832              : 
    2833            0 :   str += ")";
    2834              : 
    2835            0 :   return str;
    2836              : }
    2837              : 
    2838              : std::string
    2839            0 : StructExpr::as_string () const
    2840              : {
    2841            0 :   std::string str = append_attributes (outer_attrs, OUTER);
    2842            0 :   indent_spaces (enter);
    2843            0 :   str += "\n" + indent_spaces (stay) + "StructExpr:";
    2844            0 :   indent_spaces (enter);
    2845            0 :   str += "\n" + indent_spaces (stay) + "PathInExpr:\n";
    2846            0 :   str += indent_spaces (stay) + struct_name.as_string ();
    2847            0 :   indent_spaces (out);
    2848            0 :   indent_spaces (out);
    2849            0 :   return str;
    2850              : }
    2851              : 
    2852              : std::string
    2853            0 : StructExprStruct::as_string () const
    2854              : {
    2855              :   // TODO: doesn't this require data from StructExpr?
    2856            0 :   std::string str ("StructExprStruct (or subclass): ");
    2857              : 
    2858            0 :   str += "\n Path: " + get_struct_name ().as_string ();
    2859              : 
    2860              :   // inner attributes
    2861            0 :   str += append_attributes (inner_attrs, INNER);
    2862              : 
    2863            0 :   return str;
    2864              : }
    2865              : 
    2866              : std::string
    2867            0 : StructBase::as_string () const
    2868              : {
    2869            0 :   if (base_struct != nullptr)
    2870            0 :     return base_struct->as_string ();
    2871              :   else
    2872            0 :     return "ERROR_MARK_STRING - invalid struct base had as string applied";
    2873              : }
    2874              : 
    2875              : std::string
    2876            0 : StructExprFieldWithVal::as_string () const
    2877              : {
    2878              :   // used to get value string
    2879            0 :   return value->as_string ();
    2880              : }
    2881              : 
    2882              : std::string
    2883            0 : StructExprFieldIdentifierValue::as_string () const
    2884              : {
    2885              :   // TODO: rewrite to work with non-linearisable exprs
    2886            0 :   return field_name.as_string () + " : " + StructExprFieldWithVal::as_string ();
    2887              : }
    2888              : 
    2889              : std::string
    2890            0 : StructExprFieldIndexValue::as_string () const
    2891              : {
    2892              :   // TODO: rewrite to work with non-linearisable exprs
    2893            0 :   return std::to_string (index) + " : " + StructExprFieldWithVal::as_string ();
    2894              : }
    2895              : 
    2896              : std::string
    2897            0 : StructExprStructFields::as_string () const
    2898              : {
    2899            0 :   std::string str = StructExprStruct::as_string ();
    2900              : 
    2901            0 :   str += "\n Fields: ";
    2902            0 :   if (fields.empty ())
    2903              :     {
    2904            0 :       str += "none";
    2905              :     }
    2906              :   else
    2907              :     {
    2908            0 :       for (const auto &field : fields)
    2909            0 :         str += "\n  " + field->as_string ();
    2910              :     }
    2911              : 
    2912            0 :   str += "\n Struct base: ";
    2913            0 :   if (!has_struct_base ())
    2914            0 :     str += "none";
    2915              :   else
    2916            0 :     str += struct_base.as_string ();
    2917              : 
    2918            0 :   return str;
    2919              : }
    2920              : 
    2921              : std::string
    2922            0 : EnumItem::as_string () const
    2923              : {
    2924            0 :   std::string str = VisItem::as_string ();
    2925            0 :   str += variant_name.as_string ();
    2926              : 
    2927            0 :   return str;
    2928              : }
    2929              : 
    2930              : std::string
    2931            0 : EnumItemTuple::as_string () const
    2932              : {
    2933            0 :   std::string str = EnumItem::as_string ();
    2934              : 
    2935              :   // add tuple opening parens
    2936            0 :   str += "(";
    2937              : 
    2938              :   // tuple fields
    2939            0 :   if (has_tuple_fields ())
    2940              :     {
    2941              :       auto i = tuple_fields.begin ();
    2942              :       auto e = tuple_fields.end ();
    2943              : 
    2944            0 :       for (; i != e; i++)
    2945              :         {
    2946            0 :           str += (*i).as_string ();
    2947            0 :           if (e != i + 1)
    2948            0 :             str += ", ";
    2949              :         }
    2950              :     }
    2951              : 
    2952              :   // add tuple closing parens
    2953            0 :   str += ")";
    2954              : 
    2955            0 :   return str;
    2956              : }
    2957              : 
    2958              : std::string
    2959            0 : TupleField::as_string () const
    2960              : {
    2961              :   // TODO: rewrite to work with non-linearisable exprs
    2962              : 
    2963              :   // outer attributes
    2964            0 :   std::string str = append_attributes (outer_attrs, OUTER);
    2965              : 
    2966            0 :   if (has_visibility ())
    2967            0 :     str += "\n" + visibility.as_string ();
    2968              : 
    2969            0 :   str += " " + field_type->as_string ();
    2970              : 
    2971            0 :   return str;
    2972              : }
    2973              : 
    2974              : std::string
    2975            0 : EnumItemStruct::as_string () const
    2976              : {
    2977            0 :   std::string str = EnumItem::as_string ();
    2978              : 
    2979              :   // add struct opening parens
    2980            0 :   str += "{";
    2981              : 
    2982              :   // tuple fields
    2983            0 :   if (has_struct_fields ())
    2984              :     {
    2985              :       auto i = struct_fields.begin ();
    2986              :       auto e = struct_fields.end ();
    2987              : 
    2988            0 :       for (; i != e; i++)
    2989              :         {
    2990            0 :           str += (*i).as_string ();
    2991            0 :           if (e != i + 1)
    2992            0 :             str += ", ";
    2993              :         }
    2994              :     }
    2995              : 
    2996              :   // add struct closing parens
    2997            0 :   str += "}";
    2998              : 
    2999            0 :   return str;
    3000              : }
    3001              : 
    3002              : std::string
    3003            0 : StructField::as_string () const
    3004              : {
    3005              :   // TODO: rewrite to work with non-linearisable exprs
    3006              :   // outer attributes
    3007            0 :   std::string str = append_attributes (outer_attrs, OUTER);
    3008              : 
    3009            0 :   if (has_visibility ())
    3010            0 :     str += "\n" + visibility.as_string ();
    3011              : 
    3012            0 :   str += " " + field_name.as_string () + " : " + field_type->as_string ();
    3013              : 
    3014            0 :   return str;
    3015              : }
    3016              : 
    3017              : std::string
    3018            0 : EnumItemDiscriminant::as_string () const
    3019              : {
    3020              :   // TODO: rewrite to work with non-linearisable exprs
    3021            0 :   std::string str = EnumItem::as_string ();
    3022              : 
    3023              :   // add equal and expression
    3024            0 :   str += " = " + expression->as_string ();
    3025              : 
    3026            0 :   return str;
    3027              : }
    3028              : 
    3029              : std::string
    3030            0 : ExternalTypeItem::as_string () const
    3031              : {
    3032            0 :   auto str = append_attributes (outer_attrs, OUTER);
    3033              : 
    3034            0 :   str += "type " + item_name.as_string () + ";";
    3035              : 
    3036            0 :   return str;
    3037              : }
    3038              : 
    3039              : std::string
    3040            0 : ExternalStaticItem::as_string () const
    3041              : {
    3042              :   // outer attributes
    3043            0 :   std::string str = append_attributes (outer_attrs, OUTER);
    3044              : 
    3045              :   // start visibility on new line and with a space
    3046            0 :   str += "\n" + visibility.as_string () + " ";
    3047              : 
    3048            0 :   str += "static ";
    3049              : 
    3050            0 :   if (has_mut)
    3051            0 :     str += "mut ";
    3052              : 
    3053              :   // add name
    3054            0 :   str += item_name.as_string ();
    3055              : 
    3056              :   // add type on new line
    3057            0 :   str += "\n Type: " + item_type->as_string ();
    3058              : 
    3059            0 :   return str;
    3060              : }
    3061              : 
    3062              : std::string
    3063            0 : TraitItemType::as_string () const
    3064              : {
    3065            0 :   std::string str = append_attributes (outer_attrs, OUTER);
    3066              : 
    3067            0 :   str += "\ntype " + name.as_string ();
    3068              : 
    3069            0 :   if (has_generics ())
    3070              :     {
    3071            0 :       str += "<";
    3072            0 :       for (size_t i = 0; i < generic_params.size (); i++)
    3073              :         {
    3074            0 :           if (i > 0)
    3075            0 :             str += ", ";
    3076            0 :           str += generic_params[i]->as_string ();
    3077              :         }
    3078            0 :       str += ">";
    3079              :     }
    3080              : 
    3081            0 :   str += "\n Type param bounds: ";
    3082            0 :   if (!has_type_param_bounds ())
    3083              :     {
    3084            0 :       str += "none";
    3085              :     }
    3086              :   else
    3087              :     {
    3088            0 :       for (const auto &bound : type_param_bounds)
    3089              :         {
    3090              :           // DEBUG: null pointer check
    3091            0 :           if (bound == nullptr)
    3092              :             {
    3093            0 :               rust_debug (
    3094              :                 "something really terrible has gone wrong - null pointer "
    3095              :                 "type param bound in trait item type.");
    3096            0 :               return "NULL_POINTER_MARK";
    3097              :             }
    3098              : 
    3099            0 :           str += "\n  " + bound->as_string ();
    3100              :         }
    3101              :     }
    3102              : 
    3103            0 :   return str;
    3104            0 : }
    3105              : 
    3106              : std::string
    3107            0 : SelfParam::as_string () const
    3108              : {
    3109              :   // TODO: rewrite to allow non-linearisable types
    3110            0 :   if (is_error ())
    3111              :     {
    3112            0 :       return "error";
    3113              :     }
    3114              :   else
    3115              :     {
    3116            0 :       if (has_type ())
    3117              :         {
    3118              :           // type (i.e. not ref, no lifetime)
    3119            0 :           std::string str;
    3120              : 
    3121            0 :           if (is_mut)
    3122            0 :             str += "mut ";
    3123              : 
    3124            0 :           str += "self : ";
    3125              : 
    3126            0 :           str += type->as_string ();
    3127              : 
    3128            0 :           return str;
    3129            0 :         }
    3130            0 :       else if (has_lifetime ())
    3131              :         {
    3132              :           // ref and lifetime
    3133            0 :           std::string str = "&" + get_lifetime ().as_string () + " ";
    3134              : 
    3135            0 :           if (is_mut)
    3136            0 :             str += "mut ";
    3137              : 
    3138            0 :           str += "self";
    3139              : 
    3140            0 :           return str;
    3141            0 :         }
    3142            0 :       else if (has_ref)
    3143              :         {
    3144              :           // ref with no lifetime
    3145            0 :           std::string str = "&";
    3146              : 
    3147            0 :           if (is_mut)
    3148            0 :             str += " mut ";
    3149              : 
    3150            0 :           str += "self";
    3151              : 
    3152            0 :           return str;
    3153            0 :         }
    3154              :       else
    3155              :         {
    3156              :           // no ref, no type
    3157            0 :           std::string str;
    3158              : 
    3159            0 :           if (is_mut)
    3160            0 :             str += "mut ";
    3161              : 
    3162            0 :           str += "self";
    3163              : 
    3164            0 :           return str;
    3165            0 :         }
    3166              :     }
    3167              : }
    3168              : 
    3169              : std::string
    3170            0 : ArrayElemsCopied::as_string () const
    3171              : {
    3172              :   // TODO: rewrite to allow non-linearisable exprs
    3173            0 :   return elem_to_copy->as_string () + "; " + num_copies->as_string ();
    3174              : }
    3175              : 
    3176              : std::string
    3177            0 : LifetimeWhereClauseItem::as_string () const
    3178              : {
    3179            0 :   std::string str ("Lifetime: ");
    3180              : 
    3181            0 :   str += lifetime.as_string ();
    3182              : 
    3183            0 :   str += "\nLifetime bounds: ";
    3184              : 
    3185            0 :   for (const auto &bound : lifetime_bounds)
    3186            0 :     str += "\n " + bound.as_string ();
    3187              : 
    3188            0 :   return str;
    3189              : }
    3190              : 
    3191              : std::string
    3192            0 : TypeBoundWhereClauseItem::as_string () const
    3193              : {
    3194            0 :   std::string str ("For lifetimes: ");
    3195              : 
    3196            0 :   if (!has_for_lifetimes ())
    3197              :     {
    3198            0 :       str += "none";
    3199              :     }
    3200              :   else
    3201              :     {
    3202            0 :       for (const auto &for_lifetime : for_lifetimes)
    3203            0 :         str += "\n " + for_lifetime.as_string ();
    3204              :     }
    3205              : 
    3206            0 :   str += "\nType: " + bound_type->as_string ();
    3207              : 
    3208            0 :   str += "\nType param bounds bounds: ";
    3209              : 
    3210            0 :   for (const auto &bound : type_param_bounds)
    3211              :     {
    3212              :       // debug null pointer check
    3213            0 :       if (bound == nullptr)
    3214            0 :         return "NULL_POINTER_MARK - type param bounds";
    3215              : 
    3216            0 :       str += "\n " + bound->as_string ();
    3217              :     }
    3218              : 
    3219            0 :   return str;
    3220            0 : }
    3221              : 
    3222              : std::string
    3223            0 : ArrayElemsValues::as_string () const
    3224              : {
    3225            0 :   std::string str;
    3226              : 
    3227            0 :   for (const auto &expr : values)
    3228              :     {
    3229              :       // DEBUG: null pointer check
    3230            0 :       if (expr == nullptr)
    3231              :         {
    3232            0 :           rust_debug ("something really terrible has gone wrong - null pointer "
    3233              :                       "expr in array elems values.");
    3234            0 :           return "NULL_POINTER_MARK";
    3235              :         }
    3236              : 
    3237            0 :       str += "\n  " + expr->as_string ();
    3238              :     }
    3239              : 
    3240            0 :   return str;
    3241            0 : }
    3242              : 
    3243              : std::string
    3244            0 : MaybeNamedParam::as_string () const
    3245              : {
    3246              :   // TODO: rewrite to allow using non-linearisable types in dump
    3247            0 :   std::string str;
    3248              : 
    3249            0 :   switch (param_kind)
    3250              :     {
    3251              :     case UNNAMED:
    3252              :       break;
    3253            0 :     case IDENTIFIER:
    3254            0 :       str = name.as_string () + " : ";
    3255            0 :       break;
    3256            0 :     case WILDCARD:
    3257            0 :       str = "_ : ";
    3258            0 :       break;
    3259            0 :     default:
    3260            0 :       return "ERROR_MARK_STRING - maybe named param unrecognised param kind";
    3261              :     }
    3262              : 
    3263            0 :   str += param_type->as_string ();
    3264              : 
    3265            0 :   return str;
    3266            0 : }
    3267              : 
    3268        12788 : MetaItemInner::~MetaItemInner () = default;
    3269              : 
    3270              : std::unique_ptr<MetaNameValueStr>
    3271            0 : MetaItemInner::to_meta_name_value_str () const
    3272              : {
    3273            0 :   if (is_key_value_pair ())
    3274              :     {
    3275            0 :       auto converted_item = static_cast<const MetaNameValueStr *> (this);
    3276            0 :       return converted_item->to_meta_name_value_str ();
    3277              :     }
    3278              :   // TODO actually parse foo = bar
    3279            0 :   return nullptr;
    3280              : }
    3281              : 
    3282              : std::string
    3283          126 : MetaItemSeq::as_string () const
    3284              : {
    3285          126 :   std::string path_str = path.as_string () + "(";
    3286              : 
    3287          126 :   auto i = seq.begin ();
    3288          126 :   auto e = seq.end ();
    3289              : 
    3290          282 :   for (; i != e; i++)
    3291              :     {
    3292          312 :       path_str += (*i)->as_string ();
    3293          156 :       if (e != i + 1)
    3294           30 :         path_str += ", ";
    3295              :     }
    3296              : 
    3297          126 :   return path_str + ")";
    3298          126 : }
    3299              : 
    3300              : std::string
    3301            0 : MetaListPaths::as_string () const
    3302              : {
    3303            0 :   std::string str = ident.as_string () + "(";
    3304              : 
    3305            0 :   auto i = paths.begin ();
    3306            0 :   auto e = paths.end ();
    3307              : 
    3308            0 :   for (; i != e; i++)
    3309              :     {
    3310            0 :       str += (*i).as_string ();
    3311            0 :       if (e != i + 1)
    3312            0 :         str += ", ";
    3313              :     }
    3314              : 
    3315            0 :   return str + ")";
    3316            0 : }
    3317              : 
    3318              : std::string
    3319            0 : MetaListNameValueStr::as_string () const
    3320              : {
    3321            0 :   std::string str = ident.as_string () + "(";
    3322              : 
    3323            0 :   auto i = strs.begin ();
    3324            0 :   auto e = strs.end ();
    3325              : 
    3326            0 :   for (; i != e; i++)
    3327              :     {
    3328            0 :       str += (*i).as_string ();
    3329            0 :       if (e != i + 1)
    3330            0 :         str += ", ";
    3331              :     }
    3332              : 
    3333            0 :   return str + ")";
    3334            0 : }
    3335              : 
    3336              : std::string
    3337         2115 : AttrInputMetaItemContainer::as_string () const
    3338              : {
    3339         2115 :   std::string str = "(";
    3340              : 
    3341         2115 :   auto i = items.begin ();
    3342         2115 :   auto e = items.end ();
    3343              : 
    3344         4230 :   for (; i != e; i++)
    3345              :     {
    3346         4230 :       str += (*i)->as_string ();
    3347         2115 :       if (e != i + 1)
    3348            1 :         str += ", ";
    3349              :     }
    3350              : 
    3351         2115 :   return str + ")";
    3352         2115 : }
    3353              : 
    3354           19 : AttrInputExpr::AttrInputExpr (const AttrInputExpr &oth)
    3355           19 :   : expr (oth.expr->clone_expr ())
    3356           19 : {}
    3357              : 
    3358              : AttrInputExpr &
    3359            0 : AttrInputExpr::operator= (const AttrInputExpr &oth)
    3360              : {
    3361            0 :   expr = oth.expr->clone_expr ();
    3362            0 :   return *this;
    3363              : }
    3364              : 
    3365              : std::string
    3366            0 : AttrInputExpr::as_string () const
    3367              : {
    3368            0 :   return expr->as_string ();
    3369              : }
    3370              : 
    3371              : void
    3372           56 : AttrInputExpr::accept_vis (ASTVisitor &vis)
    3373              : {
    3374           56 :   vis.visit (*this);
    3375           56 : }
    3376              : 
    3377              : /* Override that calls the function recursively on all items contained within
    3378              :  * the module. */
    3379              : void
    3380            0 : Module::add_crate_name (std::vector<std::string> &names) const
    3381              : {
    3382              :   /* TODO: test whether module has been 'cfg'-ed out to determine whether to
    3383              :    * exclude it from search */
    3384              : 
    3385            0 :   for (const auto &item : items)
    3386            0 :     item->add_crate_name (names);
    3387            0 : }
    3388              : 
    3389              : static bool
    3390          121 : file_exists (const std::string path)
    3391              : {
    3392              :   // Simply check if the file exists
    3393              :   // FIXME: This does not work on Windows
    3394            0 :   return access (path.c_str (), F_OK) != -1;
    3395              : }
    3396              : 
    3397              : static std::string
    3398           79 : filename_from_path_attribute (std::vector<Attribute> &outer_attrs)
    3399              : {
    3400              :   // An out-of-line module cannot have inner attributes. Additionally, the
    3401              :   // default name is specified as `""` so that the caller can detect the case
    3402              :   // of "no path given" and use the default path logic (`name.rs` or
    3403              :   // `name/mod.rs`).
    3404           79 :   return extract_module_path ({}, outer_attrs, "");
    3405              : }
    3406              : 
    3407              : void
    3408           82 : Module::process_file_path ()
    3409              : {
    3410           82 :   rust_assert (kind == Module::ModuleKind::UNLOADED);
    3411              : 
    3412           82 :   if (!module_file.empty ())
    3413              :     {
    3414            3 :       rust_error_at (locus, "error handling module file for %qs",
    3415            3 :                      module_name.as_string ().c_str ());
    3416           67 :       return;
    3417              :     }
    3418              : 
    3419              :   // This corresponds to the path of the file 'including' the module. So the
    3420              :   // file that contains the 'mod <file>;' directive
    3421           79 :   std::string including_fpath (outer_filename);
    3422              : 
    3423           79 :   std::string expected_file_path = module_name.as_string () + ".rs";
    3424           79 :   std::string expected_dir_path = "mod.rs";
    3425              : 
    3426           79 :   auto dir_slash_pos = including_fpath.rfind (file_separator);
    3427           79 :   std::string current_directory_name;
    3428           79 :   std::string including_fname;
    3429              : 
    3430              :   // If we haven't found a file_separator, then we may have to look for files in
    3431              :   // the current directory ('.')
    3432           79 :   if (dir_slash_pos == std::string::npos)
    3433              :     {
    3434            1 :       including_fname = std::move (including_fpath);
    3435            2 :       including_fpath = std::string (".") + file_separator + including_fname;
    3436            1 :       dir_slash_pos = 1;
    3437              :     }
    3438              :   else
    3439              :     {
    3440           78 :       including_fname = including_fpath.substr (dir_slash_pos + 1);
    3441              :     }
    3442              : 
    3443           79 :   current_directory_name
    3444          158 :     = including_fpath.substr (0, dir_slash_pos) + file_separator;
    3445              : 
    3446           79 :   auto path_string = filename_from_path_attribute (get_outer_attrs ());
    3447              : 
    3448           79 :   std::string including_subdir;
    3449           79 :   bool subdir_was_added = false;
    3450           79 :   if (path_string.empty () && module_scope.empty ()
    3451          117 :       && get_file_subdir (including_fname, including_subdir))
    3452              :     {
    3453           76 :       current_directory_name += including_subdir + file_separator;
    3454           38 :       subdir_was_added = true;
    3455              :     }
    3456              : 
    3457              :   // Handle inline module declarations adding path components.
    3458           84 :   for (auto const &name : module_scope)
    3459              :     {
    3460            5 :       current_directory_name.append (name);
    3461            5 :       current_directory_name.append (file_separator);
    3462              :     }
    3463              : 
    3464           79 :   if (!path_string.empty ())
    3465              :     {
    3466           40 :       module_file = current_directory_name + path_string;
    3467           40 :       return;
    3468              :     }
    3469              : 
    3470              :   // FIXME: We also have to search for
    3471              :   // <directory>/<including_fname>/<module_name>.rs In rustc, this is done via
    3472              :   // the concept of `DirOwnernship`, which is based on whether or not the
    3473              :   // current file is titled `mod.rs`.
    3474              : 
    3475              :   // First, we search for <directory>/<module_name>.rs
    3476           39 :   std::string file_mod_path = current_directory_name + expected_file_path;
    3477           78 :   bool file_mod_found = file_exists (file_mod_path);
    3478              : 
    3479              :   // Then, search for <directory>/<module_name>/mod.rs
    3480           39 :   std::string dir_mod_path = current_directory_name + module_name.as_string ()
    3481           39 :                              + file_separator + expected_dir_path;
    3482           78 :   bool dir_mod_found = file_exists (dir_mod_path);
    3483              : 
    3484           39 :   if (!file_mod_found && !dir_mod_found && subdir_was_added)
    3485              :     {
    3486           22 :       size_t suffix_len
    3487           22 :         = including_subdir.length () + std::string (file_separator).length ();
    3488           22 :       std::string fallback_dir
    3489           22 :         = current_directory_name.substr (0, current_directory_name.length ()
    3490           22 :                                               - suffix_len);
    3491           22 :       std::string fallback_file = fallback_dir + expected_file_path;
    3492           22 :       std::string fallback_dir_mod = fallback_dir + module_name.as_string ()
    3493           22 :                                      + file_separator + expected_dir_path;
    3494           44 :       if (file_exists (fallback_file))
    3495              :         {
    3496            1 :           file_mod_found = true;
    3497            1 :           file_mod_path = fallback_file;
    3498              :         }
    3499           42 :       else if (file_exists (fallback_dir_mod))
    3500              :         {
    3501            0 :           dir_mod_found = true;
    3502            0 :           dir_mod_path = fallback_dir_mod;
    3503              :         }
    3504           22 :     }
    3505              : 
    3506           39 :   bool multiple_candidates_found = file_mod_found && dir_mod_found;
    3507           39 :   bool no_candidates_found = !file_mod_found && !dir_mod_found;
    3508              : 
    3509           39 :   if (multiple_candidates_found)
    3510            0 :     rust_error_at (locus,
    3511              :                    "two candidates found for module %s: %s.rs and %s%smod.rs",
    3512            0 :                    module_name.as_string ().c_str (),
    3513            0 :                    module_name.as_string ().c_str (),
    3514            0 :                    module_name.as_string ().c_str (), file_separator);
    3515              : 
    3516           39 :   if (no_candidates_found)
    3517           21 :     rust_error_at (locus, "no candidate found for module %s",
    3518           21 :                    module_name.as_string ().c_str ());
    3519              : 
    3520           39 :   if (no_candidates_found || multiple_candidates_found)
    3521           21 :     return;
    3522              : 
    3523           33 :   module_file = std::move (file_mod_found ? file_mod_path : dir_mod_path);
    3524          100 : }
    3525              : 
    3526              : void
    3527           82 : Module::load_items ()
    3528              : {
    3529           82 :   process_file_path ();
    3530              : 
    3531              :   // We will already have errored out appropriately in the process_file_path ()
    3532              :   // method
    3533           82 :   if (module_file.empty ())
    3534           32 :     return;
    3535              : 
    3536           61 :   RAIIFile file_wrap (module_file.c_str ());
    3537           61 :   Linemap *linemap = Session::get_instance ().linemap;
    3538           61 :   if (!file_wrap.ok ())
    3539              :     {
    3540           11 :       rust_error_at (get_locus (), "cannot open module file %s: %m",
    3541              :                      module_file.c_str ());
    3542           11 :       return;
    3543              :     }
    3544              : 
    3545           50 :   rust_debug ("Attempting to parse file %s", module_file.c_str ());
    3546              : 
    3547           50 :   Lexer lex (module_file.c_str (), std::move (file_wrap), linemap);
    3548           50 :   Parser<Lexer> parser (lex);
    3549              : 
    3550              :   // we need to parse any possible inner attributes for this module
    3551           50 :   inner_attrs = parser.parse_inner_attributes ();
    3552           50 :   auto parsed_items = parser.parse_items ().value_or (
    3553           50 :     std::vector<std::unique_ptr<AST::Item>>{});
    3554              : 
    3555           50 :   for (const auto &error : parser.get_errors ())
    3556            0 :     error.emit ();
    3557              : 
    3558           50 :   items = std::move (parsed_items);
    3559           50 :   kind = ModuleKind::LOADED;
    3560           61 : }
    3561              : 
    3562              : void
    3563         1002 : Attribute::parse_attr_to_meta_item ()
    3564              : {
    3565              :   // only parse if has attribute input and not already parsed
    3566         1002 :   if (!has_attr_input () || is_parsed_to_meta_item ())
    3567          338 :     return;
    3568              : 
    3569          664 :   auto res = attr_input->parse_to_meta_item ();
    3570          664 :   std::unique_ptr<AttrInput> converted_input (res);
    3571              : 
    3572          664 :   if (converted_input != nullptr)
    3573          664 :     attr_input = std::move (converted_input);
    3574          664 : }
    3575              : 
    3576              : AttrInputMetaItemContainer *
    3577        10266 : DelimTokenTree::parse_to_meta_item () const
    3578              : {
    3579              :   // must have token trees
    3580        10266 :   if (token_trees.empty ())
    3581              :     return nullptr;
    3582              : 
    3583              :   /* assume top-level delim token tree in attribute - convert all nested ones
    3584              :    * to token stream */
    3585        10266 :   std::vector<std::unique_ptr<Token>> token_stream_wrapped = to_token_stream ();
    3586              : 
    3587        10266 :   std::vector<const_TokenPtr> token_stream;
    3588        10266 :   token_stream.reserve (token_stream_wrapped.size ());
    3589        51172 :   for (auto &tk : token_stream_wrapped)
    3590        81812 :     token_stream.push_back (tk->get_tok_ptr ());
    3591              : 
    3592        10266 :   AttributeParser parser (std::move (token_stream));
    3593        10266 :   std::vector<std::unique_ptr<MetaItemInner>> meta_items (
    3594        10266 :     parser.parse_meta_item_seq ());
    3595              : 
    3596        10266 :   return new AttrInputMetaItemContainer (std::move (meta_items));
    3597        10266 : }
    3598              : 
    3599        10266 : AttributeParser::AttributeParser (std::vector<const_TokenPtr> token_stream,
    3600        10266 :                                   int stream_start_pos)
    3601        10266 :   : lexer (new MacroInvocLexer (std::move (token_stream))),
    3602        10266 :     parser (new Parser<MacroInvocLexer> (*lexer))
    3603              : {
    3604        10266 :   if (stream_start_pos)
    3605            0 :     lexer->skip_token (stream_start_pos - 1);
    3606        10266 : }
    3607              : 
    3608        10266 : AttributeParser::~AttributeParser () {}
    3609              : 
    3610              : std::unique_ptr<MetaItemInner>
    3611        11655 : AttributeParser::parse_meta_item_inner ()
    3612              : {
    3613              :   // if first tok not identifier, not a "special" case one
    3614        23310 :   if (lexer->peek_token ()->get_id () != IDENTIFIER)
    3615              :     {
    3616           56 :       switch (lexer->peek_token ()->get_id ())
    3617              :         {
    3618           28 :         case CHAR_LITERAL:
    3619           28 :         case STRING_LITERAL:
    3620           28 :         case BYTE_CHAR_LITERAL:
    3621           28 :         case BYTE_STRING_LITERAL:
    3622           28 :         case RAW_STRING_LITERAL:
    3623           28 :         case INT_LITERAL:
    3624           28 :         case FLOAT_LITERAL:
    3625           28 :         case TRUE_LITERAL:
    3626           28 :         case FALSE_LITERAL:
    3627           28 :           return parse_meta_item_lit ();
    3628              : 
    3629            0 :         case SUPER:
    3630            0 :         case SELF:
    3631            0 :         case CRATE:
    3632            0 :         case DOLLAR_SIGN:
    3633            0 :         case SCOPE_RESOLUTION:
    3634            0 :           return parse_path_meta_item ();
    3635              : 
    3636            0 :         default:
    3637            0 :           rust_error_at (lexer->peek_token ()->get_locus (),
    3638              :                          "unrecognised token '%s' in meta item",
    3639              :                          get_token_description (
    3640            0 :                            lexer->peek_token ()->get_id ()));
    3641            0 :           return nullptr;
    3642              :         }
    3643              :     }
    3644              : 
    3645              :   // else, check for path
    3646        23254 :   if (lexer->peek_token (1)->get_id () == SCOPE_RESOLUTION)
    3647              :     {
    3648              :       // path
    3649            0 :       return parse_path_meta_item ();
    3650              :     }
    3651              : 
    3652        23254 :   auto ident = lexer->peek_token ()->get_str ();
    3653        11627 :   auto ident_locus = lexer->peek_token ()->get_locus ();
    3654              : 
    3655        23254 :   if (is_end_meta_item_tok (lexer->peek_token (1)->get_id ()))
    3656              :     {
    3657              :       // meta word syntax
    3658         7913 :       lexer->skip_token ();
    3659        23739 :       return std::unique_ptr<MetaWord> (new MetaWord (ident, ident_locus));
    3660              :     }
    3661              : 
    3662         7428 :   if (lexer->peek_token (1)->get_id () == EQUAL)
    3663              :     {
    3664              :       // maybe meta name value str syntax - check next 2 tokens
    3665         7202 :       if (lexer->peek_token (2)->get_id () == STRING_LITERAL
    3666         7200 :           && is_end_meta_item_tok (lexer->peek_token (3)->get_id ()))
    3667              :         {
    3668              :           // meta name value str syntax
    3669         3599 :           const_TokenPtr value_tok = lexer->peek_token (2);
    3670         3599 :           auto value = value_tok->get_str ();
    3671         3599 :           auto locus = value_tok->get_locus ();
    3672              : 
    3673         3599 :           lexer->skip_token (2);
    3674              : 
    3675         3599 :           return std::unique_ptr<MetaNameValueStr> (
    3676         7198 :             new MetaNameValueStr (ident, ident_locus, std::move (value),
    3677        10797 :                                   locus));
    3678         7198 :         }
    3679              :       else
    3680              :         {
    3681              :           // just interpret as path-based meta item
    3682            2 :           return parse_path_meta_item ();
    3683              :         }
    3684              :     }
    3685              : 
    3686          226 :   if (lexer->peek_token (1)->get_id () != LEFT_PAREN)
    3687              :     {
    3688            0 :       rust_error_at (lexer->peek_token (1)->get_locus (),
    3689              :                      "unexpected token '%s' after identifier in attribute",
    3690            0 :                      get_token_description (lexer->peek_token (1)->get_id ()));
    3691            0 :       return nullptr;
    3692              :     }
    3693              : 
    3694              :   // is it one of those special cases like not?
    3695          226 :   if (lexer->peek_token ()->get_id () == IDENTIFIER)
    3696              :     {
    3697          113 :       return parse_path_meta_item ();
    3698              :     }
    3699              : 
    3700            0 :   auto meta_items = parse_meta_item_seq ();
    3701              : 
    3702              :   // pass for meta name value str
    3703            0 :   std::vector<MetaNameValueStr> meta_name_value_str_items;
    3704            0 :   for (const auto &item : meta_items)
    3705              :     {
    3706            0 :       std::unique_ptr<MetaNameValueStr> converted_item
    3707            0 :         = item->to_meta_name_value_str ();
    3708            0 :       if (converted_item == nullptr)
    3709              :         {
    3710            0 :           meta_name_value_str_items.clear ();
    3711            0 :           break;
    3712              :         }
    3713            0 :       meta_name_value_str_items.push_back (std::move (*converted_item));
    3714            0 :     }
    3715              :   // if valid, return this
    3716            0 :   if (!meta_name_value_str_items.empty ())
    3717              :     {
    3718            0 :       return std::unique_ptr<MetaListNameValueStr> (
    3719            0 :         new MetaListNameValueStr (ident, ident_locus,
    3720            0 :                                   std::move (meta_name_value_str_items)));
    3721              :     }
    3722              : 
    3723              :   // // pass for meta list idents
    3724              :   // std::vector<Identifier> ident_items;
    3725              :   // for (const auto &item : meta_items)
    3726              :   //   {
    3727              :   //     std::unique_ptr<Identifier> converted_ident (item->to_ident_item ());
    3728              :   //     if (converted_ident == nullptr)
    3729              :   //       {
    3730              :   //         ident_items.clear ();
    3731              :   //         break;
    3732              :   //       }
    3733              :   //     ident_items.push_back (std::move (*converted_ident));
    3734              :   //   }
    3735              :   // // if valid return this
    3736              :   // if (!ident_items.empty ())
    3737              :   //   {
    3738              :   //     return std::unique_ptr<MetaListIdents> (
    3739              :   //       new MetaListIdents (std::move (ident), std::move (ident_items)));
    3740              :   //   }
    3741              :   // // as currently no meta list ident, currently no path. may change in future
    3742              : 
    3743              :   // pass for meta list paths
    3744            0 :   std::vector<SimplePath> path_items;
    3745            0 :   for (const auto &item : meta_items)
    3746              :     {
    3747            0 :       SimplePath converted_path (item->to_path_item ());
    3748            0 :       if (converted_path.is_empty ())
    3749              :         {
    3750            0 :           path_items.clear ();
    3751            0 :           break;
    3752              :         }
    3753            0 :       path_items.push_back (std::move (converted_path));
    3754            0 :     }
    3755            0 :   if (!path_items.empty ())
    3756              :     {
    3757            0 :       return std::unique_ptr<MetaListPaths> (
    3758            0 :         new MetaListPaths (ident, ident_locus, std::move (path_items)));
    3759              :     }
    3760              : 
    3761            0 :   rust_error_at (UNKNOWN_LOCATION, "failed to parse any meta item inner");
    3762            0 :   return nullptr;
    3763        11627 : }
    3764              : 
    3765              : bool
    3766        15226 : AttributeParser::is_end_meta_item_tok (TokenId id) const
    3767              : {
    3768        15226 :   return id == COMMA || id == RIGHT_PAREN;
    3769              : }
    3770              : 
    3771              : std::unique_ptr<MetaItem>
    3772          115 : AttributeParser::parse_path_meta_item ()
    3773              : {
    3774          115 :   auto path = parser->parse_simple_path ();
    3775          115 :   if (!path)
    3776              :     {
    3777            0 :       rust_error_at (lexer->peek_token ()->get_locus (),
    3778              :                      "failed to parse simple path in attribute");
    3779            0 :       return nullptr;
    3780              :     }
    3781              : 
    3782          230 :   switch (lexer->peek_token ()->get_id ())
    3783              :     {
    3784          113 :     case LEFT_PAREN:
    3785          113 :       {
    3786          113 :         std::vector<std::unique_ptr<MetaItemInner>> meta_items
    3787          113 :           = parse_meta_item_seq ();
    3788              : 
    3789          113 :         return std::unique_ptr<MetaItemSeq> (
    3790          226 :           new MetaItemSeq (std::move (path.value ()), std::move (meta_items)));
    3791          113 :       }
    3792            2 :     case EQUAL:
    3793            2 :       {
    3794            2 :         lexer->skip_token ();
    3795              : 
    3796            2 :         auto expr = parser->parse_expr ();
    3797              : 
    3798              :         // handle error
    3799              :         // parse_expr should already emit an error and return nullptr
    3800            2 :         if (!expr)
    3801            0 :           return nullptr;
    3802              : 
    3803            2 :         return std::unique_ptr<MetaItemPathExpr> (
    3804            2 :           new MetaItemPathExpr (std::move (path.value ()),
    3805            4 :                                 std::move (expr.value ())));
    3806            2 :       }
    3807            0 :     case COMMA:
    3808              :       // just simple path
    3809            0 :       return std::unique_ptr<MetaItemPath> (
    3810            0 :         new MetaItemPath (std::move (path.value ())));
    3811            0 :     default:
    3812            0 :       rust_error_at (lexer->peek_token ()->get_locus (),
    3813              :                      "unrecognised token '%s' in meta item",
    3814            0 :                      get_token_description (lexer->peek_token ()->get_id ()));
    3815            0 :       return nullptr;
    3816              :     }
    3817          115 : }
    3818              : 
    3819              : /* Parses a parenthesised sequence of meta item inners. Parentheses are
    3820              :  * required here. */
    3821              : std::vector<std::unique_ptr<MetaItemInner>>
    3822        10379 : AttributeParser::parse_meta_item_seq ()
    3823              : {
    3824        10379 :   std::vector<std::unique_ptr<MetaItemInner>> meta_items;
    3825              : 
    3826        20758 :   if (lexer->peek_token ()->get_id () != LEFT_PAREN)
    3827              :     {
    3828            0 :       rust_error_at (lexer->peek_token ()->get_locus (),
    3829              :                      "missing left paren in delim token tree");
    3830            0 :       return {};
    3831              :     }
    3832        10379 :   lexer->skip_token ();
    3833              : 
    3834        10379 :   while (lexer->peek_token ()->get_id () != END_OF_FILE
    3835        34986 :          && lexer->peek_token ()->get_id () != RIGHT_PAREN)
    3836              :     {
    3837        11655 :       std::unique_ptr<MetaItemInner> inner = parse_meta_item_inner ();
    3838        11655 :       if (inner == nullptr)
    3839              :         {
    3840            0 :           rust_error_at (lexer->peek_token ()->get_locus (),
    3841              :                          "failed to parse inner meta item in attribute");
    3842            0 :           return {};
    3843              :         }
    3844        11655 :       meta_items.push_back (std::move (inner));
    3845              : 
    3846        23310 :       if (lexer->peek_token ()->get_id () != COMMA)
    3847              :         break;
    3848              : 
    3849         1283 :       lexer->skip_token ();
    3850        11655 :     }
    3851              : 
    3852        20758 :   if (lexer->peek_token ()->get_id () != RIGHT_PAREN)
    3853              :     {
    3854            0 :       rust_error_at (lexer->peek_token ()->get_locus (),
    3855              :                      "missing right paren in delim token tree");
    3856            0 :       return {};
    3857              :     }
    3858        10379 :   lexer->skip_token ();
    3859              : 
    3860        10379 :   return meta_items;
    3861        10379 : }
    3862              : 
    3863              : /* Collects any nested token trees into a flat token stream, suitable for
    3864              :  * parsing. */
    3865              : std::vector<std::unique_ptr<Token>>
    3866        27666 : DelimTokenTree::to_token_stream () const
    3867              : {
    3868        27666 :   std::vector<std::unique_ptr<Token>> tokens;
    3869       190571 :   for (const auto &tree : token_trees)
    3870              :     {
    3871       162905 :       std::vector<std::unique_ptr<Token>> stream = tree->to_token_stream ();
    3872              : 
    3873       162905 :       tokens.insert (tokens.end (), std::make_move_iterator (stream.begin ()),
    3874              :                      std::make_move_iterator (stream.end ()));
    3875       162905 :     }
    3876              : 
    3877        27666 :   tokens.shrink_to_fit ();
    3878        27666 :   return tokens;
    3879              : }
    3880              : 
    3881              : std::unique_ptr<MetaItemLitExpr>
    3882           28 : AttributeParser::parse_meta_item_lit ()
    3883              : {
    3884           28 :   auto lit_expr = parser->parse_literal_expr ({});
    3885              : 
    3886              :   // TODO: return nullptr instead?
    3887           28 :   if (!lit_expr)
    3888            0 :     lit_expr = std::unique_ptr<LiteralExpr> (
    3889            0 :       new LiteralExpr (Literal::create_error (), {},
    3890            0 :                        lexer->peek_token ()->get_locus ()));
    3891              : 
    3892           28 :   return std::unique_ptr<MetaItemLitExpr> (
    3893           28 :     new MetaItemLitExpr (std::move (*lit_expr.value ())));
    3894           28 : }
    3895              : 
    3896              : bool
    3897            0 : AttrInputMetaItemContainer::check_cfg_predicate (const Session &session) const
    3898              : {
    3899            0 :   if (items.empty ())
    3900              :     return false;
    3901              : 
    3902            0 :   for (const auto &inner_item : items)
    3903              :     {
    3904            0 :       if (!inner_item->check_cfg_predicate (session))
    3905            0 :         return false;
    3906              :     }
    3907              : 
    3908              :   return true;
    3909              : }
    3910              : 
    3911              : bool
    3912            1 : MetaItemLitExpr::check_cfg_predicate (const Session &) const
    3913              : {
    3914              :   /* as far as I can tell, a literal expr can never be a valid cfg body, so
    3915              :    * false */
    3916            1 :   rust_error_at (this->get_locus (), "'%s' predicate key cannot be a literal",
    3917            1 :                  this->as_string ().c_str ());
    3918              : 
    3919            1 :   return false;
    3920              : }
    3921              : 
    3922              : bool
    3923            0 : MetaListNameValueStr::check_cfg_predicate (const Session &session) const
    3924              : {
    3925            0 :   if (ident.as_string () == "all")
    3926              :     {
    3927            0 :       for (const auto &str : strs)
    3928              :         {
    3929            0 :           if (!str.check_cfg_predicate (session))
    3930            0 :             return false;
    3931              :         }
    3932              :       return true;
    3933              :     }
    3934            0 :   else if (ident.as_string () == "any")
    3935              :     {
    3936            0 :       for (const auto &str : strs)
    3937              :         {
    3938            0 :           if (str.check_cfg_predicate (session))
    3939            0 :             return true;
    3940              :         }
    3941              :       return false;
    3942              :     }
    3943            0 :   else if (ident.as_string () == "not")
    3944              :     {
    3945            0 :       if (strs.size () != 1)
    3946              :         {
    3947              :           /* HACK: convert vector platform-dependent size_type to string to
    3948              :            * use in printf */
    3949            0 :           rust_error_at (UNKNOWN_LOCATION,
    3950              :                          "cfg predicate could not be checked for "
    3951              :                          "MetaListNameValueStr with ident of "
    3952              :                          "'not' because there are '%s' elements, not '1'",
    3953            0 :                          std::to_string (strs.size ()).c_str ());
    3954            0 :           return false;
    3955              :         }
    3956              : 
    3957            0 :       return !strs[0].check_cfg_predicate (session);
    3958              :     }
    3959              :   else
    3960              :     {
    3961            0 :       rust_error_at (UNKNOWN_LOCATION,
    3962              :                      "cfg predicate could not be checked for "
    3963              :                      "MetaListNameValueStr with ident of "
    3964              :                      "'%s' - ident must be 'all' or 'any'",
    3965            0 :                      ident.as_string ().c_str ());
    3966            0 :       return false;
    3967              :     }
    3968              : }
    3969              : 
    3970              : bool
    3971            0 : MetaListPaths::check_cfg_predicate (const Session &session) const
    3972              : {
    3973            0 :   if (ident.as_string () == "all")
    3974              :     {
    3975            0 :       for (const auto &path : paths)
    3976              :         {
    3977            0 :           if (!check_path_exists_in_cfg (session, path))
    3978            0 :             return false;
    3979              :         }
    3980              :       return true;
    3981              :     }
    3982            0 :   else if (ident.as_string () == "any")
    3983              :     {
    3984            0 :       for (const auto &path : paths)
    3985              :         {
    3986            0 :           if (check_path_exists_in_cfg (session, path))
    3987            0 :             return true;
    3988              :         }
    3989              :       return false;
    3990              :     }
    3991            0 :   else if (ident.as_string () == "not")
    3992              :     {
    3993            0 :       if (paths.size () != 1)
    3994              :         {
    3995              :           // HACK: convert vector platform-dependent size_type to string to
    3996              :           // use in printf
    3997            0 :           rust_error_at (UNKNOWN_LOCATION,
    3998              :                          "cfg predicate could not be checked for MetaListPaths "
    3999              :                          "with ident of 'not' "
    4000              :                          "because there are '%s' elements, not '1'",
    4001            0 :                          std::to_string (paths.size ()).c_str ());
    4002            0 :           return false;
    4003              :         }
    4004              : 
    4005            0 :       return !check_path_exists_in_cfg (session, paths[0]);
    4006              :     }
    4007              :   else
    4008              :     {
    4009            0 :       rust_error_at (UNKNOWN_LOCATION,
    4010              :                      "cfg predicate could not be checked for "
    4011              :                      "MetaListNameValueStr with ident of "
    4012              :                      "'%s' - ident must be 'all' or 'any'",
    4013            0 :                      ident.as_string ().c_str ());
    4014            0 :       return false;
    4015              :     }
    4016              : }
    4017              : 
    4018              : bool
    4019            0 : MetaListPaths::check_path_exists_in_cfg (const Session &session,
    4020              :                                          const SimplePath &path) const
    4021              : {
    4022            0 :   return session.options.target_data.has_key (path.as_string ());
    4023              : }
    4024              : 
    4025              : bool
    4026          119 : MetaItemSeq::check_cfg_predicate (const Session &session) const
    4027              : {
    4028          119 :   if (path.as_string () == "all")
    4029              :     {
    4030           19 :       for (const auto &item : seq)
    4031              :         {
    4032           15 :           if (!item->check_cfg_predicate (session))
    4033           13 :             return false;
    4034              :         }
    4035              :       return true;
    4036              :     }
    4037          108 :   else if (path.as_string () == "any")
    4038              :     {
    4039           32 :       for (const auto &item : seq)
    4040              :         {
    4041           26 :           if (item->check_cfg_predicate (session))
    4042            9 :             return true;
    4043              :         }
    4044              :       return false;
    4045              :     }
    4046           97 :   else if (path.as_string () == "not")
    4047              :     {
    4048           97 :       if (seq.size () != 1)
    4049              :         {
    4050              :           /* HACK: convert vector platform-dependent size_type to string to
    4051              :            * use in printf */
    4052            0 :           rust_error_at (UNKNOWN_LOCATION,
    4053              :                          "cfg predicate could not be checked for MetaItemSeq "
    4054              :                          "with ident of 'not' "
    4055              :                          "because there are '%s' elements, not '1'",
    4056            0 :                          std::to_string (seq.size ()).c_str ());
    4057            0 :           return false;
    4058              :         }
    4059              : 
    4060           97 :       return !seq[0]->check_cfg_predicate (session);
    4061              :     }
    4062              :   else
    4063              :     {
    4064            0 :       rust_error_at (
    4065              :         UNKNOWN_LOCATION,
    4066              :         "cfg predicate could not be checked for MetaItemSeq with path of "
    4067              :         "'%s' - path must be 'all' or 'any'",
    4068            0 :         path.as_string ().c_str ());
    4069            0 :       return false;
    4070              :     }
    4071              : }
    4072              : 
    4073              : bool
    4074          323 : MetaWord::check_cfg_predicate (const Session &session) const
    4075              : {
    4076          646 :   return session.options.target_data.has_key (ident.as_string ());
    4077              : }
    4078              : 
    4079              : bool
    4080            0 : MetaItemPath::check_cfg_predicate (const Session &session) const
    4081              : {
    4082              :   /* Strictly speaking, this should always be false, but maybe do check
    4083              :    * relating to SimplePath being identifier. Currently, it would return true
    4084              :    * if path as identifier existed, and if the path in string form existed
    4085              :    * (though this shouldn't occur). */
    4086            0 :   return session.options.target_data.has_key (path.as_string ());
    4087              : }
    4088              : 
    4089              : bool
    4090         1884 : MetaNameValueStr::check_cfg_predicate (const Session &session) const
    4091              : {
    4092              :   // DEBUG
    4093         5684 :   rust_debug (
    4094              :     "checked key-value pair for cfg: '%s', '%s' - is%s in target data",
    4095              :     ident.as_string ().c_str (), str.c_str (),
    4096              :     session.options.target_data.has_key_value_pair (ident.as_string (), str)
    4097              :       ? ""
    4098              :       : " not");
    4099              : 
    4100         3768 :   return session.options.target_data.has_key_value_pair (ident.as_string (),
    4101         1884 :                                                          str);
    4102              : }
    4103              : 
    4104              : bool
    4105            0 : MetaItemPathExpr::check_cfg_predicate (const Session &session) const
    4106              : {
    4107              :   // FIXME: Accept path expressions
    4108            0 :   rust_assert (expr->is_literal ());
    4109            0 :   return session.options.target_data.has_key_value_pair (path.as_string (),
    4110            0 :                                                          expr->as_string ());
    4111              : }
    4112              : 
    4113              : std::vector<std::unique_ptr<Token>>
    4114       154738 : Token::to_token_stream () const
    4115              : {
    4116              :   /* initialisation list doesn't work as it needs copy constructor, so have to
    4117              :    * do this */
    4118       154738 :   std::vector<std::unique_ptr<Token>> dummy_vector;
    4119       154738 :   dummy_vector.reserve (1);
    4120       154738 :   dummy_vector.push_back (std::unique_ptr<Token> (clone_token_impl ()));
    4121       154738 :   return dummy_vector;
    4122              : }
    4123              : 
    4124              : Attribute
    4125            0 : MetaNameValueStr::to_attribute () const
    4126              : {
    4127            0 :   LiteralExpr lit_expr (str, Literal::LitType::STRING,
    4128            0 :                         PrimitiveCoreType::CORETYPE_UNKNOWN, {}, str_locus);
    4129              :   // FIXME: What location do we put here? Is the literal above supposed to have
    4130              :   // an empty location as well?
    4131              :   // Should MetaNameValueStr keep a location?
    4132            0 :   return Attribute (SimplePath::from_str (ident.as_string (), ident_locus),
    4133            0 :                     std::unique_ptr<AttrInputLiteral> (
    4134            0 :                       new AttrInputLiteral (std::move (lit_expr))));
    4135            0 : }
    4136              : 
    4137              : Attribute
    4138            0 : MetaItemPath::to_attribute () const
    4139              : {
    4140            0 :   return Attribute (path, nullptr);
    4141              : }
    4142              : 
    4143              : Attribute
    4144            8 : MetaItemSeq::to_attribute () const
    4145              : {
    4146            8 :   std::vector<std::unique_ptr<MetaItemInner>> new_seq;
    4147            8 :   new_seq.reserve (seq.size ());
    4148           16 :   for (const auto &e : seq)
    4149            8 :     new_seq.push_back (e->clone_meta_item_inner ());
    4150              : 
    4151            8 :   std::unique_ptr<AttrInputMetaItemContainer> new_seq_container (
    4152            8 :     new AttrInputMetaItemContainer (std::move (new_seq)));
    4153            8 :   return Attribute (path, std::move (new_seq_container));
    4154            8 : }
    4155              : 
    4156              : Attribute
    4157            0 : MetaWord::to_attribute () const
    4158              : {
    4159            0 :   return Attribute (SimplePath::from_str (ident.as_string (), ident_locus),
    4160            0 :                     nullptr);
    4161              : }
    4162              : 
    4163              : Attribute
    4164            0 : MetaListPaths::to_attribute () const
    4165              : {
    4166              :   /* probably one of the most annoying conversions - have to lose specificity by
    4167              :    * turning it into just AttrInputMetaItemContainer (i.e. paths-only nature is
    4168              :    * no longer known). If conversions back are required, might have to do a
    4169              :    * "check all are paths" pass or something. */
    4170              : 
    4171            0 :   std::vector<std::unique_ptr<MetaItemInner>> new_seq;
    4172            0 :   new_seq.reserve (paths.size ());
    4173            0 :   for (const auto &e : paths)
    4174            0 :     new_seq.push_back (std::unique_ptr<MetaItemPath> (new MetaItemPath (e)));
    4175              : 
    4176            0 :   std::unique_ptr<AttrInputMetaItemContainer> new_seq_container (
    4177            0 :     new AttrInputMetaItemContainer (std::move (new_seq)));
    4178            0 :   return Attribute (SimplePath::from_str (ident.as_string (), ident_locus),
    4179            0 :                     std::move (new_seq_container));
    4180            0 : }
    4181              : 
    4182              : Attribute
    4183            0 : MetaListNameValueStr::to_attribute () const
    4184              : {
    4185            0 :   std::vector<std::unique_ptr<MetaItemInner>> new_seq;
    4186            0 :   new_seq.reserve (strs.size ());
    4187            0 :   for (const auto &e : strs)
    4188            0 :     new_seq.push_back (
    4189            0 :       std::unique_ptr<MetaNameValueStr> (new MetaNameValueStr (e)));
    4190              : 
    4191            0 :   std::unique_ptr<AttrInputMetaItemContainer> new_seq_container (
    4192            0 :     new AttrInputMetaItemContainer (std::move (new_seq)));
    4193            0 :   return Attribute (SimplePath::from_str (ident.as_string (), ident_locus),
    4194            0 :                     std::move (new_seq_container));
    4195            0 : }
    4196              : 
    4197              : Attribute
    4198            1 : MetaItemPathExpr::to_attribute () const
    4199              : {
    4200            1 :   auto input = std::make_unique<AttrInputExpr> (expr->clone_expr ());
    4201            1 :   return Attribute (path, std::move (input));
    4202            1 : }
    4203              : 
    4204              : std::vector<Attribute>
    4205            9 : AttrInputMetaItemContainer::separate_cfg_attrs () const
    4206              : {
    4207            9 :   rust_assert (!items.empty ());
    4208              : 
    4209            9 :   if (items.size () == 1)
    4210            0 :     return {};
    4211              : 
    4212            9 :   std::vector<Attribute> attrs;
    4213            9 :   attrs.reserve (items.size () - 1);
    4214              : 
    4215           18 :   for (auto it = items.begin () + 1; it != items.end (); ++it)
    4216              :     {
    4217            9 :       auto &item = **it;
    4218              : 
    4219            9 :       Attribute attr = item.to_attribute ();
    4220            9 :       if (attr.is_empty ())
    4221              :         {
    4222              :           /* TODO should this be an error that causes us to chuck out
    4223              :            * everything? */
    4224            0 :           continue;
    4225              :         }
    4226            9 :       attrs.push_back (std::move (attr));
    4227            9 :     }
    4228              : 
    4229            9 :   attrs.shrink_to_fit ();
    4230            9 :   return attrs;
    4231            9 : }
    4232              : 
    4233              : bool
    4234         2147 : Attribute::check_cfg_predicate (const Session &session) const
    4235              : {
    4236         2147 :   auto string_path = path.as_string ();
    4237              :   /* assume that cfg predicate actually can exist, i.e. attribute has cfg or
    4238              :    * cfg_attr path */
    4239         2147 :   if (!has_attr_input ())
    4240              :     {
    4241            1 :       rust_error_at (path.get_locus (), "%qs is not followed by parentheses",
    4242              :                      string_path.c_str ());
    4243            1 :       return false;
    4244              :     }
    4245              : 
    4246              :   // assume that it has already been parsed
    4247         2146 :   if (!is_parsed_to_meta_item ())
    4248              :     return false;
    4249              : 
    4250         2146 :   auto &meta_item = static_cast<AttrInputMetaItemContainer &> (*attr_input);
    4251         2146 :   if (meta_item.get_items ().empty ())
    4252              :     {
    4253            3 :       rust_error_at (path.get_locus (), "malformed %<%s%> attribute input",
    4254              :                      string_path.c_str ());
    4255            3 :       return false;
    4256              :     }
    4257              : 
    4258         2143 :   if (string_path == Values::Attributes::CFG
    4259         2143 :       && meta_item.get_items ().size () != 1)
    4260              :     {
    4261            1 :       rust_error_at (path.get_locus (), "multiple %qs predicates are specified",
    4262            1 :                      path.as_string ().c_str ());
    4263            1 :       return false;
    4264              :     }
    4265         2142 :   return meta_item.get_items ().front ()->check_cfg_predicate (session);
    4266         2147 : }
    4267              : 
    4268              : std::vector<Attribute>
    4269            9 : Attribute::separate_cfg_attrs () const
    4270              : {
    4271           18 :   if (!has_attr_input () || path.as_string () != Values::Attributes::CFG_ATTR)
    4272            0 :     return {};
    4273              : 
    4274              :   // assume that it has already been parsed
    4275            9 :   if (!is_parsed_to_meta_item ())
    4276            0 :     return {};
    4277              : 
    4278            9 :   return attr_input->separate_cfg_attrs ();
    4279              : }
    4280              : 
    4281              : bool
    4282         7419 : Attribute::is_parsed_to_meta_item () const
    4283              : {
    4284         7419 :   return has_attr_input () && attr_input->is_meta_item ();
    4285              : }
    4286              : 
    4287              : void
    4288        37511 : BlockExpr::normalize_tail_expr ()
    4289              : {
    4290        37511 :   if (!expr)
    4291              :     {
    4292              :       // HACK: try to turn the last statement into a tail expression
    4293        21323 :       if (!statements.empty () && statements.back ()->is_expr ())
    4294              :         {
    4295              :           // Watch out: This reference become invalid when the vector is
    4296              :           // modified.
    4297        14316 :           auto &stmt = static_cast<ExprStmt &> (*statements.back ());
    4298              : 
    4299        14316 :           if (!stmt.is_semicolon_followed ())
    4300              :             {
    4301           59 :               expr = stmt.take_expr ();
    4302           59 :               statements.pop_back ();
    4303              :             }
    4304              :         }
    4305              :     }
    4306        37511 : }
    4307              : 
    4308              : /* Visitor implementations - these are short but inlining can't happen anyway
    4309              :  * due to virtual functions and I didn't want to make the ast header includes
    4310              :  * any longer than they already are. */
    4311              : 
    4312              : void
    4313      1452647 : Token::accept_vis (ASTVisitor &vis)
    4314              : {
    4315      1452647 :   vis.visit (*this);
    4316      1452647 : }
    4317              : 
    4318              : void
    4319       279103 : DelimTokenTree::accept_vis (ASTVisitor &vis)
    4320              : {
    4321       279103 :   vis.visit (*this);
    4322       279103 : }
    4323              : 
    4324              : void
    4325       640446 : IdentifierExpr::accept_vis (ASTVisitor &vis)
    4326              : {
    4327       640446 :   vis.visit (*this);
    4328       640445 : }
    4329              : 
    4330              : void
    4331          240 : Lifetime::accept_vis (ASTVisitor &vis)
    4332              : {
    4333          240 :   vis.visit (*this);
    4334          240 : }
    4335              : 
    4336              : void
    4337         4923 : LifetimeParam::accept_vis (ASTVisitor &vis)
    4338              : {
    4339         4923 :   vis.visit (*this);
    4340         4923 : }
    4341              : 
    4342              : void
    4343      3103821 : LiteralExpr::accept_vis (ASTVisitor &vis)
    4344              : {
    4345      3103821 :   vis.visit (*this);
    4346      3103821 : }
    4347              : 
    4348              : void
    4349       254799 : AttrInputLiteral::accept_vis (ASTVisitor &vis)
    4350              : {
    4351       254799 :   vis.visit (*this);
    4352       254799 : }
    4353              : 
    4354              : void
    4355            0 : MetaItemLitExpr::accept_vis (ASTVisitor &vis)
    4356              : {
    4357            0 :   vis.visit (*this);
    4358            0 : }
    4359              : 
    4360              : void
    4361            2 : MetaItemPathExpr::accept_vis (ASTVisitor &vis)
    4362              : {
    4363            2 :   vis.visit (*this);
    4364            2 : }
    4365              : 
    4366              : void
    4367        52668 : BorrowExpr::accept_vis (ASTVisitor &vis)
    4368              : {
    4369        52668 :   vis.visit (*this);
    4370        52668 : }
    4371              : 
    4372              : void
    4373        95781 : DereferenceExpr::accept_vis (ASTVisitor &vis)
    4374              : {
    4375        95781 :   vis.visit (*this);
    4376        95781 : }
    4377              : 
    4378              : void
    4379           13 : ErrorPropagationExpr::accept_vis (ASTVisitor &vis)
    4380              : {
    4381           13 :   vis.visit (*this);
    4382           13 : }
    4383              : 
    4384              : void
    4385        16438 : NegationExpr::accept_vis (ASTVisitor &vis)
    4386              : {
    4387        16438 :   vis.visit (*this);
    4388        16438 : }
    4389              : 
    4390              : void
    4391      2703191 : ArithmeticOrLogicalExpr::accept_vis (ASTVisitor &vis)
    4392              : {
    4393      2703191 :   vis.visit (*this);
    4394      2703191 : }
    4395              : 
    4396              : void
    4397        82139 : ComparisonExpr::accept_vis (ASTVisitor &vis)
    4398              : {
    4399        82139 :   vis.visit (*this);
    4400        82139 : }
    4401              : 
    4402              : void
    4403         8217 : LazyBooleanExpr::accept_vis (ASTVisitor &vis)
    4404              : {
    4405         8217 :   vis.visit (*this);
    4406         8217 : }
    4407              : 
    4408              : void
    4409       144999 : TypeCastExpr::accept_vis (ASTVisitor &vis)
    4410              : {
    4411       144999 :   vis.visit (*this);
    4412       144999 : }
    4413              : 
    4414              : void
    4415        56195 : AssignmentExpr::accept_vis (ASTVisitor &vis)
    4416              : {
    4417        56195 :   vis.visit (*this);
    4418        56195 : }
    4419              : 
    4420              : void
    4421        17280 : CompoundAssignmentExpr::accept_vis (ASTVisitor &vis)
    4422              : {
    4423        17280 :   vis.visit (*this);
    4424        17280 : }
    4425              : 
    4426              : void
    4427         6304 : ArrayElemsValues::accept_vis (ASTVisitor &vis)
    4428              : {
    4429         6304 :   vis.visit (*this);
    4430         6304 : }
    4431              : 
    4432              : void
    4433         2552 : ArrayElemsCopied::accept_vis (ASTVisitor &vis)
    4434              : {
    4435         2552 :   vis.visit (*this);
    4436         2552 : }
    4437              : 
    4438              : void
    4439         8871 : ArrayExpr::accept_vis (ASTVisitor &vis)
    4440              : {
    4441         8871 :   vis.visit (*this);
    4442         8871 : }
    4443              : 
    4444              : void
    4445         6482 : ArrayIndexExpr::accept_vis (ASTVisitor &vis)
    4446              : {
    4447         6482 :   vis.visit (*this);
    4448         6482 : }
    4449              : 
    4450              : void
    4451        12658 : TupleExpr::accept_vis (ASTVisitor &vis)
    4452              : {
    4453        12658 :   vis.visit (*this);
    4454        12658 : }
    4455              : 
    4456              : void
    4457        21387 : TupleIndexExpr::accept_vis (ASTVisitor &vis)
    4458              : {
    4459        21387 :   vis.visit (*this);
    4460        21387 : }
    4461              : 
    4462              : void
    4463         1725 : StructExprStruct::accept_vis (ASTVisitor &vis)
    4464              : {
    4465         1725 :   vis.visit (*this);
    4466         1725 : }
    4467              : 
    4468              : void
    4469         4338 : StructExprFieldIdentifier::accept_vis (ASTVisitor &vis)
    4470              : {
    4471         4338 :   vis.visit (*this);
    4472         4338 : }
    4473              : 
    4474              : void
    4475        45987 : StructExprFieldIdentifierValue::accept_vis (ASTVisitor &vis)
    4476              : {
    4477        45987 :   vis.visit (*this);
    4478        45987 : }
    4479              : 
    4480              : void
    4481          924 : StructExprFieldIndexValue::accept_vis (ASTVisitor &vis)
    4482              : {
    4483          924 :   vis.visit (*this);
    4484          924 : }
    4485              : 
    4486              : void
    4487        29610 : StructExprStructFields::accept_vis (ASTVisitor &vis)
    4488              : {
    4489        29610 :   vis.visit (*this);
    4490        29610 : }
    4491              : 
    4492              : void
    4493            0 : StructExprStructBase::accept_vis (ASTVisitor &vis)
    4494              : {
    4495            0 :   vis.visit (*this);
    4496            0 : }
    4497              : 
    4498              : void
    4499       307529 : CallExpr::accept_vis (ASTVisitor &vis)
    4500              : {
    4501       307529 :   vis.visit (*this);
    4502       307529 : }
    4503              : 
    4504              : void
    4505        71164 : MethodCallExpr::accept_vis (ASTVisitor &vis)
    4506              : {
    4507        71164 :   vis.visit (*this);
    4508        71164 : }
    4509              : 
    4510              : void
    4511       115865 : FieldAccessExpr::accept_vis (ASTVisitor &vis)
    4512              : {
    4513       115865 :   vis.visit (*this);
    4514       115865 : }
    4515              : 
    4516              : void
    4517          788 : ClosureExprInner::accept_vis (ASTVisitor &vis)
    4518              : {
    4519          788 :   vis.visit (*this);
    4520          788 : }
    4521              : 
    4522              : void
    4523       416237 : BlockExpr::accept_vis (ASTVisitor &vis)
    4524              : {
    4525       416237 :   vis.visit (*this);
    4526       416236 : }
    4527              : 
    4528              : void
    4529          685 : AnonConst::accept_vis (ASTVisitor &vis)
    4530              : {
    4531          685 :   vis.visit (*this);
    4532          685 : }
    4533              : 
    4534              : void
    4535          272 : ConstBlock::accept_vis (ASTVisitor &vis)
    4536              : {
    4537          272 :   vis.visit (*this);
    4538          272 : }
    4539              : 
    4540              : void
    4541          631 : ClosureExprInnerTyped::accept_vis (ASTVisitor &vis)
    4542              : {
    4543          631 :   vis.visit (*this);
    4544          631 : }
    4545              : 
    4546              : void
    4547          444 : ContinueExpr::accept_vis (ASTVisitor &vis)
    4548              : {
    4549          444 :   vis.visit (*this);
    4550          444 : }
    4551              : 
    4552              : void
    4553         2163 : BreakExpr::accept_vis (ASTVisitor &vis)
    4554              : {
    4555         2163 :   vis.visit (*this);
    4556         2162 : }
    4557              : 
    4558              : void
    4559         1659 : RangeFromToExpr::accept_vis (ASTVisitor &vis)
    4560              : {
    4561         1659 :   vis.visit (*this);
    4562         1659 : }
    4563              : 
    4564              : void
    4565          147 : RangeFromExpr::accept_vis (ASTVisitor &vis)
    4566              : {
    4567          147 :   vis.visit (*this);
    4568          147 : }
    4569              : 
    4570              : void
    4571          147 : RangeToExpr::accept_vis (ASTVisitor &vis)
    4572              : {
    4573          147 :   vis.visit (*this);
    4574          147 : }
    4575              : 
    4576              : void
    4577            0 : RangeFullExpr::accept_vis (ASTVisitor &vis)
    4578              : {
    4579            0 :   vis.visit (*this);
    4580            0 : }
    4581              : 
    4582              : void
    4583          147 : RangeFromToInclExpr::accept_vis (ASTVisitor &vis)
    4584              : {
    4585          147 :   vis.visit (*this);
    4586          147 : }
    4587              : 
    4588              : void
    4589            0 : RangeToInclExpr::accept_vis (ASTVisitor &vis)
    4590              : {
    4591            0 :   vis.visit (*this);
    4592            0 : }
    4593              : 
    4594              : void
    4595        12388 : ReturnExpr::accept_vis (ASTVisitor &vis)
    4596              : {
    4597        12388 :   vis.visit (*this);
    4598        12388 : }
    4599              : 
    4600              : void
    4601           13 : TryExpr::accept_vis (ASTVisitor &vis)
    4602              : {
    4603           13 :   vis.visit (*this);
    4604           13 : }
    4605              : 
    4606              : void
    4607        82556 : UnsafeBlockExpr::accept_vis (ASTVisitor &vis)
    4608              : {
    4609        82556 :   vis.visit (*this);
    4610        82556 : }
    4611              : 
    4612              : void
    4613         2659 : LoopExpr::accept_vis (ASTVisitor &vis)
    4614              : {
    4615         2659 :   vis.visit (*this);
    4616         2659 : }
    4617              : 
    4618              : void
    4619         2153 : WhileLoopExpr::accept_vis (ASTVisitor &vis)
    4620              : {
    4621         2153 :   vis.visit (*this);
    4622         2153 : }
    4623              : 
    4624              : void
    4625           24 : WhileLetLoopExpr::accept_vis (ASTVisitor &vis)
    4626              : {
    4627           24 :   vis.visit (*this);
    4628           24 : }
    4629              : 
    4630              : void
    4631          393 : ForLoopExpr::accept_vis (ASTVisitor &vis)
    4632              : {
    4633          393 :   vis.visit (*this);
    4634          393 : }
    4635              : 
    4636              : void
    4637        28910 : IfExpr::accept_vis (ASTVisitor &vis)
    4638              : {
    4639        28910 :   vis.visit (*this);
    4640        28910 : }
    4641              : 
    4642              : void
    4643        31073 : IfExprConseqElse::accept_vis (ASTVisitor &vis)
    4644              : {
    4645        31073 :   vis.visit (*this);
    4646        31073 : }
    4647              : 
    4648              : void
    4649          395 : IfLetExpr::accept_vis (ASTVisitor &vis)
    4650              : {
    4651          395 :   vis.visit (*this);
    4652          395 : }
    4653              : 
    4654              : void
    4655          257 : IfLetExprConseqElse::accept_vis (ASTVisitor &vis)
    4656              : {
    4657          257 :   vis.visit (*this);
    4658          257 : }
    4659              : 
    4660              : void
    4661        25404 : MatchExpr::accept_vis (ASTVisitor &vis)
    4662              : {
    4663        25404 :   vis.visit (*this);
    4664        25404 : }
    4665              : 
    4666              : void
    4667            0 : AwaitExpr::accept_vis (ASTVisitor &vis)
    4668              : {
    4669            0 :   vis.visit (*this);
    4670            0 : }
    4671              : 
    4672              : void
    4673            0 : AsyncBlockExpr::accept_vis (ASTVisitor &vis)
    4674              : {
    4675            0 :   vis.visit (*this);
    4676            0 : }
    4677              : 
    4678              : void
    4679          426 : InlineAsm::accept_vis (ASTVisitor &vis)
    4680              : {
    4681          426 :   vis.visit (*this);
    4682          426 : }
    4683              : 
    4684              : void
    4685           34 : LlvmInlineAsm::accept_vis (ASTVisitor &vis)
    4686              : {
    4687           34 :   vis.visit (*this);
    4688           34 : }
    4689              : 
    4690              : void
    4691       105642 : TypeParam::accept_vis (ASTVisitor &vis)
    4692              : {
    4693       105642 :   vis.visit (*this);
    4694       105642 : }
    4695              : 
    4696              : void
    4697           38 : LifetimeWhereClauseItem::accept_vis (ASTVisitor &vis)
    4698              : {
    4699           38 :   vis.visit (*this);
    4700           38 : }
    4701              : 
    4702              : void
    4703         7234 : TypeBoundWhereClauseItem::accept_vis (ASTVisitor &vis)
    4704              : {
    4705         7234 :   vis.visit (*this);
    4706         7234 : }
    4707              : 
    4708              : void
    4709        30259 : Module::accept_vis (ASTVisitor &vis)
    4710              : {
    4711        30259 :   vis.visit (*this);
    4712        30259 : }
    4713              : 
    4714              : void
    4715          537 : ExternCrate::accept_vis (ASTVisitor &vis)
    4716              : {
    4717          537 :   vis.visit (*this);
    4718          537 : }
    4719              : 
    4720              : void
    4721          147 : UseTreeGlob::accept_vis (ASTVisitor &vis)
    4722              : {
    4723          147 :   vis.visit (*this);
    4724          147 : }
    4725              : 
    4726              : void
    4727         2146 : UseTreeList::accept_vis (ASTVisitor &vis)
    4728              : {
    4729         2146 :   vis.visit (*this);
    4730         2146 : }
    4731              : 
    4732              : void
    4733         6810 : UseTreeRebind::accept_vis (ASTVisitor &vis)
    4734              : {
    4735         6810 :   vis.visit (*this);
    4736         6810 : }
    4737              : 
    4738              : void
    4739        16649 : UseDeclaration::accept_vis (ASTVisitor &vis)
    4740              : {
    4741        16649 :   vis.visit (*this);
    4742        16649 : }
    4743              : 
    4744              : void
    4745       445335 : Function::accept_vis (ASTVisitor &vis)
    4746              : {
    4747       445335 :   vis.visit (*this);
    4748       445334 : }
    4749              : 
    4750              : void
    4751        31966 : TypeAlias::accept_vis (ASTVisitor &vis)
    4752              : {
    4753        31966 :   vis.visit (*this);
    4754        31966 : }
    4755              : 
    4756              : void
    4757        35726 : StructStruct::accept_vis (ASTVisitor &vis)
    4758              : {
    4759        35726 :   vis.visit (*this);
    4760        35726 : }
    4761              : 
    4762              : void
    4763        21536 : TupleStruct::accept_vis (ASTVisitor &vis)
    4764              : {
    4765        21536 :   vis.visit (*this);
    4766        21536 : }
    4767              : 
    4768              : void
    4769        10913 : EnumItem::accept_vis (ASTVisitor &vis)
    4770              : {
    4771        10913 :   vis.visit (*this);
    4772        10913 : }
    4773              : 
    4774              : void
    4775        11108 : EnumItemTuple::accept_vis (ASTVisitor &vis)
    4776              : {
    4777        11108 :   vis.visit (*this);
    4778        11108 : }
    4779              : 
    4780              : void
    4781         2215 : EnumItemStruct::accept_vis (ASTVisitor &vis)
    4782              : {
    4783         2215 :   vis.visit (*this);
    4784         2215 : }
    4785              : 
    4786              : void
    4787         6972 : EnumItemDiscriminant::accept_vis (ASTVisitor &vis)
    4788              : {
    4789         6972 :   vis.visit (*this);
    4790         6972 : }
    4791              : 
    4792              : void
    4793        12733 : Enum::accept_vis (ASTVisitor &vis)
    4794              : {
    4795        12733 :   vis.visit (*this);
    4796        12733 : }
    4797              : 
    4798              : void
    4799         2348 : Union::accept_vis (ASTVisitor &vis)
    4800              : {
    4801         2348 :   vis.visit (*this);
    4802         2348 : }
    4803              : 
    4804              : void
    4805        12591 : ConstantItem::accept_vis (ASTVisitor &vis)
    4806              : {
    4807        12591 :   vis.visit (*this);
    4808        12591 : }
    4809              : 
    4810              : void
    4811         1299 : StaticItem::accept_vis (ASTVisitor &vis)
    4812              : {
    4813         1299 :   vis.visit (*this);
    4814         1299 : }
    4815              : 
    4816              : void
    4817        19625 : TraitItemType::accept_vis (ASTVisitor &vis)
    4818              : {
    4819        19625 :   vis.visit (*this);
    4820        19625 : }
    4821              : 
    4822              : void
    4823        89847 : Trait::accept_vis (ASTVisitor &vis)
    4824              : {
    4825        89847 :   vis.visit (*this);
    4826        89847 : }
    4827              : 
    4828              : void
    4829        21206 : InherentImpl::accept_vis (ASTVisitor &vis)
    4830              : {
    4831        21206 :   vis.visit (*this);
    4832        21206 : }
    4833              : 
    4834              : void
    4835       102737 : TraitImpl::accept_vis (ASTVisitor &vis)
    4836              : {
    4837       102737 :   vis.visit (*this);
    4838       102737 : }
    4839              : 
    4840              : void
    4841           19 : ExternalTypeItem::accept_vis (ASTVisitor &vis)
    4842              : {
    4843           19 :   vis.visit (*this);
    4844           19 : }
    4845              : 
    4846              : void
    4847           20 : ExternalStaticItem::accept_vis (ASTVisitor &vis)
    4848              : {
    4849           20 :   vis.visit (*this);
    4850           20 : }
    4851              : 
    4852              : void
    4853        36400 : ExternBlock::accept_vis (ASTVisitor &vis)
    4854              : {
    4855        36400 :   vis.visit (*this);
    4856        36400 : }
    4857              : 
    4858              : void
    4859        19359 : MacroMatchFragment::accept_vis (ASTVisitor &vis)
    4860              : {
    4861        19359 :   vis.visit (*this);
    4862        19359 : }
    4863              : 
    4864              : void
    4865         9057 : MacroMatchRepetition::accept_vis (ASTVisitor &vis)
    4866              : {
    4867         9057 :   vis.visit (*this);
    4868         9057 : }
    4869              : 
    4870              : void
    4871          849 : MacroMatcher::accept_vis (ASTVisitor &vis)
    4872              : {
    4873          849 :   vis.visit (*this);
    4874          849 : }
    4875              : 
    4876              : void
    4877        29528 : MacroRulesDefinition::accept_vis (ASTVisitor &vis)
    4878              : {
    4879        29528 :   vis.visit (*this);
    4880        29528 : }
    4881              : 
    4882              : void
    4883        18039 : MacroInvocation::accept_vis (ASTVisitor &vis)
    4884              : {
    4885        18039 :   vis.visit (*this);
    4886        18039 : }
    4887              : 
    4888              : void
    4889         1384 : EmptyStmt::accept_vis (ASTVisitor &vis)
    4890              : {
    4891         1384 :   vis.visit (*this);
    4892         1384 : }
    4893              : 
    4894              : void
    4895       308794 : LetStmt::accept_vis (ASTVisitor &vis)
    4896              : {
    4897       308794 :   vis.visit (*this);
    4898       308794 : }
    4899              : 
    4900              : void
    4901       265665 : ExprStmt::accept_vis (ASTVisitor &vis)
    4902              : {
    4903       265665 :   vis.visit (*this);
    4904       265664 : }
    4905              : 
    4906              : void
    4907        44070 : TraitBound::accept_vis (ASTVisitor &vis)
    4908              : {
    4909        44070 :   vis.visit (*this);
    4910        44070 : }
    4911              : 
    4912              : void
    4913            0 : ImplTraitType::accept_vis (ASTVisitor &vis)
    4914              : {
    4915            0 :   vis.visit (*this);
    4916            0 : }
    4917              : 
    4918              : void
    4919          266 : TraitObjectType::accept_vis (ASTVisitor &vis)
    4920              : {
    4921          266 :   vis.visit (*this);
    4922          266 : }
    4923              : 
    4924              : void
    4925          161 : ParenthesisedType::accept_vis (ASTVisitor &vis)
    4926              : {
    4927          161 :   vis.visit (*this);
    4928          161 : }
    4929              : 
    4930              : void
    4931         2144 : ImplTraitTypeOneBound::accept_vis (ASTVisitor &vis)
    4932              : {
    4933         2144 :   vis.visit (*this);
    4934         2144 : }
    4935              : 
    4936              : void
    4937         3425 : TraitObjectTypeOneBound::accept_vis (ASTVisitor &vis)
    4938              : {
    4939         3425 :   vis.visit (*this);
    4940         3425 : }
    4941              : 
    4942              : void
    4943         9603 : TupleType::accept_vis (ASTVisitor &vis)
    4944              : {
    4945         9603 :   vis.visit (*this);
    4946         9603 : }
    4947              : 
    4948              : void
    4949         3947 : NeverType::accept_vis (ASTVisitor &vis)
    4950              : {
    4951         3947 :   vis.visit (*this);
    4952         3947 : }
    4953              : 
    4954              : void
    4955       168736 : RawPointerType::accept_vis (ASTVisitor &vis)
    4956              : {
    4957       168736 :   vis.visit (*this);
    4958       168736 : }
    4959              : 
    4960              : void
    4961       119367 : ReferenceType::accept_vis (ASTVisitor &vis)
    4962              : {
    4963       119367 :   vis.visit (*this);
    4964       119367 : }
    4965              : 
    4966              : void
    4967        17515 : ArrayType::accept_vis (ASTVisitor &vis)
    4968              : {
    4969        17515 :   vis.visit (*this);
    4970        17515 : }
    4971              : 
    4972              : void
    4973        19317 : SliceType::accept_vis (ASTVisitor &vis)
    4974              : {
    4975        19317 :   vis.visit (*this);
    4976        19317 : }
    4977              : 
    4978              : void
    4979         6095 : InferredType::accept_vis (ASTVisitor &vis)
    4980              : {
    4981         6095 :   vis.visit (*this);
    4982         6095 : }
    4983              : 
    4984              : void
    4985         1376 : BareFunctionType::accept_vis (ASTVisitor &vis)
    4986              : {
    4987         1376 :   vis.visit (*this);
    4988         1376 : }
    4989              : 
    4990              : void
    4991          255 : MetaItemSeq::accept_vis (ASTVisitor &vis)
    4992              : {
    4993          255 :   vis.visit (*this);
    4994          255 : }
    4995              : 
    4996              : void
    4997          626 : MetaItemPath::accept_vis (ASTVisitor &vis)
    4998              : {
    4999          626 :   vis.visit (*this);
    5000          626 : }
    5001              : 
    5002              : void
    5003            0 : MetaListPaths::accept_vis (ASTVisitor &vis)
    5004              : {
    5005            0 :   vis.visit (*this);
    5006            0 : }
    5007              : 
    5008              : void
    5009         6686 : MetaNameValueStr::accept_vis (ASTVisitor &vis)
    5010              : {
    5011         6686 :   vis.visit (*this);
    5012         6686 : }
    5013              : 
    5014              : void
    5015            0 : MetaListNameValueStr::accept_vis (ASTVisitor &vis)
    5016              : {
    5017            0 :   vis.visit (*this);
    5018            0 : }
    5019              : 
    5020              : void
    5021         8068 : AttrInputMetaItemContainer::accept_vis (ASTVisitor &vis)
    5022              : {
    5023         8068 :   vis.visit (*this);
    5024         8068 : }
    5025              : 
    5026              : void
    5027         1084 : MetaWord::accept_vis (ASTVisitor &vis)
    5028              : {
    5029         1084 :   vis.visit (*this);
    5030         1084 : }
    5031              : 
    5032              : void
    5033            0 : FormatArgs::accept_vis (ASTVisitor &vis)
    5034              : {
    5035            0 :   vis.visit (*this);
    5036            0 : }
    5037              : 
    5038              : void
    5039          215 : OffsetOf::accept_vis (ASTVisitor &vis)
    5040              : {
    5041          215 :   vis.visit (*this);
    5042          215 : }
    5043              : 
    5044              : std::string
    5045            0 : FormatArgs::as_string () const
    5046              : {
    5047              :   // FIXME(Arthur): Improve
    5048            0 :   return "FormatArgs";
    5049              : }
    5050              : 
    5051              : std::string
    5052            0 : OffsetOf::as_string () const
    5053              : {
    5054            0 :   return "OffsetOf(" + type->as_string () + ", " + field.as_string () + ")";
    5055              : }
    5056              : 
    5057              : location_t
    5058            3 : FormatArgs::get_locus () const
    5059              : {
    5060            3 :   return loc;
    5061              : }
    5062              : 
    5063              : bool
    5064            0 : FormatArgs::is_expr_without_block () const
    5065              : {
    5066            0 :   return false;
    5067              : }
    5068              : 
    5069              : void
    5070            0 : FormatArgs::mark_for_strip ()
    5071              : {
    5072            0 :   marked_for_strip = true;
    5073            0 : }
    5074              : 
    5075              : bool
    5076            0 : FormatArgs::is_marked_for_strip () const
    5077              : {
    5078            0 :   return marked_for_strip;
    5079              : }
    5080              : 
    5081              : std::vector<Attribute> &
    5082            0 : FormatArgs::get_outer_attrs ()
    5083              : {
    5084            0 :   rust_unreachable ();
    5085              : }
    5086              : 
    5087              : void
    5088            0 : FormatArgs::set_outer_attrs (std::vector<Attribute>)
    5089              : {
    5090            0 :   rust_unreachable ();
    5091              : }
    5092              : 
    5093              : Expr *
    5094            0 : FormatArgs::clone_expr_impl () const
    5095              : {
    5096            0 :   std::cerr << "[ARTHUR] cloning FormatArgs! " << std::endl;
    5097              : 
    5098            0 :   return new FormatArgs (*this);
    5099              : }
    5100              : 
    5101              : std::vector<Attribute> &
    5102            0 : OffsetOf::get_outer_attrs ()
    5103              : {
    5104            0 :   rust_unreachable ();
    5105              : }
    5106              : 
    5107              : void
    5108            0 : OffsetOf::set_outer_attrs (std::vector<Attribute>)
    5109              : {
    5110            0 :   rust_unreachable ();
    5111              : }
    5112              : 
    5113              : Expr *
    5114           96 : OffsetOf::clone_expr_impl () const
    5115              : {
    5116           96 :   return new OffsetOf (*this);
    5117              : }
    5118              : 
    5119              : } // namespace AST
    5120              : 
    5121              : std::ostream &
    5122            0 : operator<< (std::ostream &os, Identifier const &i)
    5123              : {
    5124            0 :   return os << i.as_string ();
    5125              : }
    5126              : 
    5127              : } // 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.