(root)/
gcc-13.2.0/
gcc/
rust/
hir/
tree/
rust-hir-pattern.h
       1  // Copyright (C) 2020-2023 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_HIR_PATTERN_H
      20  #define RUST_HIR_PATTERN_H
      21  
      22  #include "rust-common.h"
      23  #include "rust-hir.h"
      24  
      25  namespace Rust {
      26  namespace HIR {
      27  
      28  // Literal pattern HIR node (comparing to a literal)
      29  class LiteralPattern : public Pattern
      30  {
      31    Literal lit;
      32    Location locus;
      33    Analysis::NodeMapping mappings;
      34  
      35  public:
      36    std::string as_string () const override;
      37  
      38    // Constructor for a literal pattern
      39    LiteralPattern (Analysis::NodeMapping mappings, Literal lit, Location locus)
      40      : lit (std::move (lit)), locus (locus), mappings (mappings)
      41    {}
      42  
      43    LiteralPattern (Analysis::NodeMapping mappings, std::string val,
      44  		  Literal::LitType type, Location locus)
      45      : lit (Literal (std::move (val), type, PrimitiveCoreType::CORETYPE_STR)),
      46        locus (locus), mappings (mappings)
      47    {}
      48  
      49    Location get_locus () const override { return locus; }
      50  
      51    void accept_vis (HIRFullVisitor &vis) override;
      52    void accept_vis (HIRPatternVisitor &vis) override;
      53  
      54    Analysis::NodeMapping get_pattern_mappings () const override final
      55    {
      56      return mappings;
      57    }
      58  
      59    PatternType get_pattern_type () const override final
      60    {
      61      return PatternType::LITERAL;
      62    }
      63  
      64    Literal &get_literal () { return lit; }
      65    const Literal &get_literal () const { return lit; }
      66  
      67  protected:
      68    /* Use covariance to implement clone function as returning this object rather
      69     * than base */
      70    virtual LiteralPattern *clone_pattern_impl () const override
      71    {
      72      return new LiteralPattern (*this);
      73    }
      74  };
      75  
      76  // Identifier pattern HIR node (bind value matched to a variable)
      77  class IdentifierPattern : public Pattern
      78  {
      79    Identifier variable_ident;
      80    bool is_ref;
      81    Mutability mut;
      82    std::unique_ptr<Pattern> to_bind;
      83    Location locus;
      84    Analysis::NodeMapping mappings;
      85  
      86  public:
      87    std::string as_string () const override;
      88  
      89    // Returns whether the IdentifierPattern has a pattern to bind.
      90    bool has_pattern_to_bind () const { return to_bind != nullptr; }
      91  
      92    // Constructor
      93    IdentifierPattern (Analysis::NodeMapping mappings, Identifier ident,
      94  		     Location locus, bool is_ref = false,
      95  		     Mutability mut = Mutability::Imm,
      96  		     std::unique_ptr<Pattern> to_bind = nullptr)
      97      : variable_ident (std::move (ident)), is_ref (is_ref), mut (mut),
      98        to_bind (std::move (to_bind)), locus (locus), mappings (mappings)
      99    {}
     100  
     101    // Copy constructor with clone
     102    IdentifierPattern (IdentifierPattern const &other)
     103      : variable_ident (other.variable_ident), is_ref (other.is_ref),
     104        mut (other.mut), locus (other.locus), mappings (other.mappings)
     105    {
     106      // fix to get prevent null pointer dereference
     107      if (other.to_bind != nullptr)
     108        to_bind = other.to_bind->clone_pattern ();
     109    }
     110  
     111    // Overload assignment operator to use clone
     112    IdentifierPattern &operator= (IdentifierPattern const &other)
     113    {
     114      variable_ident = other.variable_ident;
     115      is_ref = other.is_ref;
     116      mut = other.mut;
     117      locus = other.locus;
     118      mappings = other.mappings;
     119  
     120      // fix to get prevent null pointer dereference
     121      if (other.to_bind != nullptr)
     122        to_bind = other.to_bind->clone_pattern ();
     123  
     124      return *this;
     125    }
     126  
     127    // default move semantics
     128    IdentifierPattern (IdentifierPattern &&other) = default;
     129    IdentifierPattern &operator= (IdentifierPattern &&other) = default;
     130  
     131    Location get_locus () const override { return locus; }
     132  
     133    bool is_mut () const { return mut == Mutability::Mut; }
     134  
     135    void accept_vis (HIRFullVisitor &vis) override;
     136    void accept_vis (HIRPatternVisitor &vis) override;
     137  
     138    Analysis::NodeMapping get_pattern_mappings () const override final
     139    {
     140      return mappings;
     141    }
     142  
     143    Identifier get_identifier () const { return variable_ident; }
     144  
     145    PatternType get_pattern_type () const override final
     146    {
     147      return PatternType::IDENTIFIER;
     148    }
     149  
     150  protected:
     151    /* Use covariance to implement clone function as returning this object rather
     152     * than base */
     153    IdentifierPattern *clone_pattern_impl () const override
     154    {
     155      return new IdentifierPattern (*this);
     156    }
     157  };
     158  
     159  // HIR node for using the '_' wildcard "match any value" pattern
     160  class WildcardPattern : public Pattern
     161  {
     162    Location locus;
     163    Analysis::NodeMapping mappings;
     164  
     165  public:
     166    std::string as_string () const override { return std::string (1, '_'); }
     167  
     168    WildcardPattern (Analysis::NodeMapping mappings, Location locus)
     169      : locus (locus), mappings (mappings)
     170    {}
     171  
     172    Location get_locus () const override { return locus; }
     173  
     174    void accept_vis (HIRFullVisitor &vis) override;
     175    void accept_vis (HIRPatternVisitor &vis) override;
     176  
     177    Analysis::NodeMapping get_pattern_mappings () const override final
     178    {
     179      return mappings;
     180    }
     181  
     182    PatternType get_pattern_type () const override final
     183    {
     184      return PatternType::WILDCARD;
     185    }
     186  
     187  protected:
     188    /* Use covariance to implement clone function as returning this object rather
     189     * than base */
     190    WildcardPattern *clone_pattern_impl () const override
     191    {
     192      return new WildcardPattern (*this);
     193    }
     194  };
     195  
     196  // Base range pattern bound (lower or upper limit) - abstract
     197  class RangePatternBound
     198  {
     199  public:
     200    enum RangePatternBoundType
     201    {
     202      LITERAL,
     203      PATH,
     204      QUALPATH
     205    };
     206  
     207    virtual ~RangePatternBound () {}
     208  
     209    // Unique pointer custom clone function
     210    std::unique_ptr<RangePatternBound> clone_range_pattern_bound () const
     211    {
     212      return std::unique_ptr<RangePatternBound> (
     213        clone_range_pattern_bound_impl ());
     214    }
     215  
     216    virtual std::string as_string () const = 0;
     217  
     218    virtual void accept_vis (HIRFullVisitor &vis) = 0;
     219  
     220    virtual RangePatternBoundType get_bound_type () const = 0;
     221  
     222  protected:
     223    // pure virtual as RangePatternBound is abstract
     224    virtual RangePatternBound *clone_range_pattern_bound_impl () const = 0;
     225  };
     226  
     227  // Literal-based pattern bound
     228  class RangePatternBoundLiteral : public RangePatternBound
     229  {
     230    Literal literal;
     231    /* Can only be a char, byte, int, or float literal - same impl here as
     232     * previously */
     233  
     234    // Minus prefixed to literal (if integer or floating-point)
     235    bool has_minus;
     236  
     237    Location locus;
     238  
     239  public:
     240    // Constructor
     241    RangePatternBoundLiteral (Literal literal, Location locus,
     242  			    bool has_minus = false)
     243      : literal (literal), has_minus (has_minus), locus (locus)
     244    {}
     245  
     246    std::string as_string () const override;
     247  
     248    Location get_locus () const { return locus; }
     249  
     250    Literal get_literal () const { return literal; }
     251  
     252    void accept_vis (HIRFullVisitor &vis) override;
     253  
     254    RangePatternBoundType get_bound_type () const override
     255    {
     256      return RangePatternBoundType::LITERAL;
     257    }
     258  
     259  protected:
     260    /* Use covariance to implement clone function as returning this object rather
     261     * than base */
     262    RangePatternBoundLiteral *clone_range_pattern_bound_impl () const override
     263    {
     264      return new RangePatternBoundLiteral (*this);
     265    }
     266  };
     267  
     268  // Path-based pattern bound
     269  class RangePatternBoundPath : public RangePatternBound
     270  {
     271    PathInExpression path;
     272  
     273    /* TODO: should this be refactored so that PathInExpression is a subclass of
     274     * RangePatternBound? */
     275  
     276  public:
     277    RangePatternBoundPath (PathInExpression path) : path (std::move (path)) {}
     278  
     279    std::string as_string () const override { return path.as_string (); }
     280  
     281    Location get_locus () const { return path.get_locus (); }
     282  
     283    PathInExpression &get_path () { return path; }
     284    const PathInExpression &get_path () const { return path; }
     285  
     286    void accept_vis (HIRFullVisitor &vis) override;
     287  
     288    RangePatternBoundType get_bound_type () const override
     289    {
     290      return RangePatternBoundType::PATH;
     291    }
     292  
     293  protected:
     294    /* Use covariance to implement clone function as returning this object rather
     295     * than base */
     296    RangePatternBoundPath *clone_range_pattern_bound_impl () const override
     297    {
     298      return new RangePatternBoundPath (*this);
     299    }
     300  };
     301  
     302  // Qualified path-based pattern bound
     303  class RangePatternBoundQualPath : public RangePatternBound
     304  {
     305    QualifiedPathInExpression path;
     306  
     307    /* TODO: should this be refactored so that QualifiedPathInExpression is a
     308     * subclass of RangePatternBound? */
     309  
     310  public:
     311    RangePatternBoundQualPath (QualifiedPathInExpression path)
     312      : path (std::move (path))
     313    {}
     314  
     315    std::string as_string () const override { return path.as_string (); }
     316  
     317    Location get_locus () const { return path.get_locus (); }
     318  
     319    void accept_vis (HIRFullVisitor &vis) override;
     320  
     321    QualifiedPathInExpression &get_qualified_path () { return path; }
     322    const QualifiedPathInExpression &get_qualified_path () const { return path; }
     323  
     324    RangePatternBoundType get_bound_type () const override
     325    {
     326      return RangePatternBoundType::QUALPATH;
     327    }
     328  
     329  protected:
     330    /* Use covariance to implement clone function as returning this object rather
     331     * than base */
     332    RangePatternBoundQualPath *clone_range_pattern_bound_impl () const override
     333    {
     334      return new RangePatternBoundQualPath (*this);
     335    }
     336  };
     337  
     338  // HIR node for matching within a certain range (range pattern)
     339  class RangePattern : public Pattern
     340  {
     341    std::unique_ptr<RangePatternBound> lower;
     342    std::unique_ptr<RangePatternBound> upper;
     343  
     344    bool has_ellipsis_syntax;
     345  
     346    /* location only stored to avoid a dereference - lower pattern should give
     347     * correct location so maybe change in future */
     348    Location locus;
     349    Analysis::NodeMapping mappings;
     350  
     351  public:
     352    std::string as_string () const override;
     353  
     354    // Constructor
     355    RangePattern (Analysis::NodeMapping mappings,
     356  		std::unique_ptr<RangePatternBound> lower,
     357  		std::unique_ptr<RangePatternBound> upper, Location locus,
     358  		bool has_ellipsis_syntax = false)
     359      : lower (std::move (lower)), upper (std::move (upper)),
     360        has_ellipsis_syntax (has_ellipsis_syntax), locus (locus),
     361        mappings (mappings)
     362    {}
     363  
     364    // Copy constructor with clone
     365    RangePattern (RangePattern const &other)
     366      : lower (other.lower->clone_range_pattern_bound ()),
     367        upper (other.upper->clone_range_pattern_bound ()),
     368        has_ellipsis_syntax (other.has_ellipsis_syntax), locus (other.locus),
     369        mappings (other.mappings)
     370    {}
     371  
     372    // Overloaded assignment operator to clone
     373    RangePattern &operator= (RangePattern const &other)
     374    {
     375      lower = other.lower->clone_range_pattern_bound ();
     376      upper = other.upper->clone_range_pattern_bound ();
     377      has_ellipsis_syntax = other.has_ellipsis_syntax;
     378      locus = other.locus;
     379      mappings = other.mappings;
     380  
     381      return *this;
     382    }
     383  
     384    // default move semantics
     385    RangePattern (RangePattern &&other) = default;
     386    RangePattern &operator= (RangePattern &&other) = default;
     387  
     388    Location get_locus () const override { return locus; }
     389  
     390    void accept_vis (HIRFullVisitor &vis) override;
     391    void accept_vis (HIRPatternVisitor &vis) override;
     392  
     393    Analysis::NodeMapping get_pattern_mappings () const override final
     394    {
     395      return mappings;
     396    }
     397  
     398    PatternType get_pattern_type () const override final
     399    {
     400      return PatternType::RANGE;
     401    }
     402  
     403    std::unique_ptr<RangePatternBound> &get_lower_bound ()
     404    {
     405      rust_assert (lower != nullptr);
     406      return lower;
     407    }
     408  
     409    std::unique_ptr<RangePatternBound> &get_upper_bound ()
     410    {
     411      rust_assert (upper != nullptr);
     412      return upper;
     413    }
     414  
     415  protected:
     416    /* Use covariance to implement clone function as returning this object rather
     417     * than base */
     418    RangePattern *clone_pattern_impl () const override
     419    {
     420      return new RangePattern (*this);
     421    }
     422  };
     423  
     424  // HIR node for pattern based on dereferencing the pointers given
     425  class ReferencePattern : public Pattern
     426  {
     427    Mutability mut;
     428    std::unique_ptr<Pattern> pattern;
     429    Location locus;
     430    Analysis::NodeMapping mappings;
     431  
     432  public:
     433    std::string as_string () const override;
     434  
     435    ReferencePattern (Analysis::NodeMapping mappings,
     436  		    std::unique_ptr<Pattern> pattern, Mutability reference_mut,
     437  		    Location locus)
     438      : mut (reference_mut), pattern (std::move (pattern)), locus (locus),
     439        mappings (mappings)
     440    {}
     441  
     442    // Copy constructor requires clone
     443    ReferencePattern (ReferencePattern const &other)
     444      : mut (other.mut), pattern (other.pattern->clone_pattern ()),
     445        locus (other.locus), mappings (other.mappings)
     446    {}
     447  
     448    // Overload assignment operator to clone
     449    ReferencePattern &operator= (ReferencePattern const &other)
     450    {
     451      pattern = other.pattern->clone_pattern ();
     452      mut = other.mut;
     453      locus = other.locus;
     454      mappings = other.mappings;
     455  
     456      return *this;
     457    }
     458  
     459    // default move semantics
     460    ReferencePattern (ReferencePattern &&other) = default;
     461    ReferencePattern &operator= (ReferencePattern &&other) = default;
     462  
     463    bool is_mut () const { return mut == Mutability::Mut; }
     464  
     465    void accept_vis (HIRFullVisitor &vis) override;
     466    void accept_vis (HIRPatternVisitor &vis) override;
     467  
     468    Analysis::NodeMapping get_pattern_mappings () const override final
     469    {
     470      return mappings;
     471    }
     472  
     473    Location get_locus () const override final { return locus; }
     474  
     475    PatternType get_pattern_type () const override final
     476    {
     477      return PatternType::REFERENCE;
     478    }
     479  
     480  protected:
     481    /* Use covariance to implement clone function as returning this object rather
     482     * than base */
     483    ReferencePattern *clone_pattern_impl () const override
     484    {
     485      return new ReferencePattern (*this);
     486    }
     487  };
     488  
     489  // Base class for a single field in a struct pattern - abstract
     490  class StructPatternField
     491  {
     492    AST::AttrVec outer_attrs;
     493    Location locus;
     494    Analysis::NodeMapping mappings;
     495  
     496  public:
     497    enum ItemType
     498    {
     499      TUPLE_PAT,
     500      IDENT_PAT,
     501      IDENT
     502    };
     503  
     504    virtual ~StructPatternField () {}
     505  
     506    // Unique pointer custom clone function
     507    std::unique_ptr<StructPatternField> clone_struct_pattern_field () const
     508    {
     509      return std::unique_ptr<StructPatternField> (
     510        clone_struct_pattern_field_impl ());
     511    }
     512  
     513    virtual std::string as_string () const;
     514    virtual void accept_vis (HIRFullVisitor &vis) = 0;
     515    virtual ItemType get_item_type () const = 0;
     516  
     517    Location get_locus () const { return locus; }
     518    Analysis::NodeMapping get_mappings () const { return mappings; };
     519  
     520  protected:
     521    StructPatternField (Analysis::NodeMapping mappings,
     522  		      AST::AttrVec outer_attribs, Location locus)
     523      : outer_attrs (std::move (outer_attribs)), locus (locus),
     524        mappings (mappings)
     525    {}
     526  
     527    // Clone function implementation as pure virtual method
     528    virtual StructPatternField *clone_struct_pattern_field_impl () const = 0;
     529  };
     530  
     531  // Tuple pattern single field in a struct pattern
     532  class StructPatternFieldTuplePat : public StructPatternField
     533  {
     534    TupleIndex index;
     535    std::unique_ptr<Pattern> tuple_pattern;
     536  
     537  public:
     538    StructPatternFieldTuplePat (Analysis::NodeMapping mappings, TupleIndex index,
     539  			      std::unique_ptr<Pattern> tuple_pattern,
     540  			      AST::AttrVec outer_attribs, Location locus)
     541      : StructPatternField (mappings, std::move (outer_attribs), locus),
     542        index (index), tuple_pattern (std::move (tuple_pattern))
     543    {}
     544  
     545    // Copy constructor requires clone
     546    StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other)
     547      : StructPatternField (other), index (other.index),
     548        tuple_pattern (other.tuple_pattern->clone_pattern ())
     549    {}
     550  
     551    // Overload assignment operator to perform clone
     552    StructPatternFieldTuplePat &
     553    operator= (StructPatternFieldTuplePat const &other)
     554    {
     555      StructPatternField::operator= (other);
     556      tuple_pattern = other.tuple_pattern->clone_pattern ();
     557      index = other.index;
     558      // outer_attrs = other.outer_attrs;
     559  
     560      return *this;
     561    }
     562  
     563    // default move semantics
     564    StructPatternFieldTuplePat (StructPatternFieldTuplePat &&other) = default;
     565    StructPatternFieldTuplePat &operator= (StructPatternFieldTuplePat &&other)
     566      = default;
     567  
     568    std::string as_string () const override;
     569  
     570    void accept_vis (HIRFullVisitor &vis) override;
     571  
     572    ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; }
     573  
     574  protected:
     575    /* Use covariance to implement clone function as returning this object rather
     576     * than base */
     577    StructPatternFieldTuplePat *clone_struct_pattern_field_impl () const override
     578    {
     579      return new StructPatternFieldTuplePat (*this);
     580    }
     581  };
     582  
     583  // Identifier pattern single field in a struct pattern
     584  class StructPatternFieldIdentPat : public StructPatternField
     585  {
     586    Identifier ident;
     587    std::unique_ptr<Pattern> ident_pattern;
     588  
     589  public:
     590    StructPatternFieldIdentPat (Analysis::NodeMapping mappings, Identifier ident,
     591  			      std::unique_ptr<Pattern> ident_pattern,
     592  			      AST::AttrVec outer_attrs, Location locus)
     593      : StructPatternField (mappings, std::move (outer_attrs), locus),
     594        ident (std::move (ident)), ident_pattern (std::move (ident_pattern))
     595    {}
     596  
     597    // Copy constructor requires clone
     598    StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other)
     599      : StructPatternField (other), ident (other.ident),
     600        ident_pattern (other.ident_pattern->clone_pattern ())
     601    {}
     602  
     603    // Overload assignment operator to clone
     604    StructPatternFieldIdentPat &
     605    operator= (StructPatternFieldIdentPat const &other)
     606    {
     607      StructPatternField::operator= (other);
     608      ident = other.ident;
     609      ident_pattern = other.ident_pattern->clone_pattern ();
     610      // outer_attrs = other.outer_attrs;
     611  
     612      return *this;
     613    }
     614  
     615    // default move semantics
     616    StructPatternFieldIdentPat (StructPatternFieldIdentPat &&other) = default;
     617    StructPatternFieldIdentPat &operator= (StructPatternFieldIdentPat &&other)
     618      = default;
     619  
     620    std::string as_string () const override;
     621  
     622    void accept_vis (HIRFullVisitor &vis) override;
     623  
     624    ItemType get_item_type () const override final { return ItemType::IDENT_PAT; }
     625  
     626  protected:
     627    /* Use covariance to implement clone function as returning this object rather
     628     * than base */
     629    StructPatternFieldIdentPat *clone_struct_pattern_field_impl () const override
     630    {
     631      return new StructPatternFieldIdentPat (*this);
     632    }
     633  };
     634  
     635  // Identifier only (with no pattern) single field in a struct pattern
     636  class StructPatternFieldIdent : public StructPatternField
     637  {
     638    bool has_ref;
     639    Mutability mut;
     640    Identifier ident;
     641  
     642  public:
     643    StructPatternFieldIdent (Analysis::NodeMapping mappings, Identifier ident,
     644  			   bool is_ref, Mutability mut,
     645  			   AST::AttrVec outer_attrs, Location locus)
     646      : StructPatternField (mappings, std::move (outer_attrs), locus),
     647        has_ref (is_ref), mut (mut), ident (std::move (ident))
     648    {}
     649  
     650    std::string as_string () const override;
     651  
     652    bool is_mut () const { return mut == Mutability::Mut; }
     653  
     654    void accept_vis (HIRFullVisitor &vis) override;
     655  
     656    ItemType get_item_type () const override final { return ItemType::IDENT; }
     657  
     658    Identifier get_identifier () const { return ident; };
     659  
     660  protected:
     661    /* Use covariance to implement clone function as returning this object rather
     662     * than base */
     663    StructPatternFieldIdent *clone_struct_pattern_field_impl () const override
     664    {
     665      return new StructPatternFieldIdent (*this);
     666    }
     667  };
     668  
     669  // Elements of a struct pattern
     670  struct StructPatternElements
     671  {
     672  private:
     673    std::vector<std::unique_ptr<StructPatternField> > fields;
     674  
     675  public:
     676    // Returns whether there are any struct pattern fields
     677    bool has_struct_pattern_fields () const { return !fields.empty (); }
     678  
     679    /* Returns whether the struct pattern elements is entirely empty (no fields,
     680     * no etc). */
     681    bool is_empty () const { return !has_struct_pattern_fields (); }
     682  
     683    // Constructor for StructPatternElements with both (potentially)
     684    StructPatternElements (
     685      std::vector<std::unique_ptr<StructPatternField> > fields)
     686      : fields (std::move (fields))
     687    {}
     688  
     689    // Copy constructor with vector clone
     690    StructPatternElements (StructPatternElements const &other)
     691    {
     692      fields.reserve (other.fields.size ());
     693      for (const auto &e : other.fields)
     694        fields.push_back (e->clone_struct_pattern_field ());
     695    }
     696  
     697    // Overloaded assignment operator with vector clone
     698    StructPatternElements &operator= (StructPatternElements const &other)
     699    {
     700      fields.reserve (other.fields.size ());
     701      for (const auto &e : other.fields)
     702        fields.push_back (e->clone_struct_pattern_field ());
     703  
     704      return *this;
     705    }
     706  
     707    // move constructors
     708    StructPatternElements (StructPatternElements &&other) = default;
     709    StructPatternElements &operator= (StructPatternElements &&other) = default;
     710  
     711    // Creates an empty StructPatternElements
     712    static StructPatternElements create_empty ()
     713    {
     714      return StructPatternElements (
     715        std::vector<std::unique_ptr<StructPatternField> > ());
     716    }
     717  
     718    std::string as_string () const;
     719  
     720    std::vector<std::unique_ptr<StructPatternField> > &
     721    get_struct_pattern_fields ()
     722    {
     723      return fields;
     724    }
     725  };
     726  
     727  // Struct pattern HIR node representation
     728  class StructPattern : public Pattern
     729  {
     730    PathInExpression path;
     731    StructPatternElements elems;
     732    Analysis::NodeMapping mappings;
     733  
     734  public:
     735    std::string as_string () const override;
     736  
     737    StructPattern (Analysis::NodeMapping mappings, PathInExpression struct_path,
     738  		 StructPatternElements elems)
     739      : path (std::move (struct_path)), elems (std::move (elems)),
     740        mappings (mappings)
     741    {}
     742  
     743    bool has_struct_pattern_elems () const { return !elems.is_empty (); }
     744  
     745    Location get_locus () const override { return path.get_locus (); }
     746  
     747    void accept_vis (HIRFullVisitor &vis) override;
     748    void accept_vis (HIRPatternVisitor &vis) override;
     749  
     750    PathInExpression &get_path () { return path; }
     751    StructPatternElements &get_struct_pattern_elems () { return elems; }
     752  
     753    Analysis::NodeMapping get_pattern_mappings () const override final
     754    {
     755      return mappings;
     756    }
     757  
     758    PatternType get_pattern_type () const override final
     759    {
     760      return PatternType::STRUCT;
     761    }
     762  
     763  protected:
     764    /* Use covariance to implement clone function as returning this object rather
     765     * than base */
     766    StructPattern *clone_pattern_impl () const override
     767    {
     768      return new StructPattern (*this);
     769    }
     770  };
     771  
     772  // Base abstract class for patterns used in TupleStructPattern
     773  class TupleStructItems
     774  {
     775  public:
     776    enum ItemType
     777    {
     778      RANGE,
     779      NO_RANGE
     780    };
     781  
     782    virtual ~TupleStructItems () {}
     783  
     784    // TODO: should this store location data?
     785  
     786    // Unique pointer custom clone function
     787    std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const
     788    {
     789      return std::unique_ptr<TupleStructItems> (clone_tuple_struct_items_impl ());
     790    }
     791  
     792    virtual std::string as_string () const = 0;
     793  
     794    virtual void accept_vis (HIRFullVisitor &vis) = 0;
     795  
     796    virtual ItemType get_item_type () const = 0;
     797  
     798  protected:
     799    // pure virtual clone implementation
     800    virtual TupleStructItems *clone_tuple_struct_items_impl () const = 0;
     801  };
     802  
     803  // Class for non-ranged tuple struct pattern patterns
     804  class TupleStructItemsNoRange : public TupleStructItems
     805  {
     806    std::vector<std::unique_ptr<Pattern> > patterns;
     807  
     808  public:
     809    TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern> > patterns)
     810      : patterns (std::move (patterns))
     811    {}
     812  
     813    // Copy constructor with vector clone
     814    TupleStructItemsNoRange (TupleStructItemsNoRange const &other)
     815    {
     816      patterns.reserve (other.patterns.size ());
     817      for (const auto &e : other.patterns)
     818        patterns.push_back (e->clone_pattern ());
     819    }
     820  
     821    // Overloaded assignment operator with vector clone
     822    TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other)
     823    {
     824      patterns.reserve (other.patterns.size ());
     825      for (const auto &e : other.patterns)
     826        patterns.push_back (e->clone_pattern ());
     827  
     828      return *this;
     829    }
     830  
     831    // move constructors
     832    TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default;
     833    TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other)
     834      = default;
     835  
     836    std::string as_string () const override;
     837  
     838    void accept_vis (HIRFullVisitor &vis) override;
     839  
     840    std::vector<std::unique_ptr<Pattern> > &get_patterns () { return patterns; }
     841    const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
     842    {
     843      return patterns;
     844    }
     845  
     846    ItemType get_item_type () const override final { return ItemType::NO_RANGE; }
     847  
     848  protected:
     849    /* Use covariance to implement clone function as returning this object rather
     850     * than base */
     851    TupleStructItemsNoRange *clone_tuple_struct_items_impl () const override
     852    {
     853      return new TupleStructItemsNoRange (*this);
     854    }
     855  };
     856  
     857  // Class for ranged tuple struct pattern patterns
     858  class TupleStructItemsRange : public TupleStructItems
     859  {
     860    std::vector<std::unique_ptr<Pattern> > lower_patterns;
     861    std::vector<std::unique_ptr<Pattern> > upper_patterns;
     862  
     863  public:
     864    TupleStructItemsRange (std::vector<std::unique_ptr<Pattern> > lower_patterns,
     865  			 std::vector<std::unique_ptr<Pattern> > upper_patterns)
     866      : lower_patterns (std::move (lower_patterns)),
     867        upper_patterns (std::move (upper_patterns))
     868    {}
     869  
     870    // Copy constructor with vector clone
     871    TupleStructItemsRange (TupleStructItemsRange const &other)
     872    {
     873      lower_patterns.reserve (other.lower_patterns.size ());
     874      for (const auto &e : other.lower_patterns)
     875        lower_patterns.push_back (e->clone_pattern ());
     876  
     877      upper_patterns.reserve (other.upper_patterns.size ());
     878      for (const auto &e : other.upper_patterns)
     879        upper_patterns.push_back (e->clone_pattern ());
     880    }
     881  
     882    // Overloaded assignment operator to clone
     883    TupleStructItemsRange &operator= (TupleStructItemsRange const &other)
     884    {
     885      lower_patterns.reserve (other.lower_patterns.size ());
     886      for (const auto &e : other.lower_patterns)
     887        lower_patterns.push_back (e->clone_pattern ());
     888  
     889      upper_patterns.reserve (other.upper_patterns.size ());
     890      for (const auto &e : other.upper_patterns)
     891        upper_patterns.push_back (e->clone_pattern ());
     892  
     893      return *this;
     894    }
     895  
     896    // move constructors
     897    TupleStructItemsRange (TupleStructItemsRange &&other) = default;
     898    TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default;
     899  
     900    std::string as_string () const override;
     901  
     902    void accept_vis (HIRFullVisitor &vis) override;
     903  
     904    std::vector<std::unique_ptr<Pattern> > &get_lower_patterns ()
     905    {
     906      return lower_patterns;
     907    }
     908    const std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () const
     909    {
     910      return lower_patterns;
     911    }
     912  
     913    // TODO: seems kinda dodgy. Think of better way.
     914    std::vector<std::unique_ptr<Pattern> > &get_upper_patterns ()
     915    {
     916      return upper_patterns;
     917    }
     918    const std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () const
     919    {
     920      return upper_patterns;
     921    }
     922  
     923    ItemType get_item_type () const override final { return ItemType::RANGE; }
     924  
     925  protected:
     926    /* Use covariance to implement clone function as returning this object rather
     927     * than base */
     928    TupleStructItemsRange *clone_tuple_struct_items_impl () const override
     929    {
     930      return new TupleStructItemsRange (*this);
     931    }
     932  };
     933  
     934  // HIR node representing a tuple struct pattern
     935  class TupleStructPattern : public Pattern
     936  {
     937    PathInExpression path;
     938    std::unique_ptr<TupleStructItems> items;
     939    Analysis::NodeMapping mappings;
     940  
     941    /* TOOD: should this store location data? current accessor uses path location
     942     * data */
     943  
     944  public:
     945    std::string as_string () const override;
     946  
     947    TupleStructPattern (Analysis::NodeMapping mappings,
     948  		      PathInExpression tuple_struct_path,
     949  		      std::unique_ptr<TupleStructItems> items)
     950      : path (std::move (tuple_struct_path)), items (std::move (items)),
     951        mappings (mappings)
     952    {}
     953  
     954    // Copy constructor required to clone
     955    TupleStructPattern (TupleStructPattern const &other)
     956      : path (other.path), items (other.items->clone_tuple_struct_items ()),
     957        mappings (other.mappings)
     958    {}
     959  
     960    // Operator overload assignment operator to clone
     961    TupleStructPattern &operator= (TupleStructPattern const &other)
     962    {
     963      path = other.path;
     964      items = other.items->clone_tuple_struct_items ();
     965      mappings = other.mappings;
     966  
     967      return *this;
     968    }
     969  
     970    // move constructors
     971    TupleStructPattern (TupleStructPattern &&other) = default;
     972    TupleStructPattern &operator= (TupleStructPattern &&other) = default;
     973  
     974    Location get_locus () const override { return path.get_locus (); }
     975  
     976    void accept_vis (HIRFullVisitor &vis) override;
     977    void accept_vis (HIRPatternVisitor &vis) override;
     978  
     979    PathInExpression &get_path () { return path; }
     980  
     981    std::unique_ptr<TupleStructItems> &get_items () { return items; }
     982  
     983    Analysis::NodeMapping get_pattern_mappings () const override final
     984    {
     985      return mappings;
     986    }
     987  
     988    PatternType get_pattern_type () const override final
     989    {
     990      return PatternType::TUPLE_STRUCT;
     991    }
     992  
     993  protected:
     994    /* Use covariance to implement clone function as returning this object rather
     995     * than base */
     996    TupleStructPattern *clone_pattern_impl () const override
     997    {
     998      return new TupleStructPattern (*this);
     999    }
    1000  };
    1001  
    1002  // Base abstract class representing TuplePattern patterns
    1003  class TuplePatternItems
    1004  {
    1005  public:
    1006    enum TuplePatternItemType
    1007    {
    1008      MULTIPLE,
    1009      RANGED,
    1010    };
    1011  
    1012    virtual ~TuplePatternItems () {}
    1013  
    1014    // TODO: should this store location data?
    1015  
    1016    // Unique pointer custom clone function
    1017    std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const
    1018    {
    1019      return std::unique_ptr<TuplePatternItems> (
    1020        clone_tuple_pattern_items_impl ());
    1021    }
    1022  
    1023    virtual std::string as_string () const = 0;
    1024  
    1025    virtual void accept_vis (HIRFullVisitor &vis) = 0;
    1026  
    1027    virtual TuplePatternItemType get_pattern_type () const = 0;
    1028  
    1029  protected:
    1030    // pure virtual clone implementation
    1031    virtual TuplePatternItems *clone_tuple_pattern_items_impl () const = 0;
    1032  };
    1033  
    1034  // Class representing TuplePattern patterns where there are multiple patterns
    1035  class TuplePatternItemsMultiple : public TuplePatternItems
    1036  {
    1037    std::vector<std::unique_ptr<Pattern> > patterns;
    1038  
    1039  public:
    1040    TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern> > patterns)
    1041      : patterns (std::move (patterns))
    1042    {}
    1043  
    1044    // Copy constructor with vector clone
    1045    TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other)
    1046    {
    1047      patterns.reserve (other.patterns.size ());
    1048      for (const auto &e : other.patterns)
    1049        patterns.push_back (e->clone_pattern ());
    1050    }
    1051  
    1052    // Overloaded assignment operator to vector clone
    1053    TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other)
    1054    {
    1055      patterns.reserve (other.patterns.size ());
    1056      for (const auto &e : other.patterns)
    1057        patterns.push_back (e->clone_pattern ());
    1058  
    1059      return *this;
    1060    }
    1061  
    1062    // move constructors
    1063    TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default;
    1064    TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other)
    1065      = default;
    1066  
    1067    std::string as_string () const override;
    1068  
    1069    void accept_vis (HIRFullVisitor &vis) override;
    1070  
    1071    TuplePatternItemType get_pattern_type () const override
    1072    {
    1073      return TuplePatternItemType::MULTIPLE;
    1074    }
    1075  
    1076    std::vector<std::unique_ptr<Pattern> > &get_patterns () { return patterns; }
    1077    const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
    1078    {
    1079      return patterns;
    1080    }
    1081  
    1082  protected:
    1083    /* Use covariance to implement clone function as returning this object rather
    1084     * than base */
    1085    TuplePatternItemsMultiple *clone_tuple_pattern_items_impl () const override
    1086    {
    1087      return new TuplePatternItemsMultiple (*this);
    1088    }
    1089  };
    1090  
    1091  // Class representing TuplePattern patterns where there are a range of patterns
    1092  class TuplePatternItemsRanged : public TuplePatternItems
    1093  {
    1094    std::vector<std::unique_ptr<Pattern> > lower_patterns;
    1095    std::vector<std::unique_ptr<Pattern> > upper_patterns;
    1096  
    1097  public:
    1098    TuplePatternItemsRanged (
    1099      std::vector<std::unique_ptr<Pattern> > lower_patterns,
    1100      std::vector<std::unique_ptr<Pattern> > upper_patterns)
    1101      : lower_patterns (std::move (lower_patterns)),
    1102        upper_patterns (std::move (upper_patterns))
    1103    {}
    1104  
    1105    // Copy constructor with vector clone
    1106    TuplePatternItemsRanged (TuplePatternItemsRanged const &other)
    1107    {
    1108      lower_patterns.reserve (other.lower_patterns.size ());
    1109      for (const auto &e : other.lower_patterns)
    1110        lower_patterns.push_back (e->clone_pattern ());
    1111  
    1112      upper_patterns.reserve (other.upper_patterns.size ());
    1113      for (const auto &e : other.upper_patterns)
    1114        upper_patterns.push_back (e->clone_pattern ());
    1115    }
    1116  
    1117    // Overloaded assignment operator to clone
    1118    TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other)
    1119    {
    1120      lower_patterns.reserve (other.lower_patterns.size ());
    1121      for (const auto &e : other.lower_patterns)
    1122        lower_patterns.push_back (e->clone_pattern ());
    1123  
    1124      upper_patterns.reserve (other.upper_patterns.size ());
    1125      for (const auto &e : other.upper_patterns)
    1126        upper_patterns.push_back (e->clone_pattern ());
    1127  
    1128      return *this;
    1129    }
    1130  
    1131    // move constructors
    1132    TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default;
    1133    TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other)
    1134      = default;
    1135  
    1136    std::string as_string () const override;
    1137  
    1138    void accept_vis (HIRFullVisitor &vis) override;
    1139  
    1140    TuplePatternItemType get_pattern_type () const override
    1141    {
    1142      return TuplePatternItemType::RANGED;
    1143    }
    1144  
    1145    std::vector<std::unique_ptr<Pattern> > &get_lower_patterns ()
    1146    {
    1147      return lower_patterns;
    1148    }
    1149    const std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () const
    1150    {
    1151      return lower_patterns;
    1152    }
    1153  
    1154    std::vector<std::unique_ptr<Pattern> > &get_upper_patterns ()
    1155    {
    1156      return upper_patterns;
    1157    }
    1158    const std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () const
    1159    {
    1160      return upper_patterns;
    1161    }
    1162  
    1163  protected:
    1164    /* Use covariance to implement clone function as returning this object rather
    1165     * than base */
    1166    TuplePatternItemsRanged *clone_tuple_pattern_items_impl () const override
    1167    {
    1168      return new TuplePatternItemsRanged (*this);
    1169    }
    1170  };
    1171  
    1172  // HIR node representing a tuple pattern
    1173  class TuplePattern : public Pattern
    1174  {
    1175    std::unique_ptr<TuplePatternItems> items;
    1176    Location locus;
    1177    Analysis::NodeMapping mappings;
    1178  
    1179  public:
    1180    std::string as_string () const override;
    1181  
    1182    // Returns true if the tuple pattern has items
    1183    bool has_tuple_pattern_items () const { return items != nullptr; }
    1184  
    1185    TuplePattern (Analysis::NodeMapping mappings,
    1186  		std::unique_ptr<TuplePatternItems> items, Location locus)
    1187      : items (std::move (items)), locus (locus), mappings (mappings)
    1188    {}
    1189  
    1190    // Copy constructor requires clone
    1191    TuplePattern (TuplePattern const &other)
    1192      : items (other.items->clone_tuple_pattern_items ()), locus (other.locus),
    1193        mappings (other.mappings)
    1194    {}
    1195  
    1196    // Overload assignment operator to clone
    1197    TuplePattern &operator= (TuplePattern const &other)
    1198    {
    1199      items = other.items->clone_tuple_pattern_items ();
    1200      locus = other.locus;
    1201      mappings = other.mappings;
    1202  
    1203      return *this;
    1204    }
    1205  
    1206    Location get_locus () const override { return locus; }
    1207  
    1208    void accept_vis (HIRFullVisitor &vis) override;
    1209    void accept_vis (HIRPatternVisitor &vis) override;
    1210  
    1211    Analysis::NodeMapping get_pattern_mappings () const override final
    1212    {
    1213      return mappings;
    1214    }
    1215  
    1216    PatternType get_pattern_type () const override final
    1217    {
    1218      return PatternType::TUPLE;
    1219    }
    1220  
    1221    std::unique_ptr<TuplePatternItems> &get_items () { return items; }
    1222    const std::unique_ptr<TuplePatternItems> &get_items () const { return items; }
    1223  
    1224  protected:
    1225    /* Use covariance to implement clone function as returning this object rather
    1226     * than base */
    1227    TuplePattern *clone_pattern_impl () const override
    1228    {
    1229      return new TuplePattern (*this);
    1230    }
    1231  };
    1232  
    1233  // HIR node representing patterns that can match slices and arrays
    1234  class SlicePattern : public Pattern
    1235  {
    1236    std::vector<std::unique_ptr<Pattern> > items;
    1237    Location locus;
    1238    Analysis::NodeMapping mappings;
    1239  
    1240  public:
    1241    std::string as_string () const override;
    1242  
    1243    SlicePattern (Analysis::NodeMapping mappings,
    1244  		std::vector<std::unique_ptr<Pattern> > items, Location locus)
    1245      : items (std::move (items)), locus (locus), mappings (mappings)
    1246    {}
    1247  
    1248    // Copy constructor with vector clone
    1249    SlicePattern (SlicePattern const &other)
    1250      : locus (other.locus), mappings (other.mappings)
    1251    {
    1252      items.reserve (other.items.size ());
    1253      for (const auto &e : other.items)
    1254        items.push_back (e->clone_pattern ());
    1255    }
    1256  
    1257    // Overloaded assignment operator to vector clone
    1258    SlicePattern &operator= (SlicePattern const &other)
    1259    {
    1260      locus = other.locus;
    1261      mappings = other.mappings;
    1262  
    1263      items.reserve (other.items.size ());
    1264      for (const auto &e : other.items)
    1265        items.push_back (e->clone_pattern ());
    1266  
    1267      return *this;
    1268    }
    1269  
    1270    // move constructors
    1271    SlicePattern (SlicePattern &&other) = default;
    1272    SlicePattern &operator= (SlicePattern &&other) = default;
    1273  
    1274    Location get_locus () const override { return locus; }
    1275  
    1276    void accept_vis (HIRFullVisitor &vis) override;
    1277    void accept_vis (HIRPatternVisitor &vis) override;
    1278  
    1279    Analysis::NodeMapping get_pattern_mappings () const override final
    1280    {
    1281      return mappings;
    1282    }
    1283  
    1284    PatternType get_pattern_type () const override final
    1285    {
    1286      return PatternType::SLICE;
    1287    }
    1288  
    1289  protected:
    1290    /* Use covariance to implement clone function as returning this object rather
    1291     * than base */
    1292    SlicePattern *clone_pattern_impl () const override
    1293    {
    1294      return new SlicePattern (*this);
    1295    }
    1296  };
    1297  
    1298  // Moved definition to rust-path.h
    1299  class PathPattern;
    1300  
    1301  // Forward decls for paths (defined in rust-path.h)
    1302  class PathInExpression;
    1303  class QualifiedPathInExpression;
    1304  
    1305  } // namespace HIR
    1306  } // namespace Rust
    1307  
    1308  #endif