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