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