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_PATH_H
      20  #define RUST_HIR_PATH_H
      21  
      22  #include "rust-hir.h"
      23  
      24  namespace Rust {
      25  namespace HIR {
      26  
      27  // The "identifier" (not generic args) aspect of each path expression segment
      28  class PathIdentSegment
      29  {
      30    std::string segment_name;
      31  
      32    // TODO: should this have location info stored?
      33  
      34    // only allow identifiers, "super", "self", "Self", "crate", or "$crate"
      35  public:
      36    PathIdentSegment (std::string segment_name)
      37      : segment_name (std::move (segment_name))
      38    {}
      39  
      40    /* TODO: insert check in constructor for this? Or is this a semantic error
      41     * best handled then? */
      42  
      43    /* TODO: does this require visitor? pretty sure this isn't polymorphic, but
      44     * not entirely sure */
      45  
      46    // Creates an error PathIdentSegment.
      47    static PathIdentSegment create_error () { return PathIdentSegment (""); }
      48  
      49    // Returns whether PathIdentSegment is in an error state.
      50    bool is_error () const { return segment_name.empty (); }
      51  
      52    std::string as_string () const { return segment_name; }
      53  };
      54  
      55  // A binding of an identifier to a type used in generic arguments in paths
      56  struct GenericArgsBinding
      57  {
      58  private:
      59    Identifier identifier;
      60    std::unique_ptr<Type> type;
      61  
      62    Location locus;
      63  
      64  public:
      65    // Returns whether binding is in an error state.
      66    bool is_error () const
      67    {
      68      return type == nullptr;
      69      // and also identifier is empty, but cheaper computation
      70    }
      71  
      72    // Creates an error state generic args binding.
      73    static GenericArgsBinding create_error ()
      74    {
      75      return GenericArgsBinding ("", nullptr);
      76    }
      77  
      78    // Pointer type for type in constructor to enable polymorphism
      79    GenericArgsBinding (Identifier ident, std::unique_ptr<Type> type_ptr,
      80  		      Location locus = Location ())
      81      : identifier (std::move (ident)), type (std::move (type_ptr)), locus (locus)
      82    {}
      83  
      84    // Copy constructor has to deep copy the type as it is a unique pointer
      85    GenericArgsBinding (GenericArgsBinding const &other)
      86      : identifier (other.identifier), type (other.type->clone_type ()),
      87        locus (other.locus)
      88    {}
      89  
      90    // default destructor
      91    ~GenericArgsBinding () = default;
      92  
      93    // Overload assignment operator to deep copy the pointed-to type
      94    GenericArgsBinding &operator= (GenericArgsBinding const &other)
      95    {
      96      identifier = other.identifier;
      97      type = other.type->clone_type ();
      98      locus = other.locus;
      99      return *this;
     100    }
     101  
     102    // move constructors
     103    GenericArgsBinding (GenericArgsBinding &&other) = default;
     104    GenericArgsBinding &operator= (GenericArgsBinding &&other) = default;
     105  
     106    std::string as_string () const;
     107  
     108    Identifier &get_identifier () { return identifier; }
     109    const Identifier &get_identifier () const { return identifier; }
     110  
     111    std::unique_ptr<Type> &get_type () { return type; }
     112    const std::unique_ptr<Type> &get_type () const { return type; }
     113  
     114    Location get_locus () const { return locus; }
     115  };
     116  
     117  class ConstGenericArg
     118  {
     119    // FIXME: Do we need to disambiguate or no? We should be able to disambiguate
     120    // at name-resolution, hence no need for ambiguities here
     121  
     122  public:
     123    ConstGenericArg (std::unique_ptr<Expr> expression, Location locus)
     124      : expression (std::move (expression)), locus (locus)
     125    {}
     126  
     127    ConstGenericArg (const ConstGenericArg &other) : locus (other.locus)
     128    {
     129      expression = other.expression->clone_expr ();
     130    }
     131  
     132    ConstGenericArg operator= (const ConstGenericArg &other)
     133    {
     134      expression = other.expression->clone_expr ();
     135      locus = other.locus;
     136  
     137      return *this;
     138    }
     139  
     140  private:
     141    std::unique_ptr<Expr> expression;
     142    Location locus;
     143  };
     144  
     145  class GenericArgs
     146  {
     147    std::vector<Lifetime> lifetime_args;
     148    std::vector<std::unique_ptr<Type> > type_args;
     149    std::vector<GenericArgsBinding> binding_args;
     150    std::vector<ConstGenericArg> const_args;
     151    Location locus;
     152  
     153  public:
     154    // Returns true if there are any generic arguments
     155    bool has_generic_args () const
     156    {
     157      return !(lifetime_args.empty () && type_args.empty ()
     158  	     && binding_args.empty ());
     159    }
     160  
     161    GenericArgs (std::vector<Lifetime> lifetime_args,
     162  	       std::vector<std::unique_ptr<Type> > type_args,
     163  	       std::vector<GenericArgsBinding> binding_args,
     164  	       std::vector<ConstGenericArg> const_args, Location locus)
     165      : lifetime_args (std::move (lifetime_args)),
     166        type_args (std::move (type_args)),
     167        binding_args (std::move (binding_args)),
     168        const_args (std::move (const_args)), locus (locus)
     169    {}
     170  
     171    // copy constructor with vector clone
     172    GenericArgs (GenericArgs const &other)
     173      : lifetime_args (other.lifetime_args), binding_args (other.binding_args),
     174        const_args (other.const_args), locus (other.locus)
     175    {
     176      type_args.clear ();
     177      type_args.reserve (other.type_args.size ());
     178  
     179      for (const auto &e : other.type_args)
     180        type_args.push_back (e->clone_type ());
     181    }
     182  
     183    ~GenericArgs () = default;
     184  
     185    // overloaded assignment operator to vector clone
     186    GenericArgs &operator= (GenericArgs const &other)
     187    {
     188      lifetime_args = other.lifetime_args;
     189      binding_args = other.binding_args;
     190      const_args = other.const_args;
     191      locus = other.locus;
     192  
     193      type_args.clear ();
     194      type_args.reserve (other.type_args.size ());
     195      for (const auto &e : other.type_args)
     196        type_args.push_back (e->clone_type ());
     197  
     198      return *this;
     199    }
     200  
     201    // move constructors
     202    GenericArgs (GenericArgs &&other) = default;
     203    GenericArgs &operator= (GenericArgs &&other) = default;
     204  
     205    // Creates an empty GenericArgs (no arguments)
     206    static GenericArgs create_empty (Location locus = Location ())
     207    {
     208      return GenericArgs ({}, {}, {}, {}, locus);
     209    }
     210  
     211    bool is_empty () const
     212    {
     213      return lifetime_args.size () == 0 && type_args.size () == 0
     214  	   && binding_args.size () == 0;
     215    }
     216  
     217    std::string as_string () const;
     218  
     219    std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; }
     220  
     221    std::vector<std::unique_ptr<Type> > &get_type_args () { return type_args; }
     222  
     223    std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }
     224  
     225    std::vector<ConstGenericArg> &get_const_args () { return const_args; }
     226  
     227    Location get_locus () const { return locus; }
     228  };
     229  
     230  /* A segment of a path in expression, including an identifier aspect and maybe
     231   * generic args */
     232  class PathExprSegment
     233  {
     234  private:
     235    Analysis::NodeMapping mappings;
     236    PathIdentSegment segment_name;
     237    GenericArgs generic_args;
     238    Location locus;
     239  
     240  public:
     241    PathExprSegment (Analysis::NodeMapping mappings,
     242  		   PathIdentSegment segment_name, Location locus,
     243  		   GenericArgs generic_args)
     244      : mappings (std::move (mappings)), segment_name (std::move (segment_name)),
     245        generic_args (std::move (generic_args)), locus (locus)
     246    {}
     247  
     248    PathExprSegment (PathExprSegment const &other)
     249      : mappings (other.mappings), segment_name (other.segment_name),
     250        generic_args (other.generic_args), locus (other.locus)
     251    {}
     252  
     253    PathExprSegment &operator= (PathExprSegment const &other)
     254    {
     255      mappings = other.mappings;
     256      segment_name = other.segment_name;
     257      generic_args = other.generic_args;
     258      locus = other.locus;
     259  
     260      return *this;
     261    }
     262  
     263    // move constructors
     264    PathExprSegment (PathExprSegment &&other) = default;
     265    PathExprSegment &operator= (PathExprSegment &&other) = default;
     266  
     267    std::string as_string () const;
     268  
     269    Location get_locus () const { return locus; }
     270  
     271    PathIdentSegment &get_segment () { return segment_name; }
     272    const PathIdentSegment &get_segment () const { return segment_name; }
     273  
     274    GenericArgs &get_generic_args () { return generic_args; }
     275  
     276    const Analysis::NodeMapping &get_mappings () const { return mappings; }
     277  
     278    bool has_generic_args () const { return generic_args.has_generic_args (); }
     279  };
     280  
     281  // HIR node representing a pattern that involves a "path" - abstract base class
     282  class PathPattern : public Pattern
     283  {
     284    std::vector<PathExprSegment> segments;
     285  
     286  protected:
     287    PathPattern (std::vector<PathExprSegment> segments)
     288      : segments (std::move (segments))
     289    {}
     290  
     291    // Returns whether path has segments.
     292    bool has_segments () const { return !segments.empty (); }
     293  
     294    /* Converts path segments to their equivalent SimplePath segments if possible,
     295     * and creates a SimplePath from them. */
     296    AST::SimplePath
     297    convert_to_simple_path (bool with_opening_scope_resolution) const;
     298  
     299  public:
     300    /* Returns whether the path is a single segment (excluding qualified path
     301     * initial as segment). */
     302    bool is_single_segment () const { return segments.size () == 1; }
     303  
     304    std::string as_string () const override;
     305  
     306    void iterate_path_segments (std::function<bool (PathExprSegment &)> cb)
     307    {
     308      for (auto it = segments.begin (); it != segments.end (); it++)
     309        {
     310  	if (!cb (*it))
     311  	  return;
     312        }
     313    }
     314  
     315    size_t get_num_segments () const { return segments.size (); }
     316  
     317    std::vector<PathExprSegment> &get_segments () { return segments; }
     318  
     319    const std::vector<PathExprSegment> &get_segments () const { return segments; }
     320  
     321    PathExprSegment &get_root_seg () { return segments.at (0); }
     322  
     323    PathExprSegment get_final_segment () const { return segments.back (); }
     324  
     325    PatternType get_pattern_type () const override final
     326    {
     327      return PatternType::PATH;
     328    }
     329  };
     330  
     331  /* HIR node representing a path-in-expression pattern (path that allows generic
     332   * arguments) */
     333  class PathInExpression : public PathPattern, public PathExpr
     334  {
     335    bool has_opening_scope_resolution;
     336    Location locus;
     337  
     338  public:
     339    std::string as_string () const override;
     340  
     341    // Constructor
     342    PathInExpression (Analysis::NodeMapping mappings,
     343  		    std::vector<PathExprSegment> path_segments,
     344  		    Location locus = Location (),
     345  		    bool has_opening_scope_resolution = false,
     346  		    std::vector<AST::Attribute> outer_attrs
     347  		    = std::vector<AST::Attribute> ())
     348      : PathPattern (std::move (path_segments)),
     349        PathExpr (std::move (mappings), std::move (outer_attrs)),
     350        has_opening_scope_resolution (has_opening_scope_resolution), locus (locus)
     351    {}
     352  
     353    // Creates an error state path in expression.
     354    static PathInExpression create_error ()
     355    {
     356      return PathInExpression (Analysis::NodeMapping::get_error (),
     357  			     std::vector<PathExprSegment> ());
     358    }
     359  
     360    // Returns whether path in expression is in an error state.
     361    bool is_error () const { return !has_segments (); }
     362  
     363    /* Converts PathInExpression to SimplePath if possible (i.e. no generic
     364     * arguments). Otherwise returns an empty SimplePath. */
     365    AST::SimplePath as_simple_path () const
     366    {
     367      /* delegate to parent class as can't access segments. however,
     368       * QualifiedPathInExpression conversion to simple path wouldn't make sense,
     369       * so the method in the parent class should be protected, not public. Have
     370       * to pass in opening scope resolution as parent class has no access to it.
     371       */
     372      return convert_to_simple_path (has_opening_scope_resolution);
     373    }
     374  
     375    Location get_locus () const override final { return locus; }
     376  
     377    void accept_vis (HIRFullVisitor &vis) override;
     378    void accept_vis (HIRExpressionVisitor &vis) override;
     379    void accept_vis (HIRPatternVisitor &vis) override;
     380  
     381    bool opening_scope_resolution () { return has_opening_scope_resolution; }
     382  
     383    bool is_self () const
     384    {
     385      if (!is_single_segment ())
     386        return false;
     387  
     388      return get_final_segment ().get_segment ().as_string ().compare ("self")
     389  	   == 0;
     390    }
     391  
     392    Analysis::NodeMapping get_pattern_mappings () const override final
     393    {
     394      return get_mappings ();
     395    }
     396  
     397  protected:
     398    /* Use covariance to implement clone function as returning this object rather
     399     * than base */
     400    PathInExpression *clone_pattern_impl () const override
     401    {
     402      return new PathInExpression (*this);
     403    }
     404  
     405    /* Use covariance to implement clone function as returning this object rather
     406     * than base */
     407    PathInExpression *clone_expr_without_block_impl () const override
     408    {
     409      return new PathInExpression (*this);
     410    }
     411  };
     412  
     413  /* Base class for segments used in type paths - not abstract (represents an
     414   * ident-only segment) */
     415  class TypePathSegment
     416  {
     417  public:
     418    enum SegmentType
     419    {
     420      REG,
     421      GENERIC,
     422      FUNCTION
     423    };
     424  
     425  private:
     426    Analysis::NodeMapping mappings;
     427    PathIdentSegment ident_segment;
     428    Location locus;
     429  
     430  protected:
     431    bool has_separating_scope_resolution;
     432    SegmentType type;
     433  
     434    // Clone function implementation - not pure virtual as overrided by subclasses
     435    virtual TypePathSegment *clone_type_path_segment_impl () const
     436    {
     437      return new TypePathSegment (*this);
     438    }
     439  
     440  public:
     441    virtual ~TypePathSegment () {}
     442  
     443    virtual SegmentType get_type () const { return SegmentType::REG; }
     444  
     445    // Unique pointer custom clone function
     446    std::unique_ptr<TypePathSegment> clone_type_path_segment () const
     447    {
     448      return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ());
     449    }
     450  
     451    TypePathSegment (Analysis::NodeMapping mappings,
     452  		   PathIdentSegment ident_segment,
     453  		   bool has_separating_scope_resolution, Location locus)
     454      : mappings (std::move (mappings)),
     455        ident_segment (std::move (ident_segment)), locus (locus),
     456        has_separating_scope_resolution (has_separating_scope_resolution),
     457        type (SegmentType::REG)
     458    {}
     459  
     460    TypePathSegment (Analysis::NodeMapping mappings, std::string segment_name,
     461  		   bool has_separating_scope_resolution, Location locus)
     462      : mappings (std::move (mappings)),
     463        ident_segment (PathIdentSegment (std::move (segment_name))),
     464        locus (locus),
     465        has_separating_scope_resolution (has_separating_scope_resolution),
     466        type (SegmentType::REG)
     467    {}
     468  
     469    virtual std::string as_string () const { return ident_segment.as_string (); }
     470  
     471    /* Returns whether the type path segment is in an error state. May be virtual
     472     * in future. */
     473    bool is_error () const { return ident_segment.is_error (); }
     474  
     475    /* Returns whether segment is identifier only (as opposed to generic args or
     476     * function). Overriden in derived classes with other segments. */
     477    virtual bool is_ident_only () const { return true; }
     478  
     479    Location get_locus () const { return locus; }
     480  
     481    // not pure virtual as class not abstract
     482    virtual void accept_vis (HIRFullVisitor &vis);
     483  
     484    const Analysis::NodeMapping &get_mappings () const { return mappings; }
     485  
     486    const PathIdentSegment &get_ident_segment () const { return ident_segment; }
     487  
     488    bool is_generic_segment () const
     489    {
     490      return get_type () == SegmentType::GENERIC;
     491    }
     492  };
     493  
     494  // Segment used in type path with generic args
     495  class TypePathSegmentGeneric : public TypePathSegment
     496  {
     497    GenericArgs generic_args;
     498  
     499  public:
     500    bool has_generic_args () const { return generic_args.has_generic_args (); }
     501  
     502    bool is_ident_only () const override { return false; }
     503  
     504    // Constructor with PathIdentSegment and GenericArgs
     505    TypePathSegmentGeneric (Analysis::NodeMapping mappings,
     506  			  PathIdentSegment ident_segment,
     507  			  bool has_separating_scope_resolution,
     508  			  GenericArgs generic_args, Location locus)
     509      : TypePathSegment (std::move (mappings), std::move (ident_segment),
     510  		       has_separating_scope_resolution, locus),
     511        generic_args (std::move (generic_args))
     512    {}
     513  
     514    // Constructor from segment name and all args
     515    TypePathSegmentGeneric (Analysis::NodeMapping mappings,
     516  			  std::string segment_name,
     517  			  bool has_separating_scope_resolution,
     518  			  std::vector<Lifetime> lifetime_args,
     519  			  std::vector<std::unique_ptr<Type> > type_args,
     520  			  std::vector<GenericArgsBinding> binding_args,
     521  			  std::vector<ConstGenericArg> const_args,
     522  			  Location locus)
     523      : TypePathSegment (std::move (mappings), std::move (segment_name),
     524  		       has_separating_scope_resolution, locus),
     525        generic_args (
     526  	GenericArgs (std::move (lifetime_args), std::move (type_args),
     527  		     std::move (binding_args), std::move (const_args), locus))
     528    {}
     529  
     530    std::string as_string () const override;
     531  
     532    void accept_vis (HIRFullVisitor &vis) override;
     533  
     534    GenericArgs &get_generic_args () { return generic_args; }
     535  
     536    virtual SegmentType get_type () const override final
     537    {
     538      return SegmentType::GENERIC;
     539    }
     540  
     541  protected:
     542    // Use covariance to override base class method
     543    TypePathSegmentGeneric *clone_type_path_segment_impl () const override
     544    {
     545      return new TypePathSegmentGeneric (*this);
     546    }
     547  };
     548  
     549  // A function as represented in a type path
     550  struct TypePathFunction
     551  {
     552  private:
     553    std::vector<std::unique_ptr<Type> > inputs;
     554    std::unique_ptr<Type> return_type;
     555  
     556  public:
     557    // Returns whether the return type of the function has been specified.
     558    bool has_return_type () const { return return_type != nullptr; }
     559  
     560    // Returns whether the function has inputs.
     561    bool has_inputs () const { return !inputs.empty (); }
     562  
     563    // Constructor
     564    TypePathFunction (std::vector<std::unique_ptr<Type> > inputs,
     565  		    std::unique_ptr<Type> type)
     566      : inputs (std::move (inputs)), return_type (std::move (type))
     567    {}
     568  
     569    // Copy constructor with clone
     570    TypePathFunction (TypePathFunction const &other)
     571    {
     572      return_type = other.has_return_type ()
     573  		    ? other.get_return_type ()->clone_type ()
     574  		    : nullptr;
     575  
     576      inputs.reserve (other.inputs.size ());
     577      for (const auto &e : other.inputs)
     578        inputs.push_back (e->clone_type ());
     579    }
     580  
     581    ~TypePathFunction () = default;
     582  
     583    // Overloaded assignment operator to clone type
     584    TypePathFunction &operator= (TypePathFunction const &other)
     585    {
     586      return_type = other.has_return_type ()
     587  		    ? other.get_return_type ()->clone_type ()
     588  		    : nullptr;
     589  
     590      inputs.reserve (other.inputs.size ());
     591      for (const auto &e : other.inputs)
     592        inputs.push_back (e->clone_type ());
     593  
     594      return *this;
     595    }
     596  
     597    // move constructors
     598    TypePathFunction (TypePathFunction &&other) = default;
     599    TypePathFunction &operator= (TypePathFunction &&other) = default;
     600  
     601    std::string as_string () const;
     602  
     603    const std::vector<std::unique_ptr<Type> > &get_params () const
     604    {
     605      return inputs;
     606    };
     607    std::vector<std::unique_ptr<Type> > &get_params () { return inputs; };
     608  
     609    const std::unique_ptr<Type> &get_return_type () const
     610    {
     611      rust_assert (has_return_type ());
     612      return return_type;
     613    };
     614    std::unique_ptr<Type> &get_return_type ()
     615    {
     616      rust_assert (has_return_type ());
     617      return return_type;
     618    };
     619  };
     620  
     621  // Segment used in type path with a function argument
     622  class TypePathSegmentFunction : public TypePathSegment
     623  {
     624    TypePathFunction function_path;
     625  
     626  public:
     627    // Constructor with PathIdentSegment and TypePathFn
     628    TypePathSegmentFunction (Analysis::NodeMapping mappings,
     629  			   PathIdentSegment ident_segment,
     630  			   bool has_separating_scope_resolution,
     631  			   TypePathFunction function_path, Location locus)
     632      : TypePathSegment (std::move (mappings), std::move (ident_segment),
     633  		       has_separating_scope_resolution, locus),
     634        function_path (std::move (function_path))
     635    {}
     636  
     637    // Constructor with segment name and TypePathFn
     638    TypePathSegmentFunction (Analysis::NodeMapping mappings,
     639  			   std::string segment_name,
     640  			   bool has_separating_scope_resolution,
     641  			   TypePathFunction function_path, Location locus)
     642      : TypePathSegment (std::move (mappings), std::move (segment_name),
     643  		       has_separating_scope_resolution, locus),
     644        function_path (std::move (function_path))
     645    {}
     646  
     647    std::string as_string () const override;
     648  
     649    bool is_ident_only () const override { return false; }
     650  
     651    void accept_vis (HIRFullVisitor &vis) override;
     652  
     653    SegmentType get_type () const override final { return SegmentType::FUNCTION; }
     654  
     655    TypePathFunction &get_function_path () { return function_path; }
     656  
     657  protected:
     658    // Use covariance to override base class method
     659    TypePathSegmentFunction *clone_type_path_segment_impl () const override
     660    {
     661      return new TypePathSegmentFunction (*this);
     662    }
     663  };
     664  
     665  // Path used inside types
     666  class TypePath : public TypeNoBounds
     667  {
     668  public:
     669    bool has_opening_scope_resolution;
     670    std::vector<std::unique_ptr<TypePathSegment> > segments;
     671  
     672  protected:
     673    /* Use covariance to implement clone function as returning this object rather
     674     * than base */
     675    TypePath *clone_type_impl () const override { return new TypePath (*this); }
     676  
     677    /* Use covariance to implement clone function as returning this object rather
     678     * than base */
     679    TypePath *clone_type_no_bounds_impl () const override
     680    {
     681      return new TypePath (*this);
     682    }
     683  
     684  public:
     685    /* Returns whether the TypePath has an opening scope resolution operator (i.e.
     686     * is global path or crate-relative path, not module-relative) */
     687    bool has_opening_scope_resolution_op () const
     688    {
     689      return has_opening_scope_resolution;
     690    }
     691  
     692    // Returns whether the TypePath is in an invalid state.
     693    bool is_error () const { return segments.empty (); }
     694  
     695    // Creates an error state TypePath.
     696    static TypePath create_error ()
     697    {
     698      return TypePath (Analysis::NodeMapping::get_error (),
     699  		     std::vector<std::unique_ptr<TypePathSegment> > (),
     700  		     Location ());
     701    }
     702  
     703    // Constructor
     704    TypePath (Analysis::NodeMapping mappings,
     705  	    std::vector<std::unique_ptr<TypePathSegment> > segments,
     706  	    Location locus, bool has_opening_scope_resolution = false)
     707      : TypeNoBounds (mappings, locus),
     708        has_opening_scope_resolution (has_opening_scope_resolution),
     709        segments (std::move (segments))
     710    {}
     711  
     712    // Copy constructor with vector clone
     713    TypePath (TypePath const &other)
     714      : TypeNoBounds (other.mappings, other.locus),
     715        has_opening_scope_resolution (other.has_opening_scope_resolution)
     716    {
     717      segments.reserve (other.segments.size ());
     718      for (const auto &e : other.segments)
     719        segments.push_back (e->clone_type_path_segment ());
     720    }
     721  
     722    // Overloaded assignment operator with clone
     723    TypePath &operator= (TypePath const &other)
     724    {
     725      has_opening_scope_resolution = other.has_opening_scope_resolution;
     726      locus = other.locus;
     727      mappings = other.mappings;
     728  
     729      segments.reserve (other.segments.size ());
     730      for (const auto &e : other.segments)
     731        segments.push_back (e->clone_type_path_segment ());
     732  
     733      return *this;
     734    }
     735  
     736    // move constructors
     737    TypePath (TypePath &&other) = default;
     738    TypePath &operator= (TypePath &&other) = default;
     739  
     740    std::string as_string () const override;
     741  
     742    /* Converts TypePath to SimplePath if possible (i.e. no generic or function
     743     * arguments). Otherwise returns an empty SimplePath. */
     744    AST::SimplePath as_simple_path () const;
     745  
     746    // Creates a trait bound with a clone of this type path as its only element.
     747    TraitBound *to_trait_bound (bool in_parens) const override;
     748  
     749    void accept_vis (HIRFullVisitor &vis) override;
     750    void accept_vis (HIRTypeVisitor &vis) override;
     751  
     752    size_t get_num_segments () const { return segments.size (); }
     753  
     754    std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
     755    {
     756      return segments;
     757    }
     758  
     759    std::unique_ptr<TypePathSegment> &get_final_segment ()
     760    {
     761      return segments.back ();
     762    }
     763  };
     764  
     765  struct QualifiedPathType
     766  {
     767  private:
     768    std::unique_ptr<Type> type;
     769    std::unique_ptr<TypePath> trait;
     770    Location locus;
     771    Analysis::NodeMapping mappings;
     772  
     773  public:
     774    // Constructor
     775    QualifiedPathType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type,
     776  		     std::unique_ptr<TypePath> trait, Location locus)
     777      : type (std::move (type)), trait (std::move (trait)), locus (locus),
     778        mappings (mappings)
     779    {}
     780  
     781    // Copy constructor uses custom deep copy for Type to preserve polymorphism
     782    QualifiedPathType (QualifiedPathType const &other)
     783      : type (other.type->clone_type ()),
     784        trait (other.has_as_clause () ? std::unique_ptr<HIR::TypePath> (
     785  	       new HIR::TypePath (*other.trait))
     786  				    : nullptr),
     787        locus (other.locus), mappings (other.mappings)
     788    {}
     789  
     790    // default destructor
     791    ~QualifiedPathType () = default;
     792  
     793    // overload assignment operator to use custom clone method
     794    QualifiedPathType &operator= (QualifiedPathType const &other)
     795    {
     796      type = other.type->clone_type ();
     797      locus = other.locus;
     798      mappings = other.mappings;
     799      trait
     800        = other.has_as_clause ()
     801  	  ? std::unique_ptr<HIR::TypePath> (new HIR::TypePath (*other.trait))
     802  	  : nullptr;
     803  
     804      return *this;
     805    }
     806  
     807    // move constructor
     808    QualifiedPathType (QualifiedPathType &&other) = default;
     809    QualifiedPathType &operator= (QualifiedPathType &&other) = default;
     810  
     811    // Returns whether the qualified path type has a rebind as clause.
     812    bool has_as_clause () const { return trait != nullptr; }
     813  
     814    std::string as_string () const;
     815  
     816    Location get_locus () const { return locus; }
     817  
     818    Analysis::NodeMapping get_mappings () const { return mappings; }
     819  
     820    std::unique_ptr<Type> &get_type () { return type; }
     821  
     822    std::unique_ptr<TypePath> &get_trait ()
     823    {
     824      rust_assert (has_as_clause ());
     825      return trait;
     826    }
     827  
     828    bool trait_has_generic_args () const
     829    {
     830      rust_assert (has_as_clause ());
     831      bool is_generic_seg = trait->get_final_segment ()->get_type ()
     832  			  == TypePathSegment::SegmentType::GENERIC;
     833      if (!is_generic_seg)
     834        return false;
     835  
     836      TypePathSegmentGeneric *seg = static_cast<TypePathSegmentGeneric *> (
     837        trait->get_final_segment ().get ());
     838      return seg->has_generic_args ();
     839    }
     840  
     841    GenericArgs &get_trait_generic_args ()
     842    {
     843      rust_assert (trait_has_generic_args ());
     844      TypePathSegmentGeneric *seg = static_cast<TypePathSegmentGeneric *> (
     845        trait->get_final_segment ().get ());
     846      return seg->get_generic_args ();
     847    }
     848  };
     849  
     850  /* HIR node representing a qualified path-in-expression pattern (path that
     851   * allows specifying trait functions) */
     852  class QualifiedPathInExpression : public PathPattern, public PathExpr
     853  {
     854    QualifiedPathType path_type;
     855    Location locus;
     856  
     857  public:
     858    std::string as_string () const override;
     859  
     860    QualifiedPathInExpression (Analysis::NodeMapping mappings,
     861  			     QualifiedPathType qual_path_type,
     862  			     std::vector<PathExprSegment> path_segments,
     863  			     Location locus = Location (),
     864  			     std::vector<AST::Attribute> outer_attrs
     865  			     = std::vector<AST::Attribute> ())
     866      : PathPattern (std::move (path_segments)),
     867        PathExpr (std::move (mappings), std::move (outer_attrs)),
     868        path_type (std::move (qual_path_type)), locus (locus)
     869    {}
     870  
     871    Location get_locus () const override final { return locus; }
     872  
     873    void accept_vis (HIRFullVisitor &vis) override;
     874    void accept_vis (HIRExpressionVisitor &vis) override;
     875    void accept_vis (HIRPatternVisitor &vis) override;
     876  
     877    QualifiedPathType &get_path_type () { return path_type; }
     878  
     879    Location get_locus () { return locus; }
     880  
     881    Analysis::NodeMapping get_pattern_mappings () const override final
     882    {
     883      return get_mappings ();
     884    }
     885  
     886  protected:
     887    /* Use covariance to implement clone function as returning this object rather
     888     * than base */
     889    QualifiedPathInExpression *clone_pattern_impl () const override
     890    {
     891      return new QualifiedPathInExpression (*this);
     892    }
     893  
     894    /* Use covariance to implement clone function as returning this object rather
     895     * than base */
     896    QualifiedPathInExpression *clone_expr_without_block_impl () const override
     897    {
     898      return new QualifiedPathInExpression (*this);
     899    }
     900  };
     901  
     902  /* Represents a qualified path in a type; used for disambiguating trait function
     903   * calls */
     904  class QualifiedPathInType : public TypeNoBounds
     905  {
     906    QualifiedPathType path_type;
     907    std::unique_ptr<TypePathSegment> associated_segment;
     908    std::vector<std::unique_ptr<TypePathSegment> > segments;
     909  
     910  protected:
     911    /* Use covariance to implement clone function as returning this object rather
     912     * than base */
     913    QualifiedPathInType *clone_type_impl () const override
     914    {
     915      return new QualifiedPathInType (*this);
     916    }
     917  
     918    /* Use covariance to implement clone function as returning this object rather
     919     * than base */
     920    QualifiedPathInType *clone_type_no_bounds_impl () const override
     921    {
     922      return new QualifiedPathInType (*this);
     923    }
     924  
     925  public:
     926    QualifiedPathInType (
     927      Analysis::NodeMapping mappings, QualifiedPathType qual_path_type,
     928      std::unique_ptr<TypePathSegment> associated_segment,
     929      std::vector<std::unique_ptr<TypePathSegment> > path_segments,
     930      Location locus = Location ())
     931      : TypeNoBounds (mappings, locus), path_type (std::move (qual_path_type)),
     932        associated_segment (std::move (associated_segment)),
     933        segments (std::move (path_segments))
     934    {}
     935  
     936    /* TODO: maybe make a shortcut constructor that has QualifiedPathType elements
     937     * as params */
     938  
     939    // Copy constructor with vector clone
     940    QualifiedPathInType (QualifiedPathInType const &other)
     941      : TypeNoBounds (other.mappings, other.locus), path_type (other.path_type)
     942    {
     943      segments.reserve (other.segments.size ());
     944      for (const auto &e : other.segments)
     945        segments.push_back (e->clone_type_path_segment ());
     946  
     947      // Untested.
     948      gcc_unreachable ();
     949    }
     950  
     951    // Overloaded assignment operator with vector clone
     952    QualifiedPathInType &operator= (QualifiedPathInType const &other)
     953    {
     954      path_type = other.path_type;
     955      locus = other.locus;
     956      mappings = other.mappings;
     957  
     958      segments.reserve (other.segments.size ());
     959      for (const auto &e : other.segments)
     960        segments.push_back (e->clone_type_path_segment ());
     961  
     962      return *this;
     963    }
     964  
     965    // move constructors
     966    QualifiedPathInType (QualifiedPathInType &&other) = default;
     967    QualifiedPathInType &operator= (QualifiedPathInType &&other) = default;
     968  
     969    std::string as_string () const override;
     970  
     971    void accept_vis (HIRFullVisitor &vis) override;
     972    void accept_vis (HIRTypeVisitor &vis) override;
     973  
     974    QualifiedPathType &get_path_type () { return path_type; }
     975  
     976    std::unique_ptr<TypePathSegment> &get_associated_segment ()
     977    {
     978      return associated_segment;
     979    }
     980  
     981    std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
     982    {
     983      return segments;
     984    }
     985  };
     986  
     987  class SimplePathSegment
     988  {
     989    Analysis::NodeMapping mappings;
     990  
     991  public:
     992    SimplePathSegment (Analysis::NodeMapping mappings) : mappings (mappings) {}
     993  
     994    const Analysis::NodeMapping &get_mappings () const { return mappings; }
     995  };
     996  
     997  class SimplePath
     998  {
     999    std::vector<SimplePathSegment> segments;
    1000    Analysis::NodeMapping mappings;
    1001    Location locus;
    1002  
    1003  public:
    1004    SimplePath (std::vector<SimplePathSegment> segments,
    1005  	      Analysis::NodeMapping mappings, Location locus)
    1006      : segments (std::move (segments)), mappings (mappings), locus (locus)
    1007    {}
    1008  
    1009    static HIR::SimplePath create_empty ()
    1010    {
    1011      return HIR::SimplePath ({}, Analysis::NodeMapping::get_error (),
    1012  			    Location ());
    1013    }
    1014  
    1015    bool is_error () const { return segments.empty (); }
    1016  
    1017    const Analysis::NodeMapping &get_mappings () const { return mappings; }
    1018    const Location &get_locus () const { return locus; }
    1019  };
    1020  
    1021  } // namespace HIR
    1022  } // namespace Rust
    1023  
    1024  #endif