(root)/
gcc-13.2.0/
gcc/
rust/
ast/
rust-path.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_AST_PATH_H
      20  #define RUST_AST_PATH_H
      21  /* "Path" (identifier within namespaces, essentially) handling. Required include
      22   * for virtually all AST-related functionality. */
      23  
      24  #include "rust-ast.h"
      25  #include "system.h"
      26  
      27  namespace Rust {
      28  namespace AST {
      29  
      30  // The "identifier" (not generic args) aspect of each path expression segment
      31  class PathIdentSegment
      32  {
      33    std::string segment_name;
      34    Location locus;
      35  
      36    // only allow identifiers, "super", "self", "Self", "crate", or "$crate"
      37  public:
      38    PathIdentSegment (std::string segment_name, Location locus)
      39      : segment_name (std::move (segment_name)), locus (locus)
      40    {}
      41  
      42    // Creates an error PathIdentSegment.
      43    static PathIdentSegment create_error ()
      44    {
      45      return PathIdentSegment ("", Location ());
      46    }
      47  
      48    // Returns whether PathIdentSegment is in an error state.
      49    bool is_error () const { return segment_name.empty (); }
      50  
      51    std::string as_string () const { return segment_name; }
      52  
      53    Location get_locus () const { return locus; }
      54  
      55    bool is_super_segment () const { return as_string ().compare ("super") == 0; }
      56    bool is_crate_segment () const { return as_string ().compare ("crate") == 0; }
      57    bool is_lower_self () const { return as_string ().compare ("self") == 0; }
      58    bool is_big_self () const { return as_string ().compare ("Self") == 0; }
      59  };
      60  
      61  // A binding of an identifier to a type used in generic arguments in paths
      62  struct GenericArgsBinding
      63  {
      64  private:
      65    Identifier identifier;
      66    std::unique_ptr<Type> type;
      67    Location locus;
      68  
      69  public:
      70    // Returns whether binding is in an error state.
      71    bool is_error () const
      72    {
      73      return type == nullptr;
      74      // and also identifier is empty, but cheaper computation
      75    }
      76  
      77    // Creates an error state generic args binding.
      78    static GenericArgsBinding create_error ()
      79    {
      80      return GenericArgsBinding ("", nullptr);
      81    }
      82  
      83    // Pointer type for type in constructor to enable polymorphism
      84    GenericArgsBinding (Identifier ident, std::unique_ptr<Type> type_ptr,
      85  		      Location locus = Location ())
      86      : identifier (std::move (ident)), type (std::move (type_ptr)), locus (locus)
      87    {}
      88  
      89    // Copy constructor has to deep copy the type as it is a unique pointer
      90    GenericArgsBinding (GenericArgsBinding const &other)
      91      : identifier (other.identifier), locus (other.locus)
      92    {
      93      // guard to protect from null pointer dereference
      94      if (other.type != nullptr)
      95        type = other.type->clone_type ();
      96    }
      97  
      98    // default destructor
      99    ~GenericArgsBinding () = default;
     100  
     101    // Overload assignment operator to deep copy the pointed-to type
     102    GenericArgsBinding &operator= (GenericArgsBinding const &other)
     103    {
     104      identifier = other.identifier;
     105      locus = other.locus;
     106  
     107      // guard to protect from null pointer dereference
     108      if (other.type != nullptr)
     109        type = other.type->clone_type ();
     110      else
     111        type = nullptr;
     112  
     113      return *this;
     114    }
     115  
     116    // move constructors
     117    GenericArgsBinding (GenericArgsBinding &&other) = default;
     118    GenericArgsBinding &operator= (GenericArgsBinding &&other) = default;
     119  
     120    std::string as_string () const;
     121  
     122    // TODO: is this better? Or is a "vis_pattern" better?
     123    std::unique_ptr<Type> &get_type ()
     124    {
     125      rust_assert (type != nullptr);
     126      return type;
     127    }
     128  
     129    Location get_locus () const { return locus; }
     130  
     131    Identifier get_identifier () const { return identifier; }
     132  };
     133  
     134  /* Class representing a const generic application */
     135  class GenericArg
     136  {
     137  public:
     138    /**
     139     * const generic arguments cannot always be differentiated with generic type
     140     * arguments during parsing, e.g:
     141     * ```rust
     142     * let a: Foo<N>;
     143     * ```
     144     *
     145     * Is N a type? A constant defined elsewhere? The parser cannot know, and must
     146     * not draw any conclusions. We must wait until later passes of the compiler
     147     * to decide whether this refers to a constant item or a type.
     148     *
     149     * On the other hand, simple expressions like literals or block expressions
     150     * will always be constant expressions: There is no ambiguity at all.
     151     */
     152    enum class Kind
     153    {
     154      Error,
     155      Const,  // A const value
     156      Type,   // A type argument (not discernable during parsing)
     157      Either, // Either a type or a const value, cleared up during resolving
     158    };
     159  
     160    static GenericArg create_error ()
     161    {
     162      return GenericArg (nullptr, nullptr, "", Kind::Error, Location ());
     163    }
     164  
     165    static GenericArg create_const (std::unique_ptr<Expr> expression)
     166    {
     167      auto locus = expression->get_locus ();
     168      return GenericArg (std::move (expression), nullptr, "", Kind::Const, locus);
     169    }
     170  
     171    static GenericArg create_type (std::unique_ptr<Type> type)
     172    {
     173      auto locus = type->get_locus ();
     174      return GenericArg (nullptr, std::move (type), "", Kind::Type, locus);
     175    }
     176  
     177    static GenericArg create_ambiguous (Identifier path, Location locus)
     178    {
     179      return GenericArg (nullptr, nullptr, std::move (path), Kind::Either, locus);
     180    }
     181  
     182    GenericArg (const GenericArg &other)
     183      : path (other.path), kind (other.kind), locus (other.locus)
     184    {
     185      if (other.expression)
     186        expression = other.expression->clone_expr ();
     187      if (other.type)
     188        type = other.type->clone_type ();
     189    }
     190  
     191    GenericArg operator= (const GenericArg &other)
     192    {
     193      kind = other.kind;
     194      path = other.path;
     195      locus = other.locus;
     196  
     197      if (other.expression)
     198        expression = other.expression->clone_expr ();
     199      if (other.type)
     200        type = other.type->clone_type ();
     201  
     202      return *this;
     203    }
     204  
     205    bool is_error () const { return kind == Kind::Error; }
     206  
     207    Kind get_kind () const { return kind; }
     208    const Location &get_locus () const { return locus; }
     209  
     210    void accept_vis (AST::ASTVisitor &visitor)
     211    {
     212      switch (get_kind ())
     213        {
     214        case Kind::Const:
     215  	get_expression ()->accept_vis (visitor);
     216  	break;
     217        case Kind::Type:
     218  	get_type ()->accept_vis (visitor);
     219  	break;
     220        case Kind::Either:
     221  	break;
     222        case Kind::Error:
     223  	gcc_unreachable ();
     224        }
     225    }
     226  
     227    std::unique_ptr<Expr> &get_expression ()
     228    {
     229      rust_assert (kind == Kind::Const);
     230  
     231      return expression;
     232    }
     233  
     234    std::unique_ptr<Type> &get_type ()
     235    {
     236      rust_assert (kind == Kind::Type);
     237  
     238      return type;
     239    }
     240  
     241    const std::string &get_path () const
     242    {
     243      rust_assert (kind == Kind::Either);
     244  
     245      return path;
     246    }
     247  
     248    std::string as_string () const
     249    {
     250      switch (get_kind ())
     251        {
     252        case Kind::Error:
     253  	gcc_unreachable ();
     254        case Kind::Either:
     255  	return "Ambiguous: " + path;
     256        case Kind::Const:
     257  	return "Const: { " + expression->as_string () + " }";
     258        case Kind::Type:
     259  	return "Type: " + type->as_string ();
     260        }
     261  
     262      return "";
     263    }
     264  
     265    /**
     266     * Disambiguate an ambiguous generic argument to a const generic argument,
     267     * unequivocally
     268     */
     269    GenericArg disambiguate_to_const () const;
     270  
     271    /**
     272     * Disambiguate an ambiguous generic argument to a type argument,
     273     * unequivocally
     274     */
     275    GenericArg disambiguate_to_type () const;
     276  
     277  private:
     278    GenericArg (std::unique_ptr<Expr> expression, std::unique_ptr<Type> type,
     279  	      Identifier path, Kind kind, Location locus)
     280      : expression (std::move (expression)), type (std::move (type)),
     281        path (std::move (path)), kind (kind), locus (locus)
     282    {}
     283  
     284    /**
     285     * Expression associated with a `Clear` const generic application
     286     * A null pointer here is allowed in the case that the const argument is
     287     * ambiguous.
     288     */
     289    std::unique_ptr<Expr> expression;
     290  
     291    /**
     292     * If the argument ends up being a type argument instead. A null pointer will
     293     * be present here until the resolving phase.
     294     */
     295    std::unique_ptr<Type> type;
     296  
     297    /**
     298     * Optional path which cannot be differentiated between a constant item and
     299     * a type. Only used for ambiguous const generic arguments, otherwise
     300     * empty.
     301     */
     302    Identifier path;
     303  
     304    /* Which kind of const generic application are we dealing with */
     305    Kind kind;
     306  
     307    Location locus;
     308  };
     309  
     310  /**
     311   * Representation of const generic parameters
     312   */
     313  class ConstGenericParam : public GenericParam
     314  {
     315    /* Name of the parameter */
     316    Identifier name;
     317  
     318    /* Mandatory type of the const parameter - a null pointer is an error */
     319    std::unique_ptr<AST::Type> type;
     320  
     321    /**
     322     * Default value for the const generic parameter
     323     */
     324    GenericArg default_value;
     325  
     326    Attribute outer_attr;
     327    Location locus;
     328  
     329  public:
     330    ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type,
     331  		     GenericArg default_value, Attribute outer_attr,
     332  		     Location locus)
     333      : name (name), type (std::move (type)),
     334        default_value (std::move (default_value)), outer_attr (outer_attr),
     335        locus (locus)
     336    {}
     337  
     338    ConstGenericParam (const ConstGenericParam &other)
     339      : GenericParam (), name (other.name), type (other.type->clone_type ()),
     340        default_value (other.default_value), outer_attr (other.outer_attr),
     341        locus (other.locus)
     342    {}
     343  
     344    bool has_type () const { return type != nullptr; }
     345    bool has_default_value () const { return !default_value.is_error (); }
     346  
     347    const Identifier &get_name () const { return name; }
     348  
     349    std::unique_ptr<AST::Type> &get_type ()
     350    {
     351      rust_assert (has_type ());
     352  
     353      return type;
     354    }
     355  
     356    GenericArg &get_default_value ()
     357    {
     358      rust_assert (has_default_value ());
     359  
     360      return default_value;
     361    }
     362  
     363    const GenericArg &get_default_value () const
     364    {
     365      rust_assert (has_default_value ());
     366  
     367      return default_value;
     368    }
     369  
     370    std::string as_string () const override;
     371  
     372    void accept_vis (ASTVisitor &vis) override;
     373  
     374    Location get_locus () const override final { return locus; }
     375  
     376    Kind get_kind () const override final { return Kind::Const; }
     377  
     378  protected:
     379    /* Use covariance to implement clone function as returning this object rather
     380     * than base */
     381    ConstGenericParam *clone_generic_param_impl () const override
     382    {
     383      return new ConstGenericParam (*this);
     384    }
     385  };
     386  
     387  // Generic arguments allowed in each path expression segment - inline?
     388  struct GenericArgs
     389  {
     390    std::vector<Lifetime> lifetime_args;
     391    std::vector<GenericArg> generic_args;
     392    std::vector<GenericArgsBinding> binding_args;
     393    Location locus;
     394  
     395  public:
     396    // Returns true if there are any generic arguments
     397    bool has_generic_args () const
     398    {
     399      return !(lifetime_args.empty () && generic_args.empty ()
     400  	     && binding_args.empty ());
     401    }
     402  
     403    GenericArgs (std::vector<Lifetime> lifetime_args,
     404  	       std::vector<GenericArg> generic_args,
     405  	       std::vector<GenericArgsBinding> binding_args,
     406  	       Location locus = Location ())
     407      : lifetime_args (std::move (lifetime_args)),
     408        generic_args (std::move (generic_args)),
     409        binding_args (std::move (binding_args)), locus (locus)
     410    {}
     411  
     412    // copy constructor with vector clone
     413    GenericArgs (GenericArgs const &other)
     414      : lifetime_args (other.lifetime_args), generic_args (other.generic_args),
     415        binding_args (other.binding_args), locus (other.locus)
     416    {}
     417  
     418    ~GenericArgs () = default;
     419  
     420    // overloaded assignment operator to vector clone
     421    GenericArgs &operator= (GenericArgs const &other)
     422    {
     423      lifetime_args = other.lifetime_args;
     424      generic_args = other.generic_args;
     425      binding_args = other.binding_args;
     426      locus = other.locus;
     427  
     428      return *this;
     429    }
     430  
     431    // move constructors
     432    GenericArgs (GenericArgs &&other) = default;
     433    GenericArgs &operator= (GenericArgs &&other) = default;
     434  
     435    // Creates an empty GenericArgs (no arguments)
     436    static GenericArgs create_empty () { return GenericArgs ({}, {}, {}); }
     437  
     438    std::string as_string () const;
     439  
     440    // TODO: is this better? Or is a "vis_pattern" better?
     441    std::vector<GenericArg> &get_generic_args () { return generic_args; }
     442  
     443    // TODO: is this better? Or is a "vis_pattern" better?
     444    std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }
     445  
     446    std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; };
     447  
     448    Location get_locus () { return locus; }
     449  };
     450  
     451  /* A segment of a path in expression, including an identifier aspect and maybe
     452   * generic args */
     453  class PathExprSegment
     454  { // or should this extend PathIdentSegment?
     455  private:
     456    PathIdentSegment segment_name;
     457    GenericArgs generic_args;
     458    Location locus;
     459    NodeId node_id;
     460  
     461  public:
     462    // Returns true if there are any generic arguments
     463    bool has_generic_args () const { return generic_args.has_generic_args (); }
     464  
     465    // Constructor for segment (from IdentSegment and GenericArgs)
     466    PathExprSegment (PathIdentSegment segment_name, Location locus,
     467  		   GenericArgs generic_args = GenericArgs::create_empty ())
     468      : segment_name (std::move (segment_name)),
     469        generic_args (std::move (generic_args)), locus (locus),
     470        node_id (Analysis::Mappings::get ()->get_next_node_id ())
     471    {}
     472  
     473    /* Constructor for segment with generic arguments (from segment name and all
     474     * args) */
     475    PathExprSegment (std::string segment_name, Location locus,
     476  		   std::vector<Lifetime> lifetime_args = {},
     477  		   std::vector<GenericArg> generic_args = {},
     478  		   std::vector<GenericArgsBinding> binding_args = {})
     479      : segment_name (PathIdentSegment (std::move (segment_name), locus)),
     480        generic_args (GenericArgs (std::move (lifetime_args),
     481  				 std::move (generic_args),
     482  				 std::move (binding_args))),
     483        locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ())
     484    {}
     485  
     486    // Returns whether path expression segment is in an error state.
     487    bool is_error () const { return segment_name.is_error (); }
     488  
     489    // Creates an error-state path expression segment.
     490    static PathExprSegment create_error ()
     491    {
     492      return PathExprSegment (PathIdentSegment::create_error (), Location ());
     493    }
     494  
     495    std::string as_string () const;
     496  
     497    Location get_locus () const { return locus; }
     498  
     499    // TODO: is this better? Or is a "vis_pattern" better?
     500    GenericArgs &get_generic_args ()
     501    {
     502      rust_assert (has_generic_args ());
     503      return generic_args;
     504    }
     505  
     506    PathIdentSegment &get_ident_segment () { return segment_name; }
     507    const PathIdentSegment &get_ident_segment () const { return segment_name; }
     508  
     509    NodeId get_node_id () const { return node_id; }
     510  
     511    bool is_super_path_seg () const
     512    {
     513      return !has_generic_args () && get_ident_segment ().is_super_segment ();
     514    }
     515  
     516    bool is_crate_path_seg () const
     517    {
     518      return !has_generic_args () && get_ident_segment ().is_crate_segment ();
     519    }
     520    bool is_lower_self_seg () const
     521    {
     522      return !has_generic_args () && get_ident_segment ().is_lower_self ();
     523    }
     524  };
     525  
     526  // AST node representing a pattern that involves a "path" - abstract base
     527  // class
     528  class PathPattern : public Pattern
     529  {
     530    std::vector<PathExprSegment> segments;
     531  
     532  protected:
     533    PathPattern (std::vector<PathExprSegment> segments)
     534      : segments (std::move (segments))
     535    {}
     536  
     537    // Returns whether path has segments.
     538    bool has_segments () const { return !segments.empty (); }
     539  
     540    /* Converts path segments to their equivalent SimplePath segments if
     541     * possible, and creates a SimplePath from them. */
     542    SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const;
     543  
     544    // Removes all segments of the path.
     545    void remove_all_segments ()
     546    {
     547      segments.clear ();
     548      segments.shrink_to_fit ();
     549    }
     550  
     551  public:
     552    /* Returns whether the path is a single segment (excluding qualified path
     553     * initial as segment). */
     554    bool is_single_segment () const { return segments.size () == 1; }
     555  
     556    std::string as_string () const override;
     557  
     558    // TODO: this seems kinda dodgy
     559    std::vector<PathExprSegment> &get_segments () { return segments; }
     560    const std::vector<PathExprSegment> &get_segments () const { return segments; }
     561  };
     562  
     563  /* AST node representing a path-in-expression pattern (path that allows
     564   * generic arguments) */
     565  class PathInExpression : public PathPattern, public PathExpr
     566  {
     567    std::vector<Attribute> outer_attrs;
     568    bool has_opening_scope_resolution;
     569    Location locus;
     570    NodeId _node_id;
     571  
     572  public:
     573    std::string as_string () const override;
     574  
     575    // Constructor
     576    PathInExpression (std::vector<PathExprSegment> path_segments,
     577  		    std::vector<Attribute> outer_attrs, Location locus,
     578  		    bool has_opening_scope_resolution = false)
     579      : PathPattern (std::move (path_segments)),
     580        outer_attrs (std::move (outer_attrs)),
     581        has_opening_scope_resolution (has_opening_scope_resolution),
     582        locus (locus), _node_id (Analysis::Mappings::get ()->get_next_node_id ())
     583    {}
     584  
     585    // Creates an error state path in expression.
     586    static PathInExpression create_error ()
     587    {
     588      return PathInExpression ({}, {}, Location ());
     589    }
     590  
     591    // Returns whether path in expression is in an error state.
     592    bool is_error () const { return !has_segments (); }
     593  
     594    /* Converts PathInExpression to SimplePath if possible (i.e. no generic
     595     * arguments). Otherwise returns an empty SimplePath. */
     596    SimplePath as_simple_path () const
     597    {
     598      /* delegate to parent class as can't access segments. however,
     599       * QualifiedPathInExpression conversion to simple path wouldn't make
     600       * sense, so the method in the parent class should be protected, not
     601       * public. Have to pass in opening scope resolution as parent class has no
     602       * access to it.
     603       */
     604      return convert_to_simple_path (has_opening_scope_resolution);
     605    }
     606  
     607    Location get_locus () const override final { return locus; }
     608  
     609    void accept_vis (ASTVisitor &vis) override;
     610  
     611    // Invalid if path is empty (error state), so base stripping on that.
     612    void mark_for_strip () override { remove_all_segments (); }
     613    bool is_marked_for_strip () const override { return is_error (); }
     614  
     615    bool opening_scope_resolution () const
     616    {
     617      return has_opening_scope_resolution;
     618    }
     619  
     620    NodeId get_node_id () const override { return _node_id; }
     621  
     622    const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
     623    std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
     624  
     625    void set_outer_attrs (std::vector<Attribute> new_attrs) override
     626    {
     627      outer_attrs = std::move (new_attrs);
     628    }
     629  
     630    NodeId get_pattern_node_id () const override final { return get_node_id (); }
     631  
     632  protected:
     633    /* Use covariance to implement clone function as returning this object
     634     * rather than base */
     635    PathInExpression *clone_pattern_impl () const final override
     636    {
     637      return clone_path_in_expression_impl ();
     638    }
     639  
     640    /* Use covariance to implement clone function as returning this object
     641     * rather than base */
     642    PathInExpression *clone_expr_without_block_impl () const final override
     643    {
     644      return clone_path_in_expression_impl ();
     645    }
     646  
     647    /*virtual*/ PathInExpression *clone_path_in_expression_impl () const
     648    {
     649      return new PathInExpression (*this);
     650    }
     651  };
     652  
     653  /* Base class for segments used in type paths - not abstract (represents an
     654   * ident-only segment) */
     655  class TypePathSegment
     656  {
     657  public:
     658    enum SegmentType
     659    {
     660      REG,
     661      GENERIC,
     662      FUNCTION
     663    };
     664  
     665  private:
     666    PathIdentSegment ident_segment;
     667    Location locus;
     668  
     669  protected:
     670    /* This is protected because it is only really used by derived classes, not
     671     * the base. */
     672    bool has_separating_scope_resolution;
     673    NodeId node_id;
     674  
     675    // Clone function implementation - not pure virtual as overrided by
     676    // subclasses
     677    virtual TypePathSegment *clone_type_path_segment_impl () const
     678    {
     679      return new TypePathSegment (*this);
     680    }
     681  
     682  public:
     683    virtual ~TypePathSegment () {}
     684  
     685    virtual SegmentType get_type () const { return SegmentType::REG; }
     686  
     687    // Unique pointer custom clone function
     688    std::unique_ptr<TypePathSegment> clone_type_path_segment () const
     689    {
     690      return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ());
     691    }
     692  
     693    TypePathSegment (PathIdentSegment ident_segment,
     694  		   bool has_separating_scope_resolution, Location locus)
     695      : ident_segment (std::move (ident_segment)), locus (locus),
     696        has_separating_scope_resolution (has_separating_scope_resolution),
     697        node_id (Analysis::Mappings::get ()->get_next_node_id ())
     698    {}
     699  
     700    TypePathSegment (std::string segment_name,
     701  		   bool has_separating_scope_resolution, Location locus)
     702      : ident_segment (PathIdentSegment (std::move (segment_name), locus)),
     703        locus (locus),
     704        has_separating_scope_resolution (has_separating_scope_resolution),
     705        node_id (Analysis::Mappings::get ()->get_next_node_id ())
     706    {}
     707  
     708    virtual std::string as_string () const { return ident_segment.as_string (); }
     709  
     710    /* Returns whether the type path segment is in an error state. May be
     711     * virtual in future. */
     712    bool is_error () const { return ident_segment.is_error (); }
     713  
     714    /* Returns whether segment is identifier only (as opposed to generic args or
     715     * function). Overridden in derived classes with other segments. */
     716    virtual bool is_ident_only () const { return true; }
     717  
     718    Location get_locus () const { return locus; }
     719  
     720    // not pure virtual as class not abstract
     721    virtual void accept_vis (ASTVisitor &vis);
     722  
     723    bool get_separating_scope_resolution () const
     724    {
     725      return has_separating_scope_resolution;
     726    }
     727  
     728    PathIdentSegment &get_ident_segment () { return ident_segment; };
     729    const PathIdentSegment &get_ident_segment () const { return ident_segment; };
     730  
     731    NodeId get_node_id () const { return node_id; }
     732  
     733    bool is_crate_path_seg () const
     734    {
     735      return get_ident_segment ().is_crate_segment ();
     736    }
     737    bool is_super_path_seg () const
     738    {
     739      return get_ident_segment ().is_super_segment ();
     740    }
     741    bool is_big_self_seg () const { return get_ident_segment ().is_big_self (); }
     742    bool is_lower_self_seg () const
     743    {
     744      return get_ident_segment ().is_lower_self ();
     745    }
     746  };
     747  
     748  // Segment used in type path with generic args
     749  class TypePathSegmentGeneric : public TypePathSegment
     750  {
     751    GenericArgs generic_args;
     752  
     753  public:
     754    SegmentType get_type () const override { return SegmentType::GENERIC; }
     755  
     756    bool has_generic_args () const { return generic_args.has_generic_args (); }
     757  
     758    bool is_ident_only () const override { return false; }
     759  
     760    // Constructor with PathIdentSegment and GenericArgs
     761    TypePathSegmentGeneric (PathIdentSegment ident_segment,
     762  			  bool has_separating_scope_resolution,
     763  			  GenericArgs generic_args, Location locus)
     764      : TypePathSegment (std::move (ident_segment),
     765  		       has_separating_scope_resolution, locus),
     766        generic_args (std::move (generic_args))
     767    {}
     768  
     769    // Constructor from segment name and all args
     770    TypePathSegmentGeneric (std::string segment_name,
     771  			  bool has_separating_scope_resolution,
     772  			  std::vector<Lifetime> lifetime_args,
     773  			  std::vector<GenericArg> generic_args,
     774  			  std::vector<GenericArgsBinding> binding_args,
     775  			  Location locus)
     776      : TypePathSegment (std::move (segment_name),
     777  		       has_separating_scope_resolution, locus),
     778        generic_args (GenericArgs (std::move (lifetime_args),
     779  				 std::move (generic_args),
     780  				 std::move (binding_args)))
     781    {}
     782  
     783    std::string as_string () const override;
     784  
     785    void accept_vis (ASTVisitor &vis) override;
     786  
     787    // TODO: is this better? Or is a "vis_pattern" better?
     788    GenericArgs &get_generic_args ()
     789    {
     790      rust_assert (has_generic_args ());
     791      return generic_args;
     792    }
     793  
     794  protected:
     795    // Use covariance to override base class method
     796    TypePathSegmentGeneric *clone_type_path_segment_impl () const override
     797    {
     798      return new TypePathSegmentGeneric (*this);
     799    }
     800  };
     801  
     802  // A function as represented in a type path
     803  struct TypePathFunction
     804  {
     805  private:
     806    // TODO: remove
     807    /*bool has_inputs;
     808    TypePathFnInputs inputs;*/
     809    // inlined from TypePathFnInputs
     810    std::vector<std::unique_ptr<Type> > inputs;
     811  
     812    // bool has_type;
     813    std::unique_ptr<Type> return_type;
     814  
     815    // FIXME: think of better way to mark as invalid than taking up storage
     816    bool is_invalid;
     817  
     818    Location locus;
     819  
     820  protected:
     821    // Constructor only used to create invalid type path functions.
     822    TypePathFunction (bool is_invalid, Location locus)
     823      : is_invalid (is_invalid), locus (locus)
     824    {}
     825  
     826  public:
     827    // Returns whether the return type of the function has been specified.
     828    bool has_return_type () const { return return_type != nullptr; }
     829  
     830    // Returns whether the function has inputs.
     831    bool has_inputs () const { return !inputs.empty (); }
     832  
     833    // Returns whether function is in an error state.
     834    bool is_error () const { return is_invalid; }
     835  
     836    // Creates an error state function.
     837    static TypePathFunction create_error ()
     838    {
     839      return TypePathFunction (true, Location ());
     840    }
     841  
     842    // Constructor
     843    TypePathFunction (std::vector<std::unique_ptr<Type> > inputs, Location locus,
     844  		    std::unique_ptr<Type> type = nullptr)
     845      : inputs (std::move (inputs)), return_type (std::move (type)),
     846        is_invalid (false), locus (locus)
     847    {}
     848  
     849    // Copy constructor with clone
     850    TypePathFunction (TypePathFunction const &other)
     851      : is_invalid (other.is_invalid)
     852    {
     853      // guard to protect from null pointer dereference
     854      if (other.return_type != nullptr)
     855        return_type = other.return_type->clone_type ();
     856  
     857      inputs.reserve (other.inputs.size ());
     858      for (const auto &e : other.inputs)
     859        inputs.push_back (e->clone_type ());
     860    }
     861  
     862    ~TypePathFunction () = default;
     863  
     864    // Overloaded assignment operator to clone type
     865    TypePathFunction &operator= (TypePathFunction const &other)
     866    {
     867      is_invalid = other.is_invalid;
     868  
     869      // guard to protect from null pointer dereference
     870      if (other.return_type != nullptr)
     871        return_type = other.return_type->clone_type ();
     872      else
     873        return_type = nullptr;
     874  
     875      inputs.reserve (other.inputs.size ());
     876      for (const auto &e : other.inputs)
     877        inputs.push_back (e->clone_type ());
     878  
     879      return *this;
     880    }
     881  
     882    // move constructors
     883    TypePathFunction (TypePathFunction &&other) = default;
     884    TypePathFunction &operator= (TypePathFunction &&other) = default;
     885  
     886    std::string as_string () const;
     887  
     888    // TODO: this mutable getter seems really dodgy. Think up better way.
     889    const std::vector<std::unique_ptr<Type> > &get_params () const
     890    {
     891      return inputs;
     892    }
     893    std::vector<std::unique_ptr<Type> > &get_params () { return inputs; }
     894  
     895    // TODO: is this better? Or is a "vis_pattern" better?
     896    std::unique_ptr<Type> &get_return_type ()
     897    {
     898      rust_assert (has_return_type ());
     899      return return_type;
     900    }
     901  
     902    Location get_locus () const { return locus; }
     903  };
     904  
     905  // Segment used in type path with a function argument
     906  class TypePathSegmentFunction : public TypePathSegment
     907  {
     908    TypePathFunction function_path;
     909  
     910  public:
     911    SegmentType get_type () const override { return SegmentType::FUNCTION; }
     912  
     913    // Constructor with PathIdentSegment and TypePathFn
     914    TypePathSegmentFunction (PathIdentSegment ident_segment,
     915  			   bool has_separating_scope_resolution,
     916  			   TypePathFunction function_path, Location locus)
     917      : TypePathSegment (std::move (ident_segment),
     918  		       has_separating_scope_resolution, locus),
     919        function_path (std::move (function_path))
     920    {}
     921  
     922    // Constructor with segment name and TypePathFn
     923    TypePathSegmentFunction (std::string segment_name,
     924  			   bool has_separating_scope_resolution,
     925  			   TypePathFunction function_path, Location locus)
     926      : TypePathSegment (std::move (segment_name),
     927  		       has_separating_scope_resolution, locus),
     928        function_path (std::move (function_path))
     929    {}
     930  
     931    std::string as_string () const override;
     932  
     933    bool is_ident_only () const override { return false; }
     934  
     935    void accept_vis (ASTVisitor &vis) override;
     936  
     937    // TODO: is this better? Or is a "vis_pattern" better?
     938    TypePathFunction &get_type_path_function ()
     939    {
     940      rust_assert (!function_path.is_error ());
     941      return function_path;
     942    }
     943  
     944  protected:
     945    // Use covariance to override base class method
     946    TypePathSegmentFunction *clone_type_path_segment_impl () const override
     947    {
     948      return new TypePathSegmentFunction (*this);
     949    }
     950  };
     951  
     952  // Path used inside types
     953  class TypePath : public TypeNoBounds
     954  {
     955    bool has_opening_scope_resolution;
     956    std::vector<std::unique_ptr<TypePathSegment> > segments;
     957    Location locus;
     958  
     959  protected:
     960    /* Use covariance to implement clone function as returning this object
     961     * rather than base */
     962    TypePath *clone_type_no_bounds_impl () const override
     963    {
     964      return new TypePath (*this);
     965    }
     966  
     967  public:
     968    /* Returns whether the TypePath has an opening scope resolution operator
     969     * (i.e. is global path or crate-relative path, not module-relative) */
     970    bool has_opening_scope_resolution_op () const
     971    {
     972      return has_opening_scope_resolution;
     973    }
     974  
     975    // Returns whether the TypePath is in an invalid state.
     976    bool is_error () const { return segments.empty (); }
     977  
     978    // Creates an error state TypePath.
     979    static TypePath create_error ()
     980    {
     981      return TypePath (std::vector<std::unique_ptr<TypePathSegment> > (),
     982  		     Location ());
     983    }
     984  
     985    // Constructor
     986    TypePath (std::vector<std::unique_ptr<TypePathSegment> > segments,
     987  	    Location locus, bool has_opening_scope_resolution = false)
     988      : TypeNoBounds (),
     989        has_opening_scope_resolution (has_opening_scope_resolution),
     990        segments (std::move (segments)), locus (locus)
     991    {}
     992  
     993    // Copy constructor with vector clone
     994    TypePath (TypePath const &other)
     995      : has_opening_scope_resolution (other.has_opening_scope_resolution),
     996        locus (other.locus)
     997    {
     998      segments.reserve (other.segments.size ());
     999      for (const auto &e : other.segments)
    1000        segments.push_back (e->clone_type_path_segment ());
    1001    }
    1002  
    1003    // Overloaded assignment operator with clone
    1004    TypePath &operator= (TypePath const &other)
    1005    {
    1006      has_opening_scope_resolution = other.has_opening_scope_resolution;
    1007      locus = other.locus;
    1008  
    1009      segments.reserve (other.segments.size ());
    1010      for (const auto &e : other.segments)
    1011        segments.push_back (e->clone_type_path_segment ());
    1012  
    1013      return *this;
    1014    }
    1015  
    1016    // move constructors
    1017    TypePath (TypePath &&other) = default;
    1018    TypePath &operator= (TypePath &&other) = default;
    1019  
    1020    std::string as_string () const override;
    1021  
    1022    /* Converts TypePath to SimplePath if possible (i.e. no generic or function
    1023     * arguments). Otherwise returns an empty SimplePath. */
    1024    SimplePath as_simple_path () const;
    1025  
    1026    // Creates a trait bound with a clone of this type path as its only element.
    1027    TraitBound *to_trait_bound (bool in_parens) const override;
    1028  
    1029    Location get_locus () const override final { return locus; }
    1030  
    1031    void accept_vis (ASTVisitor &vis) override;
    1032  
    1033    // TODO: this seems kinda dodgy
    1034    std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
    1035    {
    1036      return segments;
    1037    }
    1038    const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const
    1039    {
    1040      return segments;
    1041    }
    1042  
    1043    size_t get_num_segments () const { return segments.size (); }
    1044  };
    1045  
    1046  struct QualifiedPathType
    1047  {
    1048  private:
    1049    std::unique_ptr<Type> type_to_invoke_on;
    1050    TypePath trait_path;
    1051    Location locus;
    1052    NodeId node_id;
    1053  
    1054  public:
    1055    // Constructor
    1056    QualifiedPathType (std::unique_ptr<Type> invoke_on_type,
    1057  		     Location locus = Location (),
    1058  		     TypePath trait_path = TypePath::create_error ())
    1059      : type_to_invoke_on (std::move (invoke_on_type)),
    1060        trait_path (std::move (trait_path)), locus (locus),
    1061        node_id (Analysis::Mappings::get ()->get_next_node_id ())
    1062    {}
    1063  
    1064    // Copy constructor uses custom deep copy for Type to preserve polymorphism
    1065    QualifiedPathType (QualifiedPathType const &other)
    1066      : trait_path (other.trait_path), locus (other.locus)
    1067    {
    1068      node_id = other.node_id;
    1069      // guard to prevent null dereference
    1070      if (other.type_to_invoke_on != nullptr)
    1071        type_to_invoke_on = other.type_to_invoke_on->clone_type ();
    1072    }
    1073  
    1074    // default destructor
    1075    ~QualifiedPathType () = default;
    1076  
    1077    // overload assignment operator to use custom clone method
    1078    QualifiedPathType &operator= (QualifiedPathType const &other)
    1079    {
    1080      node_id = other.node_id;
    1081      trait_path = other.trait_path;
    1082      locus = other.locus;
    1083  
    1084      // guard to prevent null dereference
    1085      if (other.type_to_invoke_on != nullptr)
    1086        type_to_invoke_on = other.type_to_invoke_on->clone_type ();
    1087      else
    1088        type_to_invoke_on = nullptr;
    1089  
    1090      return *this;
    1091    }
    1092  
    1093    // move constructor
    1094    QualifiedPathType (QualifiedPathType &&other) = default;
    1095    QualifiedPathType &operator= (QualifiedPathType &&other) = default;
    1096  
    1097    // Returns whether the qualified path type has a rebind as clause.
    1098    bool has_as_clause () const { return !trait_path.is_error (); }
    1099  
    1100    // Returns whether the qualified path type is in an error state.
    1101    bool is_error () const { return type_to_invoke_on == nullptr; }
    1102  
    1103    // Creates an error state qualified path type.
    1104    static QualifiedPathType create_error ()
    1105    {
    1106      return QualifiedPathType (nullptr);
    1107    }
    1108  
    1109    std::string as_string () const;
    1110  
    1111    Location get_locus () const { return locus; }
    1112  
    1113    // TODO: is this better? Or is a "vis_pattern" better?
    1114    std::unique_ptr<Type> &get_type ()
    1115    {
    1116      rust_assert (type_to_invoke_on != nullptr);
    1117      return type_to_invoke_on;
    1118    }
    1119  
    1120    // TODO: is this better? Or is a "vis_pattern" better?
    1121    TypePath &get_as_type_path ()
    1122    {
    1123      rust_assert (has_as_clause ());
    1124      return trait_path;
    1125    }
    1126  
    1127    NodeId get_node_id () const { return node_id; }
    1128  };
    1129  
    1130  /* AST node representing a qualified path-in-expression pattern (path that
    1131   * allows specifying trait functions) */
    1132  class QualifiedPathInExpression : public PathPattern, public PathExpr
    1133  {
    1134    std::vector<Attribute> outer_attrs;
    1135    QualifiedPathType path_type;
    1136    Location locus;
    1137    NodeId _node_id;
    1138  
    1139  public:
    1140    std::string as_string () const override;
    1141  
    1142    QualifiedPathInExpression (QualifiedPathType qual_path_type,
    1143  			     std::vector<PathExprSegment> path_segments,
    1144  			     std::vector<Attribute> outer_attrs, Location locus)
    1145      : PathPattern (std::move (path_segments)),
    1146        outer_attrs (std::move (outer_attrs)),
    1147        path_type (std::move (qual_path_type)), locus (locus),
    1148        _node_id (Analysis::Mappings::get ()->get_next_node_id ())
    1149    {}
    1150  
    1151    /* TODO: maybe make a shortcut constructor that has QualifiedPathType
    1152     * elements as params */
    1153  
    1154    // Returns whether qualified path in expression is in an error state.
    1155    bool is_error () const { return path_type.is_error (); }
    1156  
    1157    // Creates an error qualified path in expression.
    1158    static QualifiedPathInExpression create_error ()
    1159    {
    1160      return QualifiedPathInExpression (QualifiedPathType::create_error (), {},
    1161  				      {}, Location ());
    1162    }
    1163  
    1164    Location get_locus () const override final { return locus; }
    1165  
    1166    void accept_vis (ASTVisitor &vis) override;
    1167  
    1168    // Invalid if path_type is error, so base stripping on that.
    1169    void mark_for_strip () override
    1170    {
    1171      path_type = QualifiedPathType::create_error ();
    1172    }
    1173    bool is_marked_for_strip () const override { return is_error (); }
    1174  
    1175    // TODO: is this better? Or is a "vis_pattern" better?
    1176    QualifiedPathType &get_qualified_path_type ()
    1177    {
    1178      rust_assert (!path_type.is_error ());
    1179      return path_type;
    1180    }
    1181  
    1182    const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
    1183    std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
    1184  
    1185    void set_outer_attrs (std::vector<Attribute> new_attrs) override
    1186    {
    1187      outer_attrs = std::move (new_attrs);
    1188    }
    1189  
    1190    NodeId get_node_id () const override { return _node_id; }
    1191  
    1192    NodeId get_pattern_node_id () const override final { return get_node_id (); }
    1193  
    1194  protected:
    1195    /* Use covariance to implement clone function as returning this object
    1196     * rather than base */
    1197    QualifiedPathInExpression *clone_pattern_impl () const final override
    1198    {
    1199      return clone_qual_path_in_expression_impl ();
    1200    }
    1201  
    1202    /* Use covariance to implement clone function as returning this object
    1203     * rather than base */
    1204    QualifiedPathInExpression *
    1205    clone_expr_without_block_impl () const final override
    1206    {
    1207      return clone_qual_path_in_expression_impl ();
    1208    }
    1209  
    1210    /*virtual*/ QualifiedPathInExpression *
    1211    clone_qual_path_in_expression_impl () const
    1212    {
    1213      return new QualifiedPathInExpression (*this);
    1214    }
    1215  };
    1216  
    1217  /* Represents a qualified path in a type; used for disambiguating trait
    1218   * function calls */
    1219  class QualifiedPathInType : public TypeNoBounds
    1220  {
    1221    QualifiedPathType path_type;
    1222    std::unique_ptr<TypePathSegment> associated_segment;
    1223    std::vector<std::unique_ptr<TypePathSegment> > segments;
    1224    Location locus;
    1225  
    1226  protected:
    1227    /* Use covariance to implement clone function as returning this object
    1228     * rather than base */
    1229    QualifiedPathInType *clone_type_no_bounds_impl () const override
    1230    {
    1231      return new QualifiedPathInType (*this);
    1232    }
    1233  
    1234  public:
    1235    QualifiedPathInType (
    1236      QualifiedPathType qual_path_type,
    1237      std::unique_ptr<TypePathSegment> associated_segment,
    1238      std::vector<std::unique_ptr<TypePathSegment> > path_segments,
    1239      Location locus)
    1240      : path_type (std::move (qual_path_type)),
    1241        associated_segment (std::move (associated_segment)),
    1242        segments (std::move (path_segments)), locus (locus)
    1243    {}
    1244  
    1245    /* TODO: maybe make a shortcut constructor that has QualifiedPathType
    1246     * elements as params */
    1247  
    1248    // Copy constructor with vector clone
    1249    QualifiedPathInType (QualifiedPathInType const &other)
    1250      : path_type (other.path_type), locus (other.locus)
    1251    {
    1252      segments.reserve (other.segments.size ());
    1253      for (const auto &e : other.segments)
    1254        segments.push_back (e->clone_type_path_segment ());
    1255    }
    1256  
    1257    // Overloaded assignment operator with vector clone
    1258    QualifiedPathInType &operator= (QualifiedPathInType const &other)
    1259    {
    1260      path_type = other.path_type;
    1261      locus = other.locus;
    1262  
    1263      segments.reserve (other.segments.size ());
    1264      for (const auto &e : other.segments)
    1265        segments.push_back (e->clone_type_path_segment ());
    1266  
    1267      return *this;
    1268    }
    1269  
    1270    // move constructors
    1271    QualifiedPathInType (QualifiedPathInType &&other) = default;
    1272    QualifiedPathInType &operator= (QualifiedPathInType &&other) = default;
    1273  
    1274    // Returns whether qualified path in type is in an error state.
    1275    bool is_error () const { return path_type.is_error (); }
    1276  
    1277    // Creates an error state qualified path in type.
    1278    static QualifiedPathInType create_error ()
    1279    {
    1280      return QualifiedPathInType (
    1281        QualifiedPathType::create_error (), nullptr,
    1282        std::vector<std::unique_ptr<TypePathSegment> > (), Location ());
    1283    }
    1284  
    1285    std::string as_string () const override;
    1286  
    1287    void accept_vis (ASTVisitor &vis) override;
    1288  
    1289    // TODO: is this better? Or is a "vis_pattern" better?
    1290    QualifiedPathType &get_qualified_path_type ()
    1291    {
    1292      rust_assert (!path_type.is_error ());
    1293      return path_type;
    1294    }
    1295  
    1296    std::unique_ptr<TypePathSegment> &get_associated_segment ()
    1297    {
    1298      return associated_segment;
    1299    }
    1300  
    1301    // TODO: this seems kinda dodgy
    1302    std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
    1303    {
    1304      return segments;
    1305    }
    1306    const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const
    1307    {
    1308      return segments;
    1309    }
    1310  
    1311    Location get_locus () const override final { return locus; }
    1312  };
    1313  } // namespace AST
    1314  } // namespace Rust
    1315  
    1316  #endif