LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-pattern.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.8 % 449 403
Test Date: 2026-02-28 14:20:25 Functions: 81.2 % 133 108
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #ifndef RUST_AST_PATTERN_H
      20              : #define RUST_AST_PATTERN_H
      21              : 
      22              : #include "rust-ast.h"
      23              : #include "rust-path.h"
      24              : 
      25              : namespace Rust {
      26              : namespace AST {
      27              : // Literal pattern AST node (comparing to a literal)
      28              : class LiteralPattern : public Pattern
      29              : {
      30              :   Literal lit;
      31              :   location_t locus;
      32              :   NodeId node_id;
      33              :   bool has_minus;
      34              : 
      35              : public:
      36              :   std::string as_string () const override;
      37              : 
      38              :   // Constructor for a literal pattern
      39              :   LiteralPattern (Literal lit, location_t locus)
      40              :     : lit (std::move (lit)), locus (locus),
      41              :       node_id (Analysis::Mappings::get ().get_next_node_id ()),
      42              :       has_minus (false)
      43              :   {}
      44              : 
      45              :   LiteralPattern (Literal lit, location_t locus, bool has_minus)
      46              :     : lit (std::move (lit)), locus (locus),
      47              :       node_id (Analysis::Mappings::get ().get_next_node_id ()),
      48              :       has_minus (has_minus)
      49              :   {}
      50              : 
      51           26 :   LiteralPattern (std::string val, Literal::LitType type, location_t locus,
      52              :                   PrimitiveCoreType type_hint)
      53           26 :     : lit (Literal (std::move (val), type, type_hint)), locus (locus),
      54           26 :       node_id (Analysis::Mappings::get ().get_next_node_id ()),
      55           26 :       has_minus (false)
      56           26 :   {}
      57              : 
      58          435 :   LiteralPattern (std::string val, Literal::LitType type, location_t locus,
      59              :                   PrimitiveCoreType type_hint, bool has_minus)
      60          435 :     : lit (Literal (std::move (val), type, type_hint)), locus (locus),
      61          435 :       node_id (Analysis::Mappings::get ().get_next_node_id ()),
      62          435 :       has_minus (has_minus)
      63          435 :   {}
      64              : 
      65          902 :   location_t get_locus () const override final { return locus; }
      66              : 
      67          436 :   bool get_has_minus () const { return has_minus; }
      68              : 
      69              :   void accept_vis (ASTVisitor &vis) override;
      70              : 
      71         1320 :   NodeId get_node_id () const override { return node_id; }
      72              : 
      73          466 :   Literal &get_literal () { return lit; }
      74              : 
      75              :   const Literal &get_literal () const { return lit; }
      76              : 
      77            0 :   Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Literal; }
      78              : 
      79              : protected:
      80              :   /* Use covariance to implement clone function as returning this object rather
      81              :    * than base */
      82          511 :   virtual LiteralPattern *clone_pattern_impl () const override
      83              :   {
      84          511 :     return new LiteralPattern (*this);
      85              :   }
      86              : };
      87              : 
      88              : // Identifier pattern AST node (bind value matched to a variable)
      89              : class IdentifierPattern : public Pattern
      90              : {
      91              :   Identifier variable_ident;
      92              :   bool is_ref;
      93              :   bool is_mut;
      94              : 
      95              :   // bool has_pattern;
      96              :   std::unique_ptr<Pattern> subpattern;
      97              :   location_t locus;
      98              :   NodeId node_id;
      99              : 
     100              : public:
     101              :   std::string as_string () const override;
     102              : 
     103              :   // Returns whether the IdentifierPattern has a pattern to bind.
     104       502111 :   bool has_subpattern () const { return subpattern != nullptr; }
     105              : 
     106              :   // Constructor
     107        24706 :   IdentifierPattern (Identifier ident, location_t locus, bool is_ref = false,
     108              :                      bool is_mut = false,
     109              :                      std::unique_ptr<Pattern> subpattern = nullptr)
     110        49412 :     : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref),
     111        24706 :       is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus),
     112        24706 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
     113        24706 :   {}
     114              : 
     115              :   IdentifierPattern (NodeId node_id, Identifier ident, location_t locus,
     116              :                      bool is_ref = false, bool is_mut = false,
     117              :                      std::unique_ptr<Pattern> subpattern = nullptr)
     118              :     : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref),
     119              :       is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus),
     120              :       node_id (node_id)
     121              :   {}
     122              : 
     123              :   // Copy constructor with clone
     124        38362 :   IdentifierPattern (IdentifierPattern const &other)
     125        76724 :     : variable_ident (other.variable_ident), is_ref (other.is_ref),
     126        38362 :       is_mut (other.is_mut), locus (other.locus), node_id (other.node_id)
     127              :   {
     128              :     // fix to get prevent null pointer dereference
     129        38362 :     if (other.subpattern != nullptr)
     130           18 :       subpattern = other.subpattern->clone_pattern ();
     131        38362 :   }
     132              : 
     133              :   // Overload assignment operator to use clone
     134              :   IdentifierPattern &operator= (IdentifierPattern const &other)
     135              :   {
     136              :     variable_ident = other.variable_ident;
     137              :     is_ref = other.is_ref;
     138              :     is_mut = other.is_mut;
     139              :     locus = other.locus;
     140              :     node_id = other.node_id;
     141              : 
     142              :     // fix to prevent null pointer dereference
     143              :     if (other.subpattern != nullptr)
     144              :       subpattern = other.subpattern->clone_pattern ();
     145              :     else
     146              :       subpattern = nullptr;
     147              : 
     148              :     return *this;
     149              :   }
     150              : 
     151              :   // default move semantics
     152              :   IdentifierPattern (IdentifierPattern &&other) = default;
     153              :   IdentifierPattern &operator= (IdentifierPattern &&other) = default;
     154              : 
     155        66875 :   location_t get_locus () const override final { return locus; }
     156              : 
     157              :   void accept_vis (ASTVisitor &vis) override;
     158              : 
     159          320 :   Pattern &get_subpattern ()
     160              :   {
     161          320 :     rust_assert (has_subpattern ());
     162          320 :     return *subpattern;
     163              :   }
     164              : 
     165           54 :   std::unique_ptr<Pattern> &get_subpattern_ptr ()
     166              :   {
     167           54 :     rust_assert (has_subpattern ());
     168           54 :     return subpattern;
     169              :   }
     170              : 
     171        50211 :   Identifier get_ident () const { return variable_ident; }
     172              : 
     173        47587 :   bool get_is_mut () const { return is_mut; }
     174        47587 :   bool get_is_ref () const { return is_ref; }
     175              : 
     176       102276 :   NodeId get_node_id () const override { return node_id; }
     177              : 
     178         5246 :   Pattern::Kind get_pattern_kind () override
     179              :   {
     180         5246 :     return Pattern::Kind::Identifier;
     181              :   }
     182              : 
     183              : protected:
     184              :   /* Use covariance to implement clone function as returning this object rather
     185              :    * than base */
     186        38362 :   IdentifierPattern *clone_pattern_impl () const override
     187              :   {
     188        38362 :     return new IdentifierPattern (*this);
     189              :   }
     190              : };
     191              : 
     192              : // AST node for using the '_' wildcard "match any value" pattern
     193         1276 : class WildcardPattern : public Pattern
     194              : {
     195              :   location_t locus;
     196              :   NodeId node_id;
     197              : 
     198              : public:
     199            0 :   std::string as_string () const override { return std::string (1, '_'); }
     200              : 
     201         1185 :   WildcardPattern (location_t locus)
     202         1185 :     : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
     203         1185 :   {}
     204              : 
     205         2235 :   location_t get_locus () const override final { return locus; }
     206              : 
     207              :   void accept_vis (ASTVisitor &vis) override;
     208              : 
     209         3889 :   NodeId get_node_id () const override { return node_id; }
     210              : 
     211          132 :   Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Wildcard; }
     212              : 
     213              : protected:
     214              :   /* Use covariance to implement clone function as returning this object rather
     215              :    * than base */
     216         1276 :   WildcardPattern *clone_pattern_impl () const override
     217              :   {
     218         1276 :     return new WildcardPattern (*this);
     219              :   }
     220              : };
     221              : 
     222            0 : class RestPattern : public Pattern
     223              : {
     224              :   location_t locus;
     225              :   NodeId node_id;
     226              : 
     227              : public:
     228            0 :   std::string as_string () const override { return ".."; }
     229              : 
     230            0 :   RestPattern (location_t locus)
     231            0 :     : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
     232            0 :   {}
     233              : 
     234            0 :   location_t get_locus () const override final { return locus; }
     235              : 
     236              :   void accept_vis (ASTVisitor &vis) override;
     237              : 
     238            0 :   NodeId get_node_id () const override final { return node_id; }
     239              : 
     240            0 :   Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Rest; }
     241              : 
     242              : protected:
     243            0 :   RestPattern *clone_pattern_impl () const override
     244              :   {
     245            0 :     return new RestPattern (*this);
     246              :   }
     247              : };
     248              : 
     249              : // Base range pattern bound (lower or upper limit) - abstract
     250          214 : class RangePatternBound
     251              : {
     252              : public:
     253              :   enum RangePatternBoundType
     254              :   {
     255              :     LITERAL,
     256              :     PATH,
     257              :     QUALPATH
     258              :   };
     259              : 
     260              :   virtual ~RangePatternBound () {}
     261              : 
     262              :   // Unique pointer custom clone function
     263          102 :   std::unique_ptr<RangePatternBound> clone_range_pattern_bound () const
     264              :   {
     265           51 :     return std::unique_ptr<RangePatternBound> (
     266           51 :       clone_range_pattern_bound_impl ());
     267              :   }
     268              : 
     269              :   virtual std::string as_string () const = 0;
     270              : 
     271              :   virtual void accept_vis (ASTVisitor &vis) = 0;
     272              : 
     273              :   virtual RangePatternBoundType get_bound_type () const = 0;
     274              : 
     275              : protected:
     276              :   // pure virtual as RangePatternBound is abstract
     277              :   virtual RangePatternBound *clone_range_pattern_bound_impl () const = 0;
     278              : };
     279              : 
     280              : // Literal-based pattern bound
     281          162 : class RangePatternBoundLiteral : public RangePatternBound
     282              : {
     283              :   Literal literal;
     284              :   /* Can only be a char, byte, int, or float literal - same impl here as
     285              :    * previously */
     286              : 
     287              :   // Minus prefixed to literal (if integer or floating-point)
     288              :   bool has_minus;
     289              : 
     290              :   location_t locus;
     291              : 
     292              : public:
     293              :   // Constructor
     294           89 :   RangePatternBoundLiteral (Literal literal, location_t locus,
     295              :                             bool has_minus = false)
     296           89 :     : literal (literal), has_minus (has_minus), locus (locus)
     297              :   {}
     298              : 
     299              :   std::string as_string () const override;
     300              : 
     301           59 :   Literal get_literal () const { return literal; }
     302              : 
     303           59 :   bool get_has_minus () const { return has_minus; }
     304              : 
     305           59 :   location_t get_locus () const { return locus; }
     306              : 
     307              :   void accept_vis (ASTVisitor &vis) override;
     308              : 
     309           59 :   RangePatternBoundType get_bound_type () const override
     310              :   {
     311           59 :     return RangePatternBoundType::LITERAL;
     312              :   }
     313              : 
     314              : protected:
     315              :   /* Use covariance to implement clone function as returning this object rather
     316              :    * than base */
     317           81 :   RangePatternBoundLiteral *clone_range_pattern_bound_impl () const override
     318              :   {
     319           81 :     return new RangePatternBoundLiteral (*this);
     320              :   }
     321              : };
     322              : 
     323              : // Path-based pattern bound
     324           21 : class RangePatternBoundPath : public RangePatternBound
     325              : {
     326              :   PathInExpression path;
     327              : 
     328              :   /* TODO: should this be refactored so that PathInExpression is a subclass of
     329              :    * RangePatternBound? */
     330              : 
     331              : public:
     332           23 :   RangePatternBoundPath (PathInExpression path) : path (std::move (path)) {}
     333              : 
     334            0 :   std::string as_string () const override { return path.as_string (); }
     335              : 
     336              :   location_t get_locus () const { return path.get_locus (); }
     337              : 
     338              :   void accept_vis (ASTVisitor &vis) override;
     339              : 
     340              :   // TODO: this mutable getter seems kinda dodgy
     341          294 :   PathInExpression &get_path () { return path; }
     342              :   const PathInExpression &get_path () const { return path; }
     343              : 
     344           21 :   RangePatternBoundType get_bound_type () const override
     345              :   {
     346           21 :     return RangePatternBoundType::PATH;
     347              :   }
     348              : 
     349              : protected:
     350              :   /* Use covariance to implement clone function as returning this object rather
     351              :    * than base */
     352           21 :   RangePatternBoundPath *clone_range_pattern_bound_impl () const override
     353              :   {
     354           21 :     return new RangePatternBoundPath (*this);
     355              :   }
     356              : };
     357              : 
     358              : // Qualified path-based pattern bound
     359            0 : class RangePatternBoundQualPath : public RangePatternBound
     360              : {
     361              :   QualifiedPathInExpression path;
     362              : 
     363              :   /* TODO: should this be refactored so that QualifiedPathInExpression is a
     364              :    * subclass of RangePatternBound? */
     365              : 
     366              : public:
     367            0 :   RangePatternBoundQualPath (QualifiedPathInExpression path)
     368            0 :     : path (std::move (path))
     369              :   {}
     370              : 
     371            0 :   std::string as_string () const override { return path.as_string (); }
     372              : 
     373              :   location_t get_locus () const { return path.get_locus (); }
     374              : 
     375              :   void accept_vis (ASTVisitor &vis) override;
     376              : 
     377              :   // TODO: this mutable getter seems kinda dodgy
     378            0 :   QualifiedPathInExpression &get_qualified_path () { return path; }
     379              :   const QualifiedPathInExpression &get_qualified_path () const { return path; }
     380              : 
     381            0 :   RangePatternBoundType get_bound_type () const override
     382              :   {
     383            0 :     return RangePatternBoundType::QUALPATH;
     384              :   }
     385              : 
     386              : protected:
     387              :   /* Use covariance to implement clone function as returning this object rather
     388              :    * than base */
     389            0 :   RangePatternBoundQualPath *clone_range_pattern_bound_impl () const override
     390              :   {
     391            0 :     return new RangePatternBoundQualPath (*this);
     392              :   }
     393              : };
     394              : 
     395              : enum class RangeKind
     396              : {
     397              :   INCLUDED,
     398              :   ELLIPSIS,
     399              :   EXCLUDED,
     400              : };
     401              : 
     402              : RangeKind tokenid_to_rangekind (TokenId id);
     403              : // AST node for matching within a certain range (range pattern)
     404              : class RangePattern : public Pattern
     405              : {
     406              :   std::unique_ptr<RangePatternBound> lower;
     407              :   std::unique_ptr<RangePatternBound> upper;
     408              : 
     409              :   RangeKind range_kind;
     410              : 
     411              :   /* location only stored to avoid a dereference - lower pattern should give
     412              :    * correct location so maybe change in future */
     413              :   location_t locus;
     414              :   NodeId node_id;
     415              : 
     416              : public:
     417              :   std::string as_string () const override;
     418              : 
     419              :   // Constructor
     420           56 :   RangePattern (std::unique_ptr<RangePatternBound> lower,
     421              :                 std::unique_ptr<RangePatternBound> upper, RangeKind range_kind,
     422              :                 location_t locus)
     423           56 :     : lower (std::move (lower)), upper (std::move (upper)),
     424           56 :       range_kind (range_kind), locus (locus),
     425           56 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
     426           56 :   {}
     427              : 
     428              :   // Copy constructor with clone
     429           51 :   RangePattern (RangePattern const &other)
     430          102 :     : lower (other.lower->clone_range_pattern_bound ()),
     431           51 :       upper (other.upper->clone_range_pattern_bound ()),
     432           51 :       range_kind (other.range_kind), locus (other.locus),
     433           51 :       node_id (other.node_id)
     434           51 :   {}
     435              : 
     436              :   // Overloaded assignment operator to clone
     437              :   RangePattern &operator= (RangePattern const &other)
     438              :   {
     439              :     lower = other.lower->clone_range_pattern_bound ();
     440              :     upper = other.upper->clone_range_pattern_bound ();
     441              :     range_kind = other.range_kind;
     442              :     locus = other.locus;
     443              :     node_id = other.node_id;
     444              : 
     445              :     return *this;
     446              :   }
     447              : 
     448              :   // default move semantics
     449              :   RangePattern (RangePattern &&other) = default;
     450              :   RangePattern &operator= (RangePattern &&other) = default;
     451              : 
     452          100 :   location_t get_locus () const override final { return locus; }
     453              : 
     454            0 :   bool get_has_ellipsis_syntax () const
     455              :   {
     456            0 :     return range_kind == RangeKind::ELLIPSIS;
     457              :   }
     458              : 
     459           91 :   RangeKind get_range_kind () const { return range_kind; }
     460              : 
     461          923 :   bool get_has_lower_bound () const { return lower != nullptr; }
     462              : 
     463          923 :   bool get_has_upper_bound () const { return upper != nullptr; }
     464              : 
     465              :   void accept_vis (ASTVisitor &vis) override;
     466              : 
     467              :   // TODO: is this better? or is a "vis_bound" better?
     468          963 :   RangePatternBound &get_lower_bound ()
     469              :   {
     470          963 :     rust_assert (lower != nullptr);
     471          963 :     return *lower;
     472              :   }
     473              : 
     474          963 :   RangePatternBound &get_upper_bound ()
     475              :   {
     476          963 :     rust_assert (upper != nullptr);
     477          963 :     return *upper;
     478              :   }
     479              : 
     480          152 :   NodeId get_node_id () const override { return node_id; }
     481              : 
     482            0 :   Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Range; }
     483              : 
     484              : protected:
     485              :   /* Use covariance to implement clone function as returning this object rather
     486              :    * than base */
     487           51 :   RangePattern *clone_pattern_impl () const override
     488              :   {
     489           51 :     return new RangePattern (*this);
     490              :   }
     491              : };
     492              : 
     493              : // AST node for pattern based on dereferencing the pointers given
     494              : class ReferencePattern : public Pattern
     495              : {
     496              :   bool has_two_amps;
     497              :   bool is_mut;
     498              :   std::unique_ptr<Pattern> pattern;
     499              :   location_t locus;
     500              :   NodeId node_id;
     501              : 
     502              : public:
     503              :   std::string as_string () const override;
     504              : 
     505          195 :   ReferencePattern (std::unique_ptr<Pattern> pattern, bool is_mut_reference,
     506              :                     bool ref_has_two_amps, location_t locus)
     507          195 :     : has_two_amps (ref_has_two_amps), is_mut (is_mut_reference),
     508          195 :       pattern (std::move (pattern)), locus (locus),
     509          195 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
     510          195 :   {}
     511              : 
     512              :   // Copy constructor requires clone
     513           29 :   ReferencePattern (ReferencePattern const &other)
     514           29 :     : has_two_amps (other.has_two_amps), is_mut (other.is_mut),
     515           29 :       pattern (other.pattern->clone_pattern ()), locus (other.locus),
     516           29 :       node_id (other.node_id)
     517           29 :   {}
     518              : 
     519              :   // Overload assignment operator to clone
     520              :   ReferencePattern &operator= (ReferencePattern const &other)
     521              :   {
     522              :     pattern = other.pattern->clone_pattern ();
     523              :     is_mut = other.is_mut;
     524              :     has_two_amps = other.has_two_amps;
     525              :     locus = other.locus;
     526              :     node_id = other.node_id;
     527              : 
     528              :     return *this;
     529              :   }
     530              : 
     531              :   // default move semantics
     532              :   ReferencePattern (ReferencePattern &&other) = default;
     533              :   ReferencePattern &operator= (ReferencePattern &&other) = default;
     534              : 
     535          218 :   location_t get_locus () const override final { return locus; }
     536              : 
     537              :   void accept_vis (ASTVisitor &vis) override;
     538              : 
     539              :   // TODO: is this better? Or is a "vis_pattern" better?
     540         3552 :   Pattern &get_referenced_pattern ()
     541              :   {
     542         3552 :     rust_assert (pattern != nullptr);
     543         3552 :     return *pattern;
     544              :   }
     545              : 
     546          736 :   std::unique_ptr<Pattern> &get_referenced_pattern_ptr ()
     547              :   {
     548          736 :     rust_assert (pattern != nullptr);
     549          736 :     return pattern;
     550              :   }
     551              : 
     552          193 :   bool is_double_reference () const { return has_two_amps; }
     553              : 
     554          193 :   bool get_is_mut () const { return is_mut; }
     555              : 
     556          744 :   NodeId get_node_id () const override { return node_id; }
     557              : 
     558            0 :   Pattern::Kind get_pattern_kind () override
     559              :   {
     560            0 :     return Pattern::Kind::Reference;
     561              :   }
     562              : 
     563              : protected:
     564              :   /* Use covariance to implement clone function as returning this object rather
     565              :    * than base */
     566           29 :   ReferencePattern *clone_pattern_impl () const override
     567              :   {
     568           29 :     return new ReferencePattern (*this);
     569              :   }
     570              : };
     571              : 
     572              : #if 0
     573              : // aka StructPatternEtCetera; potential element in struct pattern
     574              : struct StructPatternEtc
     575              : {
     576              : private:
     577              :   std::vector<Attribute> outer_attrs;
     578              : 
     579              :   // should this store location data?
     580              : 
     581              : public:
     582              :   StructPatternEtc (std::vector<Attribute> outer_attribs)
     583              :     : outer_attrs (std::move (outer_attribs))
     584              :   {}
     585              : 
     586              :   // Creates an empty StructPatternEtc
     587              :   static StructPatternEtc create_empty ()
     588              :   {
     589              :     return StructPatternEtc (std::vector<Attribute> ());
     590              :   }
     591              : };
     592              : #endif
     593              : 
     594              : // Base class for a single field in a struct pattern - abstract
     595          204 : class StructPatternField
     596              : {
     597              :   std::vector<Attribute> outer_attrs;
     598              :   location_t locus;
     599              : 
     600              : protected:
     601              :   NodeId node_id;
     602              : 
     603              : public:
     604              :   enum ItemType
     605              :   {
     606              :     TUPLE_PAT,
     607              :     IDENT_PAT,
     608              :     IDENT
     609              :   };
     610              : 
     611              :   virtual ~StructPatternField () {}
     612              : 
     613              :   // Unique pointer custom clone function
     614          204 :   std::unique_ptr<StructPatternField> clone_struct_pattern_field () const
     615              :   {
     616          204 :     return std::unique_ptr<StructPatternField> (
     617          204 :       clone_struct_pattern_field_impl ());
     618              :   }
     619              : 
     620              :   virtual std::string as_string () const;
     621              : 
     622          312 :   location_t get_locus () const { return locus; }
     623              : 
     624              :   virtual void accept_vis (ASTVisitor &vis) = 0;
     625              : 
     626              :   virtual void mark_for_strip () = 0;
     627              :   virtual bool is_marked_for_strip () const = 0;
     628              :   virtual ItemType get_item_type () const = 0;
     629              : 
     630          477 :   NodeId get_node_id () const { return node_id; }
     631              : 
     632              :   // TODO: seems kinda dodgy. Think of better way.
     633         3928 :   std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
     634              :   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
     635              : 
     636              : protected:
     637          277 :   StructPatternField (std::vector<Attribute> outer_attribs, location_t locus,
     638              :                       NodeId node_id)
     639          277 :     : outer_attrs (std::move (outer_attribs)), locus (locus), node_id (node_id)
     640              :   {}
     641              : 
     642              :   // Clone function implementation as pure virtual method
     643              :   virtual StructPatternField *clone_struct_pattern_field_impl () const = 0;
     644              : };
     645              : 
     646              : // Tuple pattern single field in a struct pattern
     647              : class StructPatternFieldTuplePat : public StructPatternField
     648              : {
     649              :   TupleIndex index;
     650              :   std::unique_ptr<Pattern> tuple_pattern;
     651              : 
     652              : public:
     653           26 :   StructPatternFieldTuplePat (TupleIndex index,
     654              :                               std::unique_ptr<Pattern> tuple_pattern,
     655              :                               std::vector<Attribute> outer_attribs,
     656              :                               location_t locus)
     657           26 :     : StructPatternField (std::move (outer_attribs), locus,
     658           26 :                           Analysis::Mappings::get ().get_next_node_id ()),
     659           26 :       index (index), tuple_pattern (std::move (tuple_pattern))
     660           26 :   {}
     661              : 
     662              :   // Copy constructor requires clone
     663           42 :   StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other)
     664           42 :     : StructPatternField (other), index (other.index)
     665              :   {
     666              :     // guard to prevent null dereference (only required if error state)
     667           42 :     node_id = other.get_node_id ();
     668           42 :     if (other.tuple_pattern != nullptr)
     669           42 :       tuple_pattern = other.tuple_pattern->clone_pattern ();
     670           42 :   }
     671              : 
     672              :   // Overload assignment operator to perform clone
     673              :   StructPatternFieldTuplePat &
     674              :   operator= (StructPatternFieldTuplePat const &other)
     675              :   {
     676              :     StructPatternField::operator= (other);
     677              :     index = other.index;
     678              :     // outer_attrs = other.outer_attrs;
     679              :     node_id = other.get_node_id ();
     680              : 
     681              :     // guard to prevent null dereference (only required if error state)
     682              :     if (other.tuple_pattern != nullptr)
     683              :       tuple_pattern = other.tuple_pattern->clone_pattern ();
     684              :     else
     685              :       tuple_pattern = nullptr;
     686              : 
     687              :     return *this;
     688              :   }
     689              : 
     690              :   // default move semantics
     691              :   StructPatternFieldTuplePat (StructPatternFieldTuplePat &&other) = default;
     692              :   StructPatternFieldTuplePat &operator= (StructPatternFieldTuplePat &&other)
     693              :     = default;
     694              : 
     695              :   std::string as_string () const override;
     696              : 
     697              :   void accept_vis (ASTVisitor &vis) override;
     698              : 
     699              :   // based on idea of tuple pattern no longer existing
     700            0 :   void mark_for_strip () override { tuple_pattern = nullptr; }
     701           78 :   bool is_marked_for_strip () const override
     702              :   {
     703           78 :     return tuple_pattern == nullptr;
     704              :   }
     705              : 
     706           42 :   TupleIndex get_index () { return index; }
     707              : 
     708              :   // TODO: is this better? Or is a "vis_pattern" better?
     709          414 :   Pattern &get_index_pattern ()
     710              :   {
     711          414 :     rust_assert (tuple_pattern != nullptr);
     712          414 :     return *tuple_pattern;
     713              :   }
     714              : 
     715           72 :   std::unique_ptr<Pattern> &get_index_pattern_ptr ()
     716              :   {
     717           72 :     rust_assert (tuple_pattern != nullptr);
     718           72 :     return tuple_pattern;
     719              :   }
     720              : 
     721           24 :   ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; }
     722              : 
     723              : protected:
     724              :   /* Use covariance to implement clone function as returning this object rather
     725              :    * than base */
     726           42 :   StructPatternFieldTuplePat *clone_struct_pattern_field_impl () const override
     727              :   {
     728           42 :     return new StructPatternFieldTuplePat (*this);
     729              :   }
     730              : };
     731              : 
     732              : // Identifier pattern single field in a struct pattern
     733              : class StructPatternFieldIdentPat : public StructPatternField
     734              : {
     735              :   Identifier ident;
     736              :   std::unique_ptr<Pattern> ident_pattern;
     737              : 
     738              : public:
     739          151 :   StructPatternFieldIdentPat (Identifier ident,
     740              :                               std::unique_ptr<Pattern> ident_pattern,
     741              :                               std::vector<Attribute> outer_attrs,
     742              :                               location_t locus)
     743          151 :     : StructPatternField (std::move (outer_attrs), locus,
     744          151 :                           Analysis::Mappings::get ().get_next_node_id ()),
     745          151 :       ident (std::move (ident)), ident_pattern (std::move (ident_pattern))
     746          151 :   {}
     747              : 
     748              :   // Copy constructor requires clone
     749           60 :   StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other)
     750           60 :     : StructPatternField (other), ident (other.ident)
     751              :   {
     752              :     // guard to prevent null dereference (only required if error state)
     753           60 :     node_id = other.get_node_id ();
     754           60 :     if (other.ident_pattern != nullptr)
     755           60 :       ident_pattern = other.ident_pattern->clone_pattern ();
     756           60 :   }
     757              : 
     758              :   // Overload assignment operator to clone
     759              :   StructPatternFieldIdentPat &
     760              :   operator= (StructPatternFieldIdentPat const &other)
     761              :   {
     762              :     StructPatternField::operator= (other);
     763              :     ident = other.ident;
     764              :     // outer_attrs = other.outer_attrs;
     765              :     node_id = other.get_node_id ();
     766              : 
     767              :     // guard to prevent null dereference (only required if error state)
     768              :     if (other.ident_pattern != nullptr)
     769              :       ident_pattern = other.ident_pattern->clone_pattern ();
     770              :     else
     771              :       ident_pattern = nullptr;
     772              : 
     773              :     return *this;
     774              :   }
     775              : 
     776              :   // default move semantics
     777              :   StructPatternFieldIdentPat (StructPatternFieldIdentPat &&other) = default;
     778              :   StructPatternFieldIdentPat &operator= (StructPatternFieldIdentPat &&other)
     779              :     = default;
     780              : 
     781              :   std::string as_string () const override;
     782              : 
     783              :   void accept_vis (ASTVisitor &vis) override;
     784              : 
     785              :   // based on idea of identifier pattern no longer existing
     786            0 :   void mark_for_strip () override { ident_pattern = nullptr; }
     787          516 :   bool is_marked_for_strip () const override
     788              :   {
     789          516 :     return ident_pattern == nullptr;
     790              :   }
     791              : 
     792          151 :   const Identifier &get_identifier () const { return ident; }
     793              : 
     794              :   // TODO: is this better? Or is a "vis_pattern" better?
     795         2543 :   Pattern &get_ident_pattern ()
     796              :   {
     797         2543 :     rust_assert (ident_pattern != nullptr);
     798         2543 :     return *ident_pattern;
     799              :   }
     800              : 
     801          545 :   std::unique_ptr<Pattern> &get_ident_pattern_ptr ()
     802              :   {
     803          545 :     rust_assert (ident_pattern != nullptr);
     804          545 :     return ident_pattern;
     805              :   }
     806              : 
     807          151 :   ItemType get_item_type () const override final { return ItemType::IDENT_PAT; }
     808              : 
     809              : protected:
     810              :   /* Use covariance to implement clone function as returning this object rather
     811              :    * than base */
     812           60 :   StructPatternFieldIdentPat *clone_struct_pattern_field_impl () const override
     813              :   {
     814           60 :     return new StructPatternFieldIdentPat (*this);
     815              :   }
     816              : };
     817              : 
     818              : // Identifier only (with no pattern) single field in a struct pattern
     819              : class StructPatternFieldIdent : public StructPatternField
     820              : {
     821              :   bool has_ref;
     822              :   bool has_mut;
     823              :   Identifier ident;
     824              : 
     825              : public:
     826          100 :   StructPatternFieldIdent (Identifier ident, bool is_ref, bool is_mut,
     827              :                            std::vector<Attribute> outer_attrs, location_t locus)
     828          100 :     : StructPatternField (std::move (outer_attrs), locus,
     829          100 :                           Analysis::Mappings::get ().get_next_node_id ()),
     830          100 :       has_ref (is_ref), has_mut (is_mut), ident (std::move (ident))
     831          100 :   {}
     832              : 
     833              :   std::string as_string () const override;
     834              : 
     835              :   void accept_vis (ASTVisitor &vis) override;
     836              : 
     837              :   // based on idea of identifier no longer existing
     838            0 :   void mark_for_strip () override { ident = {""}; }
     839          252 :   bool is_marked_for_strip () const override { return ident.empty (); }
     840              : 
     841          200 :   const Identifier &get_identifier () const { return ident; }
     842              : 
     843          100 :   ItemType get_item_type () const override final { return ItemType::IDENT; }
     844              : 
     845          202 :   bool is_ref () const { return has_ref; }
     846              : 
     847          202 :   bool is_mut () const { return has_mut; }
     848              : 
     849              : protected:
     850              :   /* Use covariance to implement clone function as returning this object rather
     851              :    * than base */
     852          102 :   StructPatternFieldIdent *clone_struct_pattern_field_impl () const override
     853              :   {
     854          102 :     return new StructPatternFieldIdent (*this);
     855              :   }
     856              : };
     857              : 
     858              : // Elements of a struct pattern
     859          211 : class StructPatternElements
     860              : {
     861              :   // bool has_struct_pattern_fields;
     862              :   std::vector<std::unique_ptr<StructPatternField>> fields;
     863              : 
     864              :   bool has_rest_pattern;
     865              :   std::vector<Attribute> struct_pattern_etc_attrs;
     866              :   // StructPatternEtc etc;
     867              : 
     868              :   // must have at least one of the two and maybe both
     869              : 
     870              :   // should this store location data?
     871              : 
     872              : public:
     873              :   // Returns whether there are any struct pattern fields
     874          514 :   bool has_struct_pattern_fields () const { return !fields.empty (); }
     875              : 
     876              :   /* Returns whether the struct pattern elements is entirely empty (no fields,
     877              :    * no etc). */
     878          502 :   bool is_empty () const
     879              :   {
     880            4 :     return !has_struct_pattern_fields () && !has_rest_pattern;
     881              :   }
     882              : 
     883          677 :   bool has_rest () const { return has_rest_pattern; }
     884              : 
     885              :   // Constructor for StructPatternElements with both (potentially)
     886            5 :   StructPatternElements (
     887              :     std::vector<std::unique_ptr<StructPatternField>> fields,
     888              :     std::vector<Attribute> etc_attrs)
     889            5 :     : fields (std::move (fields)), has_rest_pattern (true),
     890           10 :       struct_pattern_etc_attrs (std::move (etc_attrs))
     891              :   {}
     892              : 
     893              :   // Constructor for StructPatternElements with no StructPatternEtc
     894          161 :   StructPatternElements (
     895              :     std::vector<std::unique_ptr<StructPatternField>> fields)
     896           56 :     : fields (std::move (fields)), has_rest_pattern (false),
     897          138 :       struct_pattern_etc_attrs ()
     898              :   {}
     899              : 
     900              :   // Copy constructor with vector clone
     901          131 :   StructPatternElements (StructPatternElements const &other)
     902          131 :     : has_rest_pattern (other.has_rest_pattern),
     903          131 :       struct_pattern_etc_attrs (other.struct_pattern_etc_attrs)
     904              :   {
     905          131 :     fields.reserve (other.fields.size ());
     906          335 :     for (const auto &e : other.fields)
     907          204 :       fields.push_back (e->clone_struct_pattern_field ());
     908          131 :   }
     909              : 
     910              :   // Overloaded assignment operator with vector clone
     911              :   StructPatternElements &operator= (StructPatternElements const &other)
     912              :   {
     913              :     struct_pattern_etc_attrs = other.struct_pattern_etc_attrs;
     914              :     has_rest_pattern = other.has_rest_pattern;
     915              : 
     916              :     fields.clear ();
     917              :     fields.reserve (other.fields.size ());
     918              :     for (const auto &e : other.fields)
     919              :       fields.push_back (e->clone_struct_pattern_field ());
     920              : 
     921              :     return *this;
     922              :   }
     923              : 
     924              :   // move constructors
     925          322 :   StructPatternElements (StructPatternElements &&other) = default;
     926              :   StructPatternElements &operator= (StructPatternElements &&other) = default;
     927              : 
     928              :   // Creates an empty StructPatternElements
     929            0 :   static StructPatternElements create_empty ()
     930              :   {
     931            0 :     return StructPatternElements (
     932            0 :       std::vector<std::unique_ptr<StructPatternField>> ());
     933              :   }
     934              : 
     935              :   std::string as_string () const;
     936              : 
     937              :   // TODO: seems kinda dodgy. Think of better way.
     938          512 :   std::vector<std::unique_ptr<StructPatternField>> &get_struct_pattern_fields ()
     939              :   {
     940         2734 :     return fields;
     941              :   }
     942              :   const std::vector<std::unique_ptr<StructPatternField>> &
     943              :   get_struct_pattern_fields () const
     944              :   {
     945              :     return fields;
     946              :   }
     947              : 
     948           12 :   std::vector<Attribute> &get_etc_outer_attrs ()
     949              :   {
     950         2069 :     return struct_pattern_etc_attrs;
     951              :   }
     952              :   const std::vector<Attribute> &get_etc_outer_attrs () const
     953              :   {
     954              :     return struct_pattern_etc_attrs;
     955              :   }
     956              : 
     957            0 :   void strip_etc ()
     958              :   {
     959            0 :     has_rest_pattern = false;
     960            0 :     struct_pattern_etc_attrs.clear ();
     961            0 :     struct_pattern_etc_attrs.shrink_to_fit ();
     962              :   }
     963              : };
     964              : 
     965              : // Struct pattern AST node representation
     966              : class StructPattern : public Pattern
     967              : {
     968              :   PathInExpression path;
     969              : 
     970              :   // bool has_struct_pattern_elements;
     971              :   StructPatternElements elems;
     972              : 
     973              :   NodeId node_id;
     974              :   location_t locus;
     975              : 
     976              : public:
     977              :   std::string as_string () const override;
     978              : 
     979              :   // Constructs a struct pattern from specified StructPatternElements
     980          166 :   StructPattern (PathInExpression struct_path, location_t locus,
     981              :                  StructPatternElements elems
     982              :                  = StructPatternElements::create_empty ())
     983          166 :     : path (std::move (struct_path)), elems (std::move (elems)),
     984          332 :       node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
     985          166 :   {}
     986              : 
     987              :   /* TODO: constructor to construct via elements included in
     988              :    * StructPatternElements */
     989              : 
     990              :   /* Returns whether struct pattern has any struct pattern elements (if not, it
     991              :    * is empty). */
     992          504 :   bool has_struct_pattern_elems () const { return !elems.is_empty (); }
     993              : 
     994          177 :   location_t get_locus () const override { return locus; }
     995              : 
     996              :   void accept_vis (ASTVisitor &vis) override;
     997              : 
     998              :   // TODO: seems kinda dodgy. Think of better way.
     999         2734 :   StructPatternElements &get_struct_pattern_elems () { return elems; }
    1000              :   const StructPatternElements &get_struct_pattern_elems () const
    1001              :   {
    1002              :     return elems;
    1003              :   }
    1004              : 
    1005         2736 :   PathInExpression &get_path () { return path; }
    1006              :   const PathInExpression &get_path () const { return path; }
    1007              : 
    1008          558 :   NodeId get_node_id () const override { return node_id; }
    1009              : 
    1010            0 :   Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Struct; }
    1011              : 
    1012              : protected:
    1013              :   /* Use covariance to implement clone function as returning this object rather
    1014              :    * than base */
    1015          109 :   StructPattern *clone_pattern_impl () const override
    1016              :   {
    1017          109 :     return new StructPattern (*this);
    1018              :   }
    1019              : };
    1020              : 
    1021              : // Base abstract class for TupleStructItems, TuplePatternItems &
    1022              : // SlicePatternItems
    1023         4025 : class PatternItems
    1024              : {
    1025              : public:
    1026              :   enum ItemType
    1027              :   {
    1028              :     NO_REST,
    1029              :     HAS_REST,
    1030              :   };
    1031              : 
    1032              :   virtual ~PatternItems () {}
    1033              : 
    1034              :   // TODO: should this store location data?
    1035              : 
    1036              :   // Unique pointer custom clone function
    1037              :   std::unique_ptr<PatternItems> clone_pattern_items () const
    1038              :   {
    1039              :     return std::unique_ptr<PatternItems> (clone_pattern_items_impl ());
    1040              :   }
    1041              : 
    1042              :   virtual std::string as_string () const = 0;
    1043              :   virtual ItemType get_item_type () const = 0;
    1044              :   virtual void accept_vis (ASTVisitor &vis) = 0;
    1045              : 
    1046              : protected:
    1047              :   virtual PatternItems *clone_pattern_items_impl () const = 0;
    1048              : };
    1049              : 
    1050              : // Base abstract class for patterns used in TupleStructPattern
    1051         2290 : class TupleStructItems : public PatternItems
    1052              : {
    1053              : public:
    1054              :   // Unique pointer custom clone function
    1055         1196 :   std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const
    1056              :   {
    1057         1196 :     return std::unique_ptr<TupleStructItems> (clone_pattern_items_impl ());
    1058              :   }
    1059              : 
    1060              : protected:
    1061              :   // pure virtual clone implementation
    1062              :   virtual TupleStructItems *clone_pattern_items_impl () const = 0;
    1063              : };
    1064              : 
    1065              : // Class for non-ranged tuple struct pattern patterns
    1066              : class TupleStructItemsNoRest : public TupleStructItems
    1067              : {
    1068              :   std::vector<std::unique_ptr<Pattern>> patterns;
    1069              : 
    1070              : public:
    1071         1055 :   TupleStructItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
    1072         1055 :     : patterns (std::move (patterns))
    1073              :   {}
    1074              : 
    1075              :   // Copy constructor with vector clone
    1076         1157 :   TupleStructItemsNoRest (TupleStructItemsNoRest const &other)
    1077         1157 :   {
    1078         1157 :     patterns.reserve (other.patterns.size ());
    1079         2351 :     for (const auto &e : other.patterns)
    1080         1194 :       patterns.push_back (e->clone_pattern ());
    1081         1157 :   }
    1082              : 
    1083              :   // Overloaded assignment operator with vector clone
    1084              :   TupleStructItemsNoRest &operator= (TupleStructItemsNoRest const &other)
    1085              :   {
    1086              :     patterns.clear ();
    1087              :     patterns.reserve (other.patterns.size ());
    1088              :     for (const auto &e : other.patterns)
    1089              :       patterns.push_back (e->clone_pattern ());
    1090              : 
    1091              :     return *this;
    1092              :   }
    1093              : 
    1094              :   // move constructors
    1095              :   TupleStructItemsNoRest (TupleStructItemsNoRest &&other) = default;
    1096              :   TupleStructItemsNoRest &operator= (TupleStructItemsNoRest &&other) = default;
    1097              : 
    1098              :   std::string as_string () const override;
    1099              : 
    1100              :   void accept_vis (ASTVisitor &vis) override;
    1101              : 
    1102              :   // TODO: seems kinda dodgy. Think of better way.
    1103        24356 :   std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
    1104              :   const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
    1105              :   {
    1106              :     return patterns;
    1107              :   }
    1108              : 
    1109          967 :   ItemType get_item_type () const override final { return ItemType::NO_REST; }
    1110              : 
    1111              : protected:
    1112              :   /* Use covariance to implement clone function as returning this object rather
    1113              :    * than base */
    1114         1157 :   TupleStructItemsNoRest *clone_pattern_items_impl () const override
    1115              :   {
    1116         1157 :     return new TupleStructItemsNoRest (*this);
    1117              :   }
    1118              : };
    1119              : 
    1120              : // Class for ranged tuple struct pattern patterns
    1121              : class TupleStructItemsHasRest : public TupleStructItems
    1122              : {
    1123              :   std::vector<std::unique_ptr<Pattern>> lower_patterns;
    1124              :   std::vector<std::unique_ptr<Pattern>> upper_patterns;
    1125              : 
    1126              : public:
    1127           39 :   TupleStructItemsHasRest (std::vector<std::unique_ptr<Pattern>> lower_patterns,
    1128              :                            std::vector<std::unique_ptr<Pattern>> upper_patterns)
    1129           39 :     : lower_patterns (std::move (lower_patterns)),
    1130           39 :       upper_patterns (std::move (upper_patterns))
    1131              :   {}
    1132              : 
    1133              :   // Copy constructor with vector clone
    1134           39 :   TupleStructItemsHasRest (TupleStructItemsHasRest const &other)
    1135           39 :   {
    1136           39 :     lower_patterns.reserve (other.lower_patterns.size ());
    1137           70 :     for (const auto &e : other.lower_patterns)
    1138           31 :       lower_patterns.push_back (e->clone_pattern ());
    1139              : 
    1140           39 :     upper_patterns.reserve (other.upper_patterns.size ());
    1141           58 :     for (const auto &e : other.upper_patterns)
    1142           19 :       upper_patterns.push_back (e->clone_pattern ());
    1143           39 :   }
    1144              : 
    1145              :   // Overloaded assignment operator to clone
    1146              :   TupleStructItemsHasRest &operator= (TupleStructItemsHasRest const &other)
    1147              :   {
    1148              :     lower_patterns.clear ();
    1149              :     lower_patterns.reserve (other.lower_patterns.size ());
    1150              :     for (const auto &e : other.lower_patterns)
    1151              :       lower_patterns.push_back (e->clone_pattern ());
    1152              : 
    1153              :     upper_patterns.clear ();
    1154              :     upper_patterns.reserve (other.upper_patterns.size ());
    1155              :     for (const auto &e : other.upper_patterns)
    1156              :       upper_patterns.push_back (e->clone_pattern ());
    1157              : 
    1158              :     return *this;
    1159              :   }
    1160              : 
    1161              :   // move constructors
    1162              :   TupleStructItemsHasRest (TupleStructItemsHasRest &&other) = default;
    1163              :   TupleStructItemsHasRest &operator= (TupleStructItemsHasRest &&other)
    1164              :     = default;
    1165              : 
    1166              :   std::string as_string () const override;
    1167              : 
    1168              :   void accept_vis (ASTVisitor &vis) override;
    1169              : 
    1170              :   // TODO: seems kinda dodgy. Think of better way.
    1171              :   std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
    1172              :   {
    1173          803 :     return lower_patterns;
    1174              :   }
    1175              :   const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
    1176              :   {
    1177              :     return lower_patterns;
    1178              :   }
    1179              : 
    1180              :   // TODO: seems kinda dodgy. Think of better way.
    1181              :   std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
    1182              :   {
    1183          803 :     return upper_patterns;
    1184              :   }
    1185              :   const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
    1186              :   {
    1187              :     return upper_patterns;
    1188              :   }
    1189              : 
    1190           39 :   ItemType get_item_type () const override final { return ItemType::HAS_REST; }
    1191              : 
    1192              : protected:
    1193              :   /* Use covariance to implement clone function as returning this object rather
    1194              :    * than base */
    1195           39 :   TupleStructItemsHasRest *clone_pattern_items_impl () const override
    1196              :   {
    1197           39 :     return new TupleStructItemsHasRest (*this);
    1198              :   }
    1199              : };
    1200              : 
    1201              : // AST node representing a tuple struct pattern
    1202              : class TupleStructPattern : public Pattern
    1203              : {
    1204              :   PathInExpression path;
    1205              :   std::unique_ptr<TupleStructItems> items;
    1206              :   NodeId node_id;
    1207              : 
    1208              :   /* TOOD: should this store location data? current accessor uses path location
    1209              :    * data */
    1210              : 
    1211              : public:
    1212              :   std::string as_string () const override;
    1213              : 
    1214         1094 :   TupleStructPattern (PathInExpression tuple_struct_path,
    1215              :                       std::unique_ptr<TupleStructItems> items)
    1216         1094 :     : path (std::move (tuple_struct_path)), items (std::move (items)),
    1217         1094 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
    1218              :   {
    1219         1094 :     rust_assert (this->items != nullptr);
    1220         1094 :   }
    1221              : 
    1222              :   // Copy constructor required to clone
    1223         1196 :   TupleStructPattern (TupleStructPattern const &other) : path (other.path)
    1224              :   {
    1225              :     // guard to protect from null dereference
    1226         1196 :     rust_assert (other.items != nullptr);
    1227              : 
    1228         1196 :     node_id = other.node_id;
    1229         1196 :     items = other.items->clone_tuple_struct_items ();
    1230         1196 :   }
    1231              : 
    1232              :   // Operator overload assignment operator to clone
    1233              :   TupleStructPattern &operator= (TupleStructPattern const &other)
    1234              :   {
    1235              :     path = other.path;
    1236              :     node_id = other.node_id;
    1237              : 
    1238              :     // guard to protect from null dereference
    1239              :     rust_assert (other.items != nullptr);
    1240              : 
    1241              :     items = other.items->clone_tuple_struct_items ();
    1242              : 
    1243              :     return *this;
    1244              :   }
    1245              : 
    1246              :   // move constructors
    1247              :   TupleStructPattern (TupleStructPattern &&other) = default;
    1248              :   TupleStructPattern &operator= (TupleStructPattern &&other) = default;
    1249              : 
    1250         1042 :   location_t get_locus () const override { return path.get_locus (); }
    1251              : 
    1252              :   void accept_vis (ASTVisitor &vis) override;
    1253              : 
    1254        20223 :   TupleStructItems &get_items ()
    1255              :   {
    1256        20223 :     rust_assert (items != nullptr);
    1257        20223 :     return *items;
    1258              :   }
    1259              : 
    1260        25159 :   PathInExpression &get_path () { return path; }
    1261              :   const PathInExpression &get_path () const { return path; }
    1262              : 
    1263         3640 :   NodeId get_node_id () const override { return node_id; }
    1264              : 
    1265            0 :   Pattern::Kind get_pattern_kind () override
    1266              :   {
    1267            0 :     return Pattern::Kind::TupleStruct;
    1268              :   }
    1269              : 
    1270              : protected:
    1271              :   /* Use covariance to implement clone function as returning this object rather
    1272              :    * than base */
    1273         1196 :   TupleStructPattern *clone_pattern_impl () const override
    1274              :   {
    1275         1196 :     return new TupleStructPattern (*this);
    1276              :   }
    1277              : };
    1278              : 
    1279              : // Base abstract class representing TuplePattern patterns
    1280         1582 : class TuplePatternItems : public PatternItems
    1281              : {
    1282              : public:
    1283              :   // Unique pointer custom clone function
    1284         1126 :   std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const
    1285              :   {
    1286         1126 :     return std::unique_ptr<TuplePatternItems> (clone_pattern_items_impl ());
    1287              :   }
    1288              : 
    1289              : protected:
    1290              :   // pure virtual clone implementation
    1291              :   virtual TuplePatternItems *clone_pattern_items_impl () const = 0;
    1292              : };
    1293              : 
    1294              : // Class representing TuplePattern patterns which contains no rest pattern
    1295              : class TuplePatternItemsNoRest : public TuplePatternItems
    1296              : {
    1297              :   std::vector<std::unique_ptr<Pattern>> patterns;
    1298              : 
    1299              : public:
    1300          429 :   TuplePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
    1301          429 :     : patterns (std::move (patterns))
    1302              :   {}
    1303              : 
    1304              :   // Copy constructor with vector clone
    1305         1099 :   TuplePatternItemsNoRest (TuplePatternItemsNoRest const &other)
    1306         1099 :   {
    1307         1099 :     patterns.reserve (other.patterns.size ());
    1308         3299 :     for (const auto &e : other.patterns)
    1309         2200 :       patterns.push_back (e->clone_pattern ());
    1310         1099 :   }
    1311              : 
    1312              :   // Overloaded assignment operator to vector clone
    1313              :   TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest const &other)
    1314              :   {
    1315              :     patterns.clear ();
    1316              :     patterns.reserve (other.patterns.size ());
    1317              :     for (const auto &e : other.patterns)
    1318              :       patterns.push_back (e->clone_pattern ());
    1319              : 
    1320              :     return *this;
    1321              :   }
    1322              : 
    1323              :   // move constructors
    1324              :   TuplePatternItemsNoRest (TuplePatternItemsNoRest &&other) = default;
    1325              :   TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest &&other)
    1326              :     = default;
    1327              : 
    1328              :   std::string as_string () const override;
    1329              : 
    1330              :   void accept_vis (ASTVisitor &vis) override;
    1331              : 
    1332              :   // TODO: seems kinda dodgy. Think of better way.
    1333        14218 :   std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
    1334              :   const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
    1335              :   {
    1336              :     return patterns;
    1337              :   }
    1338              : 
    1339          397 :   ItemType get_item_type () const override { return ItemType::NO_REST; }
    1340              : 
    1341              : protected:
    1342              :   /* Use covariance to implement clone function as returning this object rather
    1343              :    * than base */
    1344         1099 :   TuplePatternItemsNoRest *clone_pattern_items_impl () const override
    1345              :   {
    1346         1099 :     return new TuplePatternItemsNoRest (*this);
    1347              :   }
    1348              : };
    1349              : 
    1350              : // Class representing TuplePattern patterns which contains a rest pattern
    1351              : class TuplePatternItemsHasRest : public TuplePatternItems
    1352              : {
    1353              :   std::vector<std::unique_ptr<Pattern>> lower_patterns;
    1354              :   std::vector<std::unique_ptr<Pattern>> upper_patterns;
    1355              : 
    1356              : public:
    1357           27 :   TuplePatternItemsHasRest (
    1358              :     std::vector<std::unique_ptr<Pattern>> lower_patterns,
    1359              :     std::vector<std::unique_ptr<Pattern>> upper_patterns)
    1360           27 :     : lower_patterns (std::move (lower_patterns)),
    1361           27 :       upper_patterns (std::move (upper_patterns))
    1362              :   {}
    1363              : 
    1364              :   // Copy constructor with vector clone
    1365           27 :   TuplePatternItemsHasRest (TuplePatternItemsHasRest const &other)
    1366           27 :   {
    1367           27 :     lower_patterns.reserve (other.lower_patterns.size ());
    1368           55 :     for (const auto &e : other.lower_patterns)
    1369           28 :       lower_patterns.push_back (e->clone_pattern ());
    1370              : 
    1371           27 :     upper_patterns.reserve (other.upper_patterns.size ());
    1372           59 :     for (const auto &e : other.upper_patterns)
    1373           32 :       upper_patterns.push_back (e->clone_pattern ());
    1374           27 :   }
    1375              : 
    1376              :   // Overloaded assignment operator to clone
    1377              :   TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest const &other)
    1378              :   {
    1379              :     lower_patterns.clear ();
    1380              :     lower_patterns.reserve (other.lower_patterns.size ());
    1381              :     for (const auto &e : other.lower_patterns)
    1382              :       lower_patterns.push_back (e->clone_pattern ());
    1383              : 
    1384              :     upper_patterns.clear ();
    1385              :     upper_patterns.reserve (other.upper_patterns.size ());
    1386              :     for (const auto &e : other.upper_patterns)
    1387              :       upper_patterns.push_back (e->clone_pattern ());
    1388              : 
    1389              :     return *this;
    1390              :   }
    1391              : 
    1392              :   // move constructors
    1393              :   TuplePatternItemsHasRest (TuplePatternItemsHasRest &&other) = default;
    1394              :   TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest &&other)
    1395              :     = default;
    1396              : 
    1397              :   std::string as_string () const override;
    1398              : 
    1399              :   void accept_vis (ASTVisitor &vis) override;
    1400              : 
    1401              :   // TODO: seems kinda dodgy. Think of better way.
    1402              :   std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
    1403              :   {
    1404          555 :     return lower_patterns;
    1405              :   }
    1406              :   const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
    1407              :   {
    1408              :     return lower_patterns;
    1409              :   }
    1410              : 
    1411              :   // TODO: seems kinda dodgy. Think of better way.
    1412              :   std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
    1413              :   {
    1414          555 :     return upper_patterns;
    1415              :   }
    1416              :   const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
    1417              :   {
    1418              :     return upper_patterns;
    1419              :   }
    1420              : 
    1421           27 :   ItemType get_item_type () const override { return ItemType::HAS_REST; }
    1422              : 
    1423              : protected:
    1424              :   /* Use covariance to implement clone function as returning this object rather
    1425              :    * than base */
    1426           27 :   TuplePatternItemsHasRest *clone_pattern_items_impl () const override
    1427              :   {
    1428           27 :     return new TuplePatternItemsHasRest (*this);
    1429              :   }
    1430              : };
    1431              : 
    1432              : // AST node representing a tuple pattern
    1433              : class TuplePattern : public Pattern
    1434              : {
    1435              :   std::unique_ptr<TuplePatternItems> items;
    1436              :   location_t locus;
    1437              :   NodeId node_id;
    1438              : 
    1439              : public:
    1440              :   std::string as_string () const override;
    1441              : 
    1442          456 :   TuplePattern (std::unique_ptr<TuplePatternItems> items, location_t locus)
    1443          456 :     : items (std::move (items)), locus (locus),
    1444          456 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
    1445              :   {
    1446          456 :     rust_assert (this->items != nullptr);
    1447          456 :   }
    1448              : 
    1449              :   // Copy constructor requires clone
    1450         1126 :   TuplePattern (TuplePattern const &other) : locus (other.locus)
    1451              :   {
    1452              :     // guard to prevent null dereference
    1453         1126 :     rust_assert (other.items != nullptr);
    1454              : 
    1455         1126 :     node_id = other.node_id;
    1456         1126 :     items = other.items->clone_tuple_pattern_items ();
    1457         1126 :   }
    1458              : 
    1459              :   // Overload assignment operator to clone
    1460              :   TuplePattern &operator= (TuplePattern const &other)
    1461              :   {
    1462              :     locus = other.locus;
    1463              :     node_id = other.node_id;
    1464              : 
    1465              :     // guard to prevent null dereference
    1466              :     rust_assert (other.items != nullptr);
    1467              : 
    1468              :     items = other.items->clone_tuple_pattern_items ();
    1469              :     return *this;
    1470              :   }
    1471              : 
    1472          853 :   location_t get_locus () const override final { return locus; }
    1473              : 
    1474              :   void accept_vis (ASTVisitor &vis) override;
    1475              : 
    1476              :   // TODO: seems kinda dodgy. Think of better way.
    1477        11161 :   TuplePatternItems &get_items ()
    1478              :   {
    1479        11161 :     rust_assert (items != nullptr);
    1480        11161 :     return *items;
    1481              :   }
    1482              : 
    1483         1650 :   NodeId get_node_id () const override { return node_id; }
    1484              : 
    1485            0 :   Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Tuple; }
    1486              : 
    1487              : protected:
    1488              :   /* Use covariance to implement clone function as returning this object rather
    1489              :    * than base */
    1490         1126 :   TuplePattern *clone_pattern_impl () const override
    1491              :   {
    1492         1126 :     return new TuplePattern (*this);
    1493              :   }
    1494              : };
    1495              : 
    1496              : // AST node representing a pattern in parentheses, used to control precedence
    1497              : class GroupedPattern : public Pattern
    1498              : {
    1499              :   std::unique_ptr<Pattern> pattern_in_parens;
    1500              :   location_t locus;
    1501              :   NodeId node_id;
    1502              : 
    1503              : public:
    1504            0 :   std::string as_string () const override
    1505              :   {
    1506            0 :     return "(" + pattern_in_parens->as_string () + ")";
    1507              :   }
    1508              : 
    1509           44 :   GroupedPattern (std::unique_ptr<Pattern> pattern_in_parens, location_t locus)
    1510           44 :     : pattern_in_parens (std::move (pattern_in_parens)), locus (locus),
    1511           44 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
    1512           44 :   {}
    1513              : 
    1514              :   // Copy constructor uses clone
    1515           44 :   GroupedPattern (GroupedPattern const &other)
    1516           88 :     : pattern_in_parens (other.pattern_in_parens->clone_pattern ()),
    1517           44 :       locus (other.locus), node_id (other.node_id)
    1518           44 :   {}
    1519              : 
    1520              :   // Overload assignment operator to clone
    1521              :   GroupedPattern &operator= (GroupedPattern const &other)
    1522              :   {
    1523              :     pattern_in_parens = other.pattern_in_parens->clone_pattern ();
    1524              :     locus = other.locus;
    1525              :     node_id = other.node_id;
    1526              : 
    1527              :     return *this;
    1528              :   }
    1529              : 
    1530              :   // default move semantics
    1531              :   GroupedPattern (GroupedPattern &&other) = default;
    1532              :   GroupedPattern &operator= (GroupedPattern &&other) = default;
    1533              : 
    1534            3 :   location_t get_locus () const override final { return locus; }
    1535              : 
    1536              :   void accept_vis (ASTVisitor &vis) override;
    1537              : 
    1538              :   // TODO: seems kinda dodgy. Think of better way.
    1539          751 :   Pattern &get_pattern_in_parens ()
    1540              :   {
    1541          751 :     rust_assert (pattern_in_parens != nullptr);
    1542          751 :     return *pattern_in_parens;
    1543              :   }
    1544              : 
    1545          132 :   std::unique_ptr<Pattern> &get_pattern_in_parens_ptr ()
    1546              :   {
    1547          132 :     rust_assert (pattern_in_parens != nullptr);
    1548          132 :     return pattern_in_parens;
    1549              :   }
    1550              : 
    1551           88 :   NodeId get_node_id () const override { return node_id; }
    1552              : 
    1553            0 :   Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Grouped; }
    1554              : 
    1555              : protected:
    1556              :   /* Use covariance to implement clone function as returning this object rather
    1557              :    * than base */
    1558           44 :   GroupedPattern *clone_pattern_impl () const override
    1559              :   {
    1560           44 :     return new GroupedPattern (*this);
    1561              :   }
    1562              : };
    1563              : 
    1564              : // Base abstract class representing patterns in a SlicePattern
    1565          153 : class SlicePatternItems : public PatternItems
    1566              : {
    1567              : public:
    1568              :   // Unique pointer custom clone function
    1569           76 :   std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const
    1570              :   {
    1571           76 :     return std::unique_ptr<SlicePatternItems> (clone_pattern_items_impl ());
    1572              :   }
    1573              : 
    1574              : protected:
    1575              :   // pure virtual clone implementation
    1576              :   virtual SlicePatternItems *clone_pattern_items_impl () const = 0;
    1577              : };
    1578              : 
    1579              : // Class representing the patterns in a SlicePattern without `..`
    1580              : class SlicePatternItemsNoRest : public SlicePatternItems
    1581              : {
    1582              :   std::vector<std::unique_ptr<Pattern>> patterns;
    1583              : 
    1584              : public:
    1585           33 :   SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
    1586           33 :     : patterns (std::move (patterns))
    1587              :   {}
    1588              : 
    1589              :   // Copy constructor with vector clone
    1590           32 :   SlicePatternItemsNoRest (SlicePatternItemsNoRest const &other)
    1591           32 :   {
    1592           32 :     patterns.reserve (other.patterns.size ());
    1593           96 :     for (const auto &e : other.patterns)
    1594           64 :       patterns.push_back (e->clone_pattern ());
    1595           32 :   }
    1596              : 
    1597              :   // Overloaded assignment operator to vector clone
    1598              :   SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other)
    1599              :   {
    1600              :     patterns.clear ();
    1601              :     patterns.reserve (other.patterns.size ());
    1602              :     for (const auto &e : other.patterns)
    1603              :       patterns.push_back (e->clone_pattern ());
    1604              : 
    1605              :     return *this;
    1606              :   }
    1607              : 
    1608              :   // move constructors
    1609              :   SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default;
    1610              :   SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other)
    1611              :     = default;
    1612              : 
    1613              :   std::string as_string () const override;
    1614              : 
    1615              :   void accept_vis (ASTVisitor &vis) override;
    1616              : 
    1617              :   // TODO: seems kinda dodgy. Think of better way.
    1618          656 :   std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
    1619              :   const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
    1620              :   {
    1621              :     return patterns;
    1622              :   }
    1623              : 
    1624           32 :   ItemType get_item_type () const override { return ItemType::NO_REST; }
    1625              : 
    1626              : protected:
    1627              :   /* Use covariance to implement clone function as returning this object rather
    1628              :    * than base */
    1629           32 :   SlicePatternItemsNoRest *clone_pattern_items_impl () const override
    1630              :   {
    1631           32 :     return new SlicePatternItemsNoRest (*this);
    1632              :   }
    1633              : };
    1634              : 
    1635              : // Class representing the patterns in a SlicePattern that contains a `..`
    1636              : class SlicePatternItemsHasRest : public SlicePatternItems
    1637              : {
    1638              :   std::vector<std::unique_ptr<Pattern>> lower_patterns;
    1639              :   std::vector<std::unique_ptr<Pattern>> upper_patterns;
    1640              : 
    1641              : public:
    1642           44 :   SlicePatternItemsHasRest (
    1643              :     std::vector<std::unique_ptr<Pattern>> lower_patterns,
    1644              :     std::vector<std::unique_ptr<Pattern>> upper_patterns)
    1645           44 :     : lower_patterns (std::move (lower_patterns)),
    1646           44 :       upper_patterns (std::move (upper_patterns))
    1647              :   {}
    1648              : 
    1649              :   // Copy constructor with vector clone
    1650           44 :   SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other)
    1651           44 :   {
    1652           44 :     lower_patterns.reserve (other.lower_patterns.size ());
    1653           87 :     for (const auto &e : other.lower_patterns)
    1654           43 :       lower_patterns.push_back (e->clone_pattern ());
    1655              : 
    1656           44 :     upper_patterns.reserve (other.upper_patterns.size ());
    1657           87 :     for (const auto &e : other.upper_patterns)
    1658           43 :       upper_patterns.push_back (e->clone_pattern ());
    1659           44 :   }
    1660              : 
    1661              :   // Overloaded assignment operator to clone
    1662              :   SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other)
    1663              :   {
    1664              :     lower_patterns.clear ();
    1665              :     lower_patterns.reserve (other.lower_patterns.size ());
    1666              :     for (const auto &e : other.lower_patterns)
    1667              :       lower_patterns.push_back (e->clone_pattern ());
    1668              : 
    1669              :     upper_patterns.clear ();
    1670              :     upper_patterns.reserve (other.upper_patterns.size ());
    1671              :     for (const auto &e : other.upper_patterns)
    1672              :       upper_patterns.push_back (e->clone_pattern ());
    1673              : 
    1674              :     return *this;
    1675              :   }
    1676              : 
    1677              :   // move constructors
    1678              :   SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default;
    1679              :   SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other)
    1680              :     = default;
    1681              : 
    1682              :   std::string as_string () const override;
    1683              : 
    1684              :   void accept_vis (ASTVisitor &vis) override;
    1685              : 
    1686              :   // TODO: seems kinda dodgy. Think of better way.
    1687            1 :   std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
    1688              :   {
    1689          918 :     return lower_patterns;
    1690              :   }
    1691              :   const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
    1692              :   {
    1693              :     return lower_patterns;
    1694              :   }
    1695              : 
    1696              :   // TODO: seems kinda dodgy. Think of better way.
    1697            1 :   std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
    1698              :   {
    1699          919 :     return upper_patterns;
    1700              :   }
    1701              :   const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
    1702              :   {
    1703              :     return upper_patterns;
    1704              :   }
    1705              : 
    1706           44 :   ItemType get_item_type () const override { return ItemType::HAS_REST; }
    1707              : 
    1708              : protected:
    1709              :   /* Use covariance to implement clone function as returning this object rather
    1710              :    * than base */
    1711           44 :   SlicePatternItemsHasRest *clone_pattern_items_impl () const override
    1712              :   {
    1713           44 :     return new SlicePatternItemsHasRest (*this);
    1714              :   }
    1715              : };
    1716              : 
    1717              : // AST node representing patterns that can match slices and arrays
    1718              : class SlicePattern : public Pattern
    1719              : {
    1720              :   std::unique_ptr<SlicePatternItems> items;
    1721              :   location_t locus;
    1722              :   NodeId node_id;
    1723              : 
    1724              : public:
    1725              :   std::string as_string () const override;
    1726              : 
    1727           77 :   SlicePattern (std::unique_ptr<SlicePatternItems> items, location_t locus)
    1728           77 :     : items (std::move (items)), locus (locus),
    1729           77 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
    1730           77 :   {}
    1731              : 
    1732              :   // Copy constructor requires clone
    1733           76 :   SlicePattern (SlicePattern const &other) : locus (other.locus)
    1734              :   {
    1735              :     // guard to prevent null dereference
    1736           76 :     rust_assert (other.items != nullptr);
    1737              : 
    1738           76 :     node_id = other.node_id;
    1739           76 :     items = other.items->clone_slice_pattern_items ();
    1740           76 :   }
    1741              : 
    1742              :   // Overloaded assignment operator to clone
    1743              :   SlicePattern &operator= (SlicePattern const &other)
    1744              :   {
    1745              :     locus = other.locus;
    1746              :     node_id = other.node_id;
    1747              : 
    1748              :     // guard to prevent null dereference
    1749              :     rust_assert (other.items != nullptr);
    1750              : 
    1751              :     items = other.items->clone_slice_pattern_items ();
    1752              :     return *this;
    1753              :   }
    1754              : 
    1755              :   // move constructors
    1756              :   SlicePattern (SlicePattern &&other) = default;
    1757              :   SlicePattern &operator= (SlicePattern &&other) = default;
    1758              : 
    1759          154 :   location_t get_locus () const override final { return locus; }
    1760              : 
    1761              :   void accept_vis (ASTVisitor &vis) override;
    1762              : 
    1763              :   // TODO: seems kinda dodgy. Think of better way.
    1764         1358 :   SlicePatternItems &get_items ()
    1765              :   {
    1766         1358 :     rust_assert (items != nullptr);
    1767         1358 :     return *items;
    1768              :   }
    1769              : 
    1770          228 :   NodeId get_node_id () const override { return node_id; }
    1771              : 
    1772            0 :   Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Slice; }
    1773              : 
    1774              : protected:
    1775              :   /* Use covariance to implement clone function as returning this object rather
    1776              :    * than base */
    1777           76 :   SlicePattern *clone_pattern_impl () const override
    1778              :   {
    1779           76 :     return new SlicePattern (*this);
    1780              :   }
    1781              : };
    1782              : 
    1783              : // AST node for alternate patterns
    1784              : // joins together what are technically 'PatternNoTopAlt's
    1785              : class AltPattern : public Pattern
    1786              : {
    1787              :   std::vector<std::unique_ptr<Pattern>> alts;
    1788              :   location_t locus;
    1789              :   NodeId node_id;
    1790              : 
    1791              : public:
    1792              :   std::string as_string () const override;
    1793              : 
    1794          193 :   AltPattern (std::vector<std::unique_ptr<Pattern>> alts, location_t locus)
    1795          193 :     : alts (std::move (alts)), locus (locus),
    1796          193 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
    1797          193 :   {}
    1798              : 
    1799              :   // Copy constructor with vector clone
    1800          194 :   AltPattern (AltPattern const &other) : locus (other.locus)
    1801              :   {
    1802          194 :     node_id = other.node_id;
    1803          194 :     alts.reserve (other.alts.size ());
    1804          597 :     for (const auto &e : other.alts)
    1805          403 :       alts.push_back (e->clone_pattern ());
    1806          194 :   }
    1807              : 
    1808              :   // Overloaded assignment operator to vector clone
    1809              :   AltPattern &operator= (AltPattern const &other)
    1810              :   {
    1811              :     locus = other.locus;
    1812              :     node_id = other.node_id;
    1813              : 
    1814              :     alts.clear ();
    1815              :     alts.reserve (other.alts.size ());
    1816              :     for (const auto &e : other.alts)
    1817              :       alts.push_back (e->clone_pattern ());
    1818              : 
    1819              :     return *this;
    1820              :   }
    1821              : 
    1822              :   // move constructors
    1823              :   AltPattern (AltPattern &&other) = default;
    1824              :   AltPattern &operator= (AltPattern &&other) = default;
    1825              : 
    1826          294 :   location_t get_locus () const override final { return locus; }
    1827              : 
    1828              :   void accept_vis (ASTVisitor &vis) override;
    1829              : 
    1830              :   // TODO: seems kinda dodgy. Think of better way.
    1831         4646 :   std::vector<std::unique_ptr<Pattern>> &get_alts () { return alts; }
    1832              :   const std::vector<std::unique_ptr<Pattern>> &get_alts () const
    1833              :   {
    1834              :     return alts;
    1835              :   }
    1836              : 
    1837          617 :   NodeId get_node_id () const override { return node_id; }
    1838              : 
    1839            0 :   Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Alt; }
    1840              : 
    1841              : protected:
    1842              :   /* Use covariance to implement clone function as returning this object rather
    1843              :    * than base */
    1844          194 :   AltPattern *clone_pattern_impl () const override
    1845              :   {
    1846          194 :     return new AltPattern (*this);
    1847              :   }
    1848              : };
    1849              : 
    1850              : // Moved definition to rust-path.h
    1851              : class Path;
    1852              : 
    1853              : // Forward decls for paths (defined in rust-path.h)
    1854              : class PathInExpression;
    1855              : class QualifiedPathInExpression;
    1856              : 
    1857              : // Replaced with forward decl - defined in rust-macro.h
    1858              : class MacroInvocation;
    1859              : } // namespace AST
    1860              : } // namespace Rust
    1861              : 
    1862              : #endif
        

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.