// Copyright (C) 2020-2025 Free Software Foundation, Inc.

// This file is part of GCC.

// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.

// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.

// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3.  If not see
// <http://www.gnu.org/licenses/>.

#ifndef RUST_AST_PATH_H
#define RUST_AST_PATH_H
/* "Path" (identifier within namespaces, essentially) handling. Required include
 * for virtually all AST-related functionality. */

#include "optional.h"
#include "rust-ast.h"
#include "rust-hir-map.h"
#include "rust-mapping-common.h"
#include "rust-system.h"
#include "system.h"

namespace Rust {
namespace AST {

// The "identifier" (not generic args) aspect of each path expression segment
class PathIdentSegment
{
  std::string segment_name;
  location_t locus;

  // only allow identifiers, "super", "self", "Self", "crate", or "$crate"
public:
  PathIdentSegment (std::string segment_name, location_t locus)
    : segment_name (std::move (segment_name)), locus (locus)
  {}

  // Creates an error PathIdentSegment.
  static PathIdentSegment create_error ()
  {
    return PathIdentSegment ("", UNDEF_LOCATION);
  }

  // Returns whether PathIdentSegment is in an error state.
  bool is_error () const { return segment_name.empty (); }

  std::string as_string () const { return segment_name; }

  location_t get_locus () const { return locus; }

  bool is_super_path_seg () const
  {
    return as_string ().compare ("super") == 0;
  }
  bool is_crate_path_seg () const
  {
    return as_string ().compare ("crate") == 0;
  }
  bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; }
  bool is_big_self_seg () const { return as_string ().compare ("Self") == 0; }
};

// A binding of an identifier to a type used in generic arguments in paths
struct GenericArgsBinding
{
private:
  Identifier identifier;
  std::unique_ptr<Type> type;
  location_t locus;

public:
  // Returns whether binding is in an error state.
  bool is_error () const
  {
    return type == nullptr;
    // and also identifier is empty, but cheaper computation
  }

  // Creates an error state generic args binding.
  static GenericArgsBinding create_error ()
  {
    return GenericArgsBinding ({""}, nullptr);
  }

  // Pointer type for type in constructor to enable polymorphism
  GenericArgsBinding (Identifier ident, std::unique_ptr<Type> type_ptr,
		      location_t locus = UNDEF_LOCATION)
    : identifier (std::move (ident)), type (std::move (type_ptr)), locus (locus)
  {}

  // Copy constructor has to deep copy the type as it is a unique pointer
  GenericArgsBinding (GenericArgsBinding const &other)
    : identifier (other.identifier), locus (other.locus)
  {
    // guard to protect from null pointer dereference
    if (other.type != nullptr)
      type = other.type->clone_type ();
  }

  // default destructor
  ~GenericArgsBinding () = default;

  // Overload assignment operator to deep copy the pointed-to type
  GenericArgsBinding &operator= (GenericArgsBinding const &other)
  {
    identifier = other.identifier;
    locus = other.locus;

    // guard to protect from null pointer dereference
    if (other.type != nullptr)
      type = other.type->clone_type ();
    else
      type = nullptr;

    return *this;
  }

  // move constructors
  GenericArgsBinding (GenericArgsBinding &&other) = default;
  GenericArgsBinding &operator= (GenericArgsBinding &&other) = default;

  std::string as_string () const;

  // TODO: is this better? Or is a "vis_pattern" better?
  Type &get_type ()
  {
    rust_assert (type != nullptr);
    return *type;
  }

  std::unique_ptr<Type> &get_type_ptr ()
  {
    rust_assert (type != nullptr);
    return type;
  }

  location_t get_locus () const { return locus; }

  Identifier get_identifier () const { return identifier; }
};

/* Class representing a const generic application */
class GenericArg
{
public:
  /**
   * const generic arguments cannot always be differentiated with generic type
   * arguments during parsing, e.g:
   * ```rust
   * let a: Foo<N>;
   * ```
   *
   * Is N a type? A constant defined elsewhere? The parser cannot know, and must
   * not draw any conclusions. We must wait until later passes of the compiler
   * to decide whether this refers to a constant item or a type.
   *
   * On the other hand, simple expressions like literals or block expressions
   * will always be constant expressions: There is no ambiguity at all.
   */
  enum class Kind
  {
    Const,  // A const value
    Type,   // A type argument (not discernable during parsing)
    Either, // Either a type or a const value, cleared up during resolving
  };

  static GenericArg create_const (std::unique_ptr<Expr> expression)
  {
    auto locus = expression->get_locus ();
    return GenericArg (std::move (expression), nullptr, {""}, Kind::Const,
		       locus);
  }

  static GenericArg create_type (std::unique_ptr<Type> type)
  {
    auto locus = type->get_locus ();
    return GenericArg (nullptr, std::move (type), {""}, Kind::Type, locus);
  }

  static GenericArg create_ambiguous (Identifier path, location_t locus)
  {
    return GenericArg (nullptr, nullptr, std::move (path), Kind::Either, locus);
  }

  GenericArg (const GenericArg &other)
    : path (other.path), kind (other.kind), locus (other.locus)
  {
    if (other.expression)
      expression = other.expression->clone_expr ();
    if (other.type)
      type = other.type->clone_type ();
  }

  GenericArg operator= (const GenericArg &other)
  {
    kind = other.kind;
    path = other.path;
    locus = other.locus;

    if (other.expression)
      expression = other.expression->clone_expr ();
    if (other.type)
      type = other.type->clone_type ();

    return *this;
  }

  GenericArg (GenericArg &&other) = default;
  GenericArg &operator= (GenericArg &&other) = default;

  Kind get_kind () const { return kind; }
  location_t get_locus () const { return locus; }

  void accept_vis (AST::ASTVisitor &visitor)
  {
    switch (get_kind ())
      {
      case Kind::Const:
	get_expression ().accept_vis (visitor);
	break;
      case Kind::Type:
	get_type ().accept_vis (visitor);
	break;
      case Kind::Either:
	break;
      }
  }

  Expr &get_expression ()
  {
    rust_assert (kind == Kind::Const);

    return *expression;
  }

  std::unique_ptr<Expr> &get_expression_ptr ()
  {
    rust_assert (kind == Kind::Const);

    return expression;
  }

  Type &get_type ()
  {
    rust_assert (kind == Kind::Type);

    return *type;
  }

  std::unique_ptr<Type> &get_type_ptr ()
  {
    rust_assert (kind == Kind::Type);

    return type;
  }

  const std::string get_path () const
  {
    rust_assert (kind == Kind::Either);

    return path.as_string ();
  }

  std::string as_string () const
  {
    switch (get_kind ())
      {
      case Kind::Either:
	return "Ambiguous: " + path.as_string ();
      case Kind::Const:
	return "Const: { " + expression->as_string () + " }";
      case Kind::Type:
	return "Type: " + type->as_string ();
      }

    return "";
  }

  /**
   * Disambiguate an ambiguous generic argument to a const generic argument,
   * unequivocally
   */
  GenericArg disambiguate_to_const () const;

  /**
   * Disambiguate an ambiguous generic argument to a type argument,
   * unequivocally
   */
  GenericArg disambiguate_to_type () const;

private:
  GenericArg (std::unique_ptr<Expr> expression, std::unique_ptr<Type> type,
	      Identifier path, Kind kind, location_t locus)
    : expression (std::move (expression)), type (std::move (type)),
      path (std::move (path)), kind (kind), locus (locus)
  {}

  /**
   * Expression associated with a `Clear` const generic application
   * A null pointer here is allowed in the case that the const argument is
   * ambiguous.
   */
  std::unique_ptr<Expr> expression;

  /**
   * If the argument ends up being a type argument instead. A null pointer will
   * be present here until the resolving phase.
   */
  std::unique_ptr<Type> type;

  /**
   * Optional path which cannot be differentiated between a constant item and
   * a type. Only used for ambiguous const generic arguments, otherwise
   * empty.
   */
  Identifier path;

  /* Which kind of const generic application are we dealing with */
  Kind kind;

  location_t locus;
};

/**
 * Representation of const generic parameters
 */
class ConstGenericParam : public GenericParam
{
  /* Name of the parameter */
  Identifier name;

  /* Mandatory type of the const parameter - a null pointer is an error */
  std::unique_ptr<AST::Type> type;

  /**
   * Default value for the const generic parameter
   */
  tl::optional<GenericArg> default_value;

  AST::AttrVec outer_attrs;
  location_t locus;

public:
  ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type,
		     tl::optional<GenericArg> default_value,
		     AST::AttrVec outer_attrs, location_t locus)
    : name (name), type (std::move (type)),
      default_value (std::move (default_value)), outer_attrs (outer_attrs),
      locus (locus)
  {}

  ConstGenericParam (const ConstGenericParam &other)
    : GenericParam (), name (other.name), type (other.type->clone_type ()),
      default_value (other.default_value), outer_attrs (other.outer_attrs),
      locus (other.locus)
  {}

  bool has_type () const { return type != nullptr; }
  bool has_default_value () const { return default_value.has_value (); }

  const Identifier &get_name () const { return name; }

  AST::AttrVec &get_outer_attrs () { return outer_attrs; }

  AST::Type &get_type ()
  {
    rust_assert (has_type ());

    return *type;
  }

  GenericArg &get_default_value_unchecked ()
  {
    rust_assert (has_default_value ());

    return default_value.value ();
  }

  const GenericArg &get_default_value_unchecked () const
  {
    rust_assert (has_default_value ());

    return default_value.value ();
  }

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

  location_t get_locus () const override final { return locus; }

  Kind get_kind () const override final { return Kind::Const; }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  ConstGenericParam *clone_generic_param_impl () const override
  {
    return new ConstGenericParam (*this);
  }
};

// Generic arguments allowed in each path expression segment - inline?
struct GenericArgs
{
  std::vector<Lifetime> lifetime_args;
  std::vector<GenericArg> generic_args;
  std::vector<GenericArgsBinding> binding_args;
  location_t locus;

public:
  // Returns true if there are any generic arguments
  bool has_generic_args () const
  {
    return !(lifetime_args.empty () && generic_args.empty ()
	     && binding_args.empty ());
  }

  GenericArgs (std::vector<Lifetime> lifetime_args,
	       std::vector<GenericArg> generic_args,
	       std::vector<GenericArgsBinding> binding_args,
	       location_t locus = UNDEF_LOCATION)
    : lifetime_args (std::move (lifetime_args)),
      generic_args (std::move (generic_args)),
      binding_args (std::move (binding_args)), locus (locus)
  {}

  // copy constructor with vector clone
  GenericArgs (GenericArgs const &other)
    : lifetime_args (other.lifetime_args), binding_args (other.binding_args),
      locus (other.locus)
  {
    generic_args.clear ();
    generic_args.reserve (other.generic_args.size ());
    for (const auto &arg : other.generic_args)
      {
	generic_args.push_back (GenericArg (arg));
      }
  }

  ~GenericArgs () = default;

  // overloaded assignment operator to vector clone
  GenericArgs &operator= (GenericArgs const &other)
  {
    lifetime_args = other.lifetime_args;
    binding_args = other.binding_args;
    locus = other.locus;

    generic_args.clear ();
    generic_args.reserve (other.generic_args.size ());
    for (const auto &arg : other.generic_args)
      {
	generic_args.push_back (GenericArg (arg));
      }

    return *this;
  }

  // move constructors
  GenericArgs (GenericArgs &&other) = default;
  GenericArgs &operator= (GenericArgs &&other) = default;

  // Creates an empty GenericArgs (no arguments)
  static GenericArgs create_empty () { return GenericArgs ({}, {}, {}); }

  std::string as_string () const;

  std::vector<GenericArg> &get_generic_args () { return generic_args; }

  std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }

  const std::vector<GenericArgsBinding> &get_binding_args () const
  {
    return binding_args;
  }

  std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; };

  const std::vector<Lifetime> &get_lifetime_args () const
  {
    return lifetime_args;
  };

  location_t get_locus () const { return locus; }
};

/* A segment of a path in expression, including an identifier aspect and maybe
 * generic args */
class PathExprSegment
{ // or should this extend PathIdentSegment?
private:
  PathIdentSegment segment_name;
  GenericArgs generic_args;
  location_t locus;
  NodeId node_id;

public:
  // Returns true if there are any generic arguments
  bool has_generic_args () const { return generic_args.has_generic_args (); }

  // Constructor for segment (from IdentSegment and GenericArgs)
  PathExprSegment (PathIdentSegment segment_name, location_t locus,
		   GenericArgs generic_args = GenericArgs::create_empty ())
    : segment_name (std::move (segment_name)),
      generic_args (std::move (generic_args)), locus (locus),
      node_id (Analysis::Mappings::get ().get_next_node_id ())
  {}

  /* Constructor for segment with generic arguments (from segment name and all
   * args) */
  PathExprSegment (std::string segment_name, location_t locus,
		   std::vector<Lifetime> lifetime_args = {},
		   std::vector<GenericArg> generic_args = {},
		   std::vector<GenericArgsBinding> binding_args = {})
    : segment_name (PathIdentSegment (std::move (segment_name), locus)),
      generic_args (GenericArgs (std::move (lifetime_args),
				 std::move (generic_args),
				 std::move (binding_args))),
      locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
  {}

  // Returns whether path expression segment is in an error state.
  bool is_error () const { return segment_name.is_error (); }

  // Creates an error-state path expression segment.
  static PathExprSegment create_error ()
  {
    return PathExprSegment (PathIdentSegment::create_error (), UNDEF_LOCATION);
  }

  std::string as_string () const;

  location_t get_locus () const { return locus; }

  // TODO: is this better? Or is a "vis_pattern" better?
  GenericArgs &get_generic_args ()
  {
    rust_assert (has_generic_args ());
    return generic_args;
  }

  PathIdentSegment &get_ident_segment () { return segment_name; }
  const PathIdentSegment &get_ident_segment () const { return segment_name; }

  NodeId get_node_id () const { return node_id; }

  bool is_super_path_seg () const
  {
    return !has_generic_args () && get_ident_segment ().is_super_path_seg ();
  }

  bool is_crate_path_seg () const
  {
    return !has_generic_args () && get_ident_segment ().is_crate_path_seg ();
  }

  bool is_lower_self_seg () const
  {
    return !has_generic_args () && get_ident_segment ().is_lower_self_seg ();
  }
};

// AST node representing a pattern that involves a "path" - abstract base
// class
class Path : public Pattern
{
public:
  enum class Kind
  {
    LangItem,
    Regular,
  };

  Path (std::vector<PathExprSegment> segments)
    : segments (std::move (segments)), lang_item (tl::nullopt),
      kind (Kind::Regular)
  {}

  Path (LangItem::Kind lang_item)
    : segments ({}), lang_item (lang_item), kind (Kind::LangItem)
  {}

  // Returns whether path has segments.
  bool has_segments () const
  {
    rust_assert (kind == Kind::Regular);
    return !segments.empty ();
  }

  /* Converts path segments to their equivalent SimplePath segments if
   * possible, and creates a SimplePath from them. */
  SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const;

  /* Returns whether the path is a single segment (excluding qualified path
   * initial as segment). */
  bool is_single_segment () const
  {
    rust_assert (kind == Kind::Regular);
    return segments.size () == 1;
  }

  std::string as_string () const override;

  bool is_lang_item () const { return kind == Kind::LangItem; }

  // TODO: this seems kinda dodgy
  std::vector<PathExprSegment> &get_segments ()
  {
    rust_assert (kind == Kind::Regular);
    return segments;
  }
  const std::vector<PathExprSegment> &get_segments () const
  {
    rust_assert (kind == Kind::Regular);
    return segments;
  }

  LangItem::Kind get_lang_item () const
  {
    rust_assert (kind == Kind::LangItem);
    return *lang_item;
  }

  Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
  Path::Kind get_path_kind () { return kind; }

protected:
  std::vector<PathExprSegment> segments;
  tl::optional<LangItem::Kind> lang_item;

  Path::Kind kind;
};

/* AST node representing a path-in-expression pattern (path that allows
 * generic arguments) */
class PathInExpression : public Path, public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  bool has_opening_scope_resolution;
  location_t locus;
  NodeId _node_id;

  bool marked_for_strip;

public:
  std::string as_string () const override;

  // Constructor
  PathInExpression (std::vector<PathExprSegment> path_segments,
		    std::vector<Attribute> outer_attrs, location_t locus,
		    bool has_opening_scope_resolution = false)
    : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
      has_opening_scope_resolution (has_opening_scope_resolution),
      locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()),
      marked_for_strip (false)
  {}

  PathInExpression (LangItem::Kind lang_item,
		    std::vector<Attribute> outer_attrs, location_t locus)
    : Path (lang_item), outer_attrs (std::move (outer_attrs)),
      has_opening_scope_resolution (false), locus (locus),
      _node_id (Analysis::Mappings::get ().get_next_node_id ()),
      marked_for_strip (false)
  {}

  // Creates an error state path in expression.
  static PathInExpression create_error ()
  {
    return PathInExpression (std::vector<PathExprSegment> (), {},
			     UNDEF_LOCATION);
  }

  // Returns whether path in expression is in an error state.
  bool is_error () const { return !has_segments (); }

  /* Converts PathInExpression to SimplePath if possible (i.e. no generic
   * arguments). Otherwise returns an empty SimplePath. */
  SimplePath as_simple_path () const
  {
    /* delegate to parent class as can't access segments. however,
     * QualifiedPathInExpression conversion to simple path wouldn't make
     * sense, so the method in the parent class should be protected, not
     * public. Have to pass in opening scope resolution as parent class has no
     * access to it.
     */
    return convert_to_simple_path (has_opening_scope_resolution);
  }

  location_t get_locus () const override final { return locus; }

  void accept_vis (ASTVisitor &vis) override;

  void mark_for_strip () override { marked_for_strip = true; }
  bool is_marked_for_strip () const override { return marked_for_strip; }

  bool opening_scope_resolution () const
  {
    return has_opening_scope_resolution;
  }

  NodeId get_node_id () const override { return _node_id; }

  const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
  std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  PathExprSegment &get_final_segment () { return get_segments ().back (); }
  const PathExprSegment &get_final_segment () const
  {
    return get_segments ().back ();
  }

  Expr::Kind get_expr_kind () const override
  {
    return Expr::Kind::PathInExpression;
  }

protected:
  /* Use covariance to implement clone function as returning this object
   * rather than base */
  PathInExpression *clone_pattern_impl () const final override
  {
    return clone_path_in_expression_impl ();
  }

  /* Use covariance to implement clone function as returning this object
   * rather than base */
  PathInExpression *clone_expr_without_block_impl () const final override
  {
    return clone_path_in_expression_impl ();
  }

  /*virtual*/ PathInExpression *clone_path_in_expression_impl () const
  {
    return new PathInExpression (*this);
  }
};

/* Base class for segments used in type paths - not abstract (represents an
 * ident-only segment) */
class TypePathSegment
{
public:
  enum SegmentType
  {
    REG,
    GENERIC,
    FUNCTION
  };

private:
  tl::optional<LangItem::Kind> lang_item;
  tl::optional<PathIdentSegment> ident_segment;
  location_t locus;

protected:
  /* This is protected because it is only really used by derived classes, not
   * the base. */
  bool has_separating_scope_resolution;
  NodeId node_id;

public:
  // Clone function implementation - not pure virtual as overrided by
  // subclasses
  virtual TypePathSegment *clone_type_path_segment_impl () const
  {
    return new TypePathSegment (*this);
  }

public:
  virtual ~TypePathSegment () {}

  virtual SegmentType get_type () const { return SegmentType::REG; }

  // Unique pointer custom clone function
  std::unique_ptr<TypePathSegment> clone_type_path_segment () const
  {
    return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ());
  }

  TypePathSegment (PathIdentSegment ident_segment,
		   bool has_separating_scope_resolution, location_t locus)
    : lang_item (tl::nullopt), ident_segment (std::move (ident_segment)),
      locus (locus),
      has_separating_scope_resolution (has_separating_scope_resolution),
      node_id (Analysis::Mappings::get ().get_next_node_id ())
  {}

  TypePathSegment (LangItem::Kind lang_item, location_t locus)
    : lang_item (lang_item), ident_segment (tl::nullopt), locus (locus),
      has_separating_scope_resolution (false),
      node_id (Analysis::Mappings::get ().get_next_node_id ())
  {}

  TypePathSegment (std::string segment_name,
		   bool has_separating_scope_resolution, location_t locus)
    : lang_item (tl::nullopt),
      ident_segment (PathIdentSegment (std::move (segment_name), locus)),
      locus (locus),
      has_separating_scope_resolution (has_separating_scope_resolution),
      node_id (Analysis::Mappings::get ().get_next_node_id ())
  {}

  TypePathSegment (TypePathSegment const &other)
    : lang_item (other.lang_item), ident_segment (other.ident_segment),
      locus (other.locus),
      has_separating_scope_resolution (other.has_separating_scope_resolution),
      node_id (other.node_id)
  {}

  TypePathSegment &operator= (TypePathSegment const &other)
  {
    ident_segment = other.ident_segment;
    lang_item = other.lang_item;
    locus = other.locus;
    has_separating_scope_resolution = other.has_separating_scope_resolution;
    node_id = other.node_id;

    return *this;
  }

  TypePathSegment (TypePathSegment &&other) = default;
  TypePathSegment &operator= (TypePathSegment &&other) = default;

  virtual std::string as_string () const
  {
    if (lang_item.has_value ())
      return LangItem::PrettyString (*lang_item);

    return ident_segment->as_string ();
  }

  /* Returns whether the type path segment is in an error state. May be
   * virtual in future. */
  bool is_error () const
  {
    rust_assert (ident_segment);
    return ident_segment->is_error ();
  }

  /* Returns whether segment is identifier only (as opposed to generic args or
   * function). Overridden in derived classes with other segments. */
  virtual bool is_ident_only () const { return true; }

  bool is_lang_item () const { return lang_item.has_value (); }

  location_t get_locus () const { return locus; }

  // not pure virtual as class not abstract
  virtual void accept_vis (ASTVisitor &vis);

  bool get_separating_scope_resolution () const
  {
    return has_separating_scope_resolution;
  }

  PathIdentSegment &get_ident_segment ()
  {
    rust_assert (!is_lang_item ());
    return *ident_segment;
  };

  const PathIdentSegment &get_ident_segment () const
  {
    rust_assert (!is_lang_item ());
    return *ident_segment;
  };

  LangItem::Kind get_lang_item () const
  {
    rust_assert (is_lang_item ());
    return *lang_item;
  }

  NodeId get_node_id () const { return node_id; }

  bool is_crate_path_seg () const
  {
    return get_ident_segment ().is_crate_path_seg ();
  }
  bool is_super_path_seg () const
  {
    return get_ident_segment ().is_super_path_seg ();
  }
  bool is_big_self_seg () const
  {
    return get_ident_segment ().is_big_self_seg ();
  }
  bool is_lower_self_seg () const
  {
    return get_ident_segment ().is_lower_self_seg ();
  }
};

// Segment used in type path with generic args
class TypePathSegmentGeneric : public TypePathSegment
{
  GenericArgs generic_args;

public:
  SegmentType get_type () const override { return SegmentType::GENERIC; }

  bool has_generic_args () const { return generic_args.has_generic_args (); }

  bool is_ident_only () const override { return false; }

  // Constructor with PathIdentSegment and GenericArgs
  TypePathSegmentGeneric (PathIdentSegment ident_segment,
			  bool has_separating_scope_resolution,
			  GenericArgs generic_args, location_t locus)
    : TypePathSegment (std::move (ident_segment),
		       has_separating_scope_resolution, locus),
      generic_args (std::move (generic_args))
  {}

  TypePathSegmentGeneric (LangItem::Kind lang_item, GenericArgs generic_args,
			  location_t locus)
    : TypePathSegment (lang_item, locus),
      generic_args (std::move (generic_args))
  {}

  // Constructor from segment name and all args
  TypePathSegmentGeneric (std::string segment_name,
			  bool has_separating_scope_resolution,
			  std::vector<Lifetime> lifetime_args,
			  std::vector<GenericArg> generic_args,
			  std::vector<GenericArgsBinding> binding_args,
			  location_t locus)
    : TypePathSegment (std::move (segment_name),
		       has_separating_scope_resolution, locus),
      generic_args (GenericArgs (std::move (lifetime_args),
				 std::move (generic_args),
				 std::move (binding_args)))
  {}

  // Copy constructor with vector clone
  TypePathSegmentGeneric (TypePathSegmentGeneric const &other)
    : TypePathSegment (other), generic_args (other.generic_args)
  {}

  // Overloaded assignment operator with vector clone
  TypePathSegmentGeneric &operator= (TypePathSegmentGeneric const &other)
  {
    generic_args = other.generic_args;

    return *this;
  }

  // move constructors
  TypePathSegmentGeneric (TypePathSegmentGeneric &&other) = default;
  TypePathSegmentGeneric &operator= (TypePathSegmentGeneric &&other) = default;

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_pattern" better?
  GenericArgs &get_generic_args ()
  {
    rust_assert (has_generic_args ());
    return generic_args;
  }

  // Use covariance to override base class method
  TypePathSegmentGeneric *clone_type_path_segment_impl () const override
  {
    return new TypePathSegmentGeneric (*this);
  }
};

// A function as represented in a type path
struct TypePathFunction
{
private:
  // TODO: remove
  /*bool has_inputs;
  TypePathFnInputs inputs;*/
  // inlined from TypePathFnInputs
  std::vector<std::unique_ptr<Type>> inputs;

  // bool has_type;
  std::unique_ptr<Type> return_type;

  // FIXME: think of better way to mark as invalid than taking up storage
  bool is_invalid;

  location_t locus;

protected:
  // Constructor only used to create invalid type path functions.
  TypePathFunction (bool is_invalid, location_t locus)
    : is_invalid (is_invalid), locus (locus)
  {}

public:
  // Returns whether the return type of the function has been specified.
  bool has_return_type () const { return return_type != nullptr; }

  // Returns whether the function has inputs.
  bool has_inputs () const { return !inputs.empty (); }

  // Returns whether function is in an error state.
  bool is_error () const { return is_invalid; }

  // Creates an error state function.
  static TypePathFunction create_error ()
  {
    return TypePathFunction (true, UNDEF_LOCATION);
  }

  // Constructor
  TypePathFunction (std::vector<std::unique_ptr<Type>> inputs, location_t locus,
		    std::unique_ptr<Type> type = nullptr)
    : inputs (std::move (inputs)), return_type (std::move (type)),
      is_invalid (false), locus (locus)
  {}

  // Copy constructor with clone
  TypePathFunction (TypePathFunction const &other)
    : is_invalid (other.is_invalid)
  {
    // guard to protect from null pointer dereference
    if (other.return_type != nullptr)
      return_type = other.return_type->clone_type ();

    inputs.reserve (other.inputs.size ());
    for (const auto &e : other.inputs)
      inputs.push_back (e->clone_type ());
  }

  ~TypePathFunction () = default;

  // Overloaded assignment operator to clone type
  TypePathFunction &operator= (TypePathFunction const &other)
  {
    is_invalid = other.is_invalid;

    // guard to protect from null pointer dereference
    if (other.return_type != nullptr)
      return_type = other.return_type->clone_type ();
    else
      return_type = nullptr;

    inputs.reserve (other.inputs.size ());
    for (const auto &e : other.inputs)
      inputs.push_back (e->clone_type ());

    return *this;
  }

  // move constructors
  TypePathFunction (TypePathFunction &&other) = default;
  TypePathFunction &operator= (TypePathFunction &&other) = default;

  std::string as_string () const;

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<std::unique_ptr<Type>> &get_params () const
  {
    return inputs;
  }
  std::vector<std::unique_ptr<Type>> &get_params () { return inputs; }

  // TODO: is this better? Or is a "vis_pattern" better?
  Type &get_return_type ()
  {
    rust_assert (has_return_type ());
    return *return_type;
  }

  std::unique_ptr<Type> &get_return_type_ptr ()
  {
    rust_assert (has_return_type ());
    return return_type;
  }

  location_t get_locus () const { return locus; }
};

// Segment used in type path with a function argument
class TypePathSegmentFunction : public TypePathSegment
{
  TypePathFunction function_path;

public:
  SegmentType get_type () const override { return SegmentType::FUNCTION; }

  // Constructor with PathIdentSegment and TypePathFn
  TypePathSegmentFunction (PathIdentSegment ident_segment,
			   bool has_separating_scope_resolution,
			   TypePathFunction function_path, location_t locus)
    : TypePathSegment (std::move (ident_segment),
		       has_separating_scope_resolution, locus),
      function_path (std::move (function_path))
  {}

  // Constructor with segment name and TypePathFn
  TypePathSegmentFunction (std::string segment_name,
			   bool has_separating_scope_resolution,
			   TypePathFunction function_path, location_t locus)
    : TypePathSegment (std::move (segment_name),
		       has_separating_scope_resolution, locus),
      function_path (std::move (function_path))
  {}

  std::string as_string () const override;

  bool is_ident_only () const override { return false; }

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_pattern" better?
  TypePathFunction &get_type_path_function ()
  {
    rust_assert (!function_path.is_error ());
    return function_path;
  }

  // Use covariance to override base class method
  TypePathSegmentFunction *clone_type_path_segment_impl () const override
  {
    return new TypePathSegmentFunction (*this);
  }
};

class TypePath : public TypeNoBounds
{
  bool has_opening_scope_resolution;
  std::vector<std::unique_ptr<TypePathSegment>> segments;
  location_t locus;

protected:
  /* Use covariance to implement clone function as returning this object
   * rather than base */
  TypePath *clone_type_no_bounds_impl () const override
  {
    return new TypePath (*this);
  }

public:
  /* Returns whether the TypePath has an opening scope resolution operator
   * (i.e. is global path or crate-relative path, not module-relative) */
  bool has_opening_scope_resolution_op () const
  {
    return has_opening_scope_resolution;
  }

  // Returns whether the TypePath is in an invalid state.
  bool is_error () const { return segments.empty (); }

  // Creates an error state TypePath.
  static TypePath create_error ()
  {
    return TypePath (std::vector<std::unique_ptr<TypePathSegment>> (),
		     UNDEF_LOCATION);
  }

  // Constructor
  TypePath (std::vector<std::unique_ptr<TypePathSegment>> segments,
	    location_t locus, bool has_opening_scope_resolution = false)
    : TypeNoBounds (),
      has_opening_scope_resolution (has_opening_scope_resolution),
      segments (std::move (segments)), locus (locus)
  {}

  TypePath (LangItem::Kind lang_item,
	    std::vector<std::unique_ptr<TypePathSegment>> segments,
	    location_t locus, bool has_opening_scope_resolution = false)
    : TypeNoBounds (),
      has_opening_scope_resolution (has_opening_scope_resolution),
      segments (std::move (segments)), locus (locus)
  {}

  // Copy constructor with vector clone
  TypePath (TypePath const &other)
    : has_opening_scope_resolution (other.has_opening_scope_resolution),
      locus (other.locus)
  {
    node_id = other.node_id;
    segments.reserve (other.segments.size ());
    for (const auto &e : other.segments)
      segments.push_back (e->clone_type_path_segment ());
  }

  // Overloaded assignment operator with clone
  TypePath &operator= (TypePath const &other)
  {
    node_id = other.node_id;
    has_opening_scope_resolution = other.has_opening_scope_resolution;
    locus = other.locus;

    segments.reserve (other.segments.size ());
    for (const auto &e : other.segments)
      segments.push_back (e->clone_type_path_segment ());

    return *this;
  }

  // move constructors
  TypePath (TypePath &&other) = default;
  TypePath &operator= (TypePath &&other) = default;

  std::string as_string () const override;

  /* Converts TypePath to SimplePath if possible (i.e. no generic or function
   * arguments). Otherwise returns an empty SimplePath. */
  SimplePath as_simple_path () const;

  // Creates a trait bound with a clone of this type path as its only element.
  TraitBound *to_trait_bound (bool in_parens) const override;

  location_t get_locus () const override final { return locus; }
  NodeId get_node_id () const { return node_id; }

  void mark_for_strip () override {}
  bool is_marked_for_strip () const override { return false; }

  void accept_vis (ASTVisitor &vis) override;

  // TODO: this seems kinda dodgy
  std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
  {
    return segments;
  }
  const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
  {
    return segments;
  }

  size_t get_num_segments () const { return segments.size (); }
};

struct QualifiedPathType
{
private:
  std::unique_ptr<Type> type_to_invoke_on;
  TypePath trait_path;
  location_t locus;
  NodeId node_id;

public:
  // Constructor
  QualifiedPathType (std::unique_ptr<Type> invoke_on_type,
		     location_t locus = UNDEF_LOCATION,
		     TypePath trait_path = TypePath::create_error ())
    : type_to_invoke_on (std::move (invoke_on_type)), trait_path (trait_path),
      locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
  {}

  // Copy constructor uses custom deep copy for Type to preserve polymorphism
  QualifiedPathType (QualifiedPathType const &other)
    : trait_path (other.trait_path), locus (other.locus)
  {
    node_id = other.node_id;
    // guard to prevent null dereference
    if (other.type_to_invoke_on != nullptr)
      type_to_invoke_on = other.type_to_invoke_on->clone_type ();
  }

  // default destructor
  ~QualifiedPathType () = default;

  // overload assignment operator to use custom clone method
  QualifiedPathType &operator= (QualifiedPathType const &other)
  {
    node_id = other.node_id;
    trait_path = other.trait_path;
    locus = other.locus;

    // guard to prevent null dereference
    if (other.type_to_invoke_on != nullptr)
      type_to_invoke_on = other.type_to_invoke_on->clone_type ();
    else
      type_to_invoke_on = nullptr;

    return *this;
  }

  // move constructor
  QualifiedPathType (QualifiedPathType &&other) = default;
  QualifiedPathType &operator= (QualifiedPathType &&other) = default;

  // Returns whether the qualified path type has a rebind as clause.
  bool has_as_clause () const { return !trait_path.is_error (); }

  // Returns whether the qualified path type is in an error state.
  bool is_error () const { return type_to_invoke_on == nullptr; }

  // Creates an error state qualified path type.
  static QualifiedPathType create_error ()
  {
    return QualifiedPathType (nullptr);
  }

  std::string as_string () const;

  location_t get_locus () const { return locus; }

  // TODO: is this better? Or is a "vis_pattern" better?
  Type &get_type ()
  {
    rust_assert (type_to_invoke_on != nullptr);
    return *type_to_invoke_on;
  }

  std::unique_ptr<Type> &get_type_ptr ()
  {
    rust_assert (type_to_invoke_on != nullptr);
    return type_to_invoke_on;
  }

  // TODO: is this better? Or is a "vis_pattern" better?
  TypePath &get_as_type_path ()
  {
    rust_assert (has_as_clause ());
    return trait_path;
  }

  NodeId get_node_id () const { return node_id; }
};

/* AST node representing a qualified path-in-expression pattern (path that
 * allows specifying trait functions) */
class QualifiedPathInExpression : public Path, public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  QualifiedPathType path_type;
  location_t locus;
  NodeId _node_id;

public:
  std::string as_string () const override;

  QualifiedPathInExpression (QualifiedPathType qual_path_type,
			     std::vector<PathExprSegment> path_segments,
			     std::vector<Attribute> outer_attrs,
			     location_t locus)
    : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
      path_type (std::move (qual_path_type)), locus (locus),
      _node_id (Analysis::Mappings::get ().get_next_node_id ())
  {}

  /* TODO: maybe make a shortcut constructor that has QualifiedPathType
   * elements as params */

  // Returns whether qualified path in expression is in an error state.
  bool is_error () const { return path_type.is_error (); }

  // Creates an error qualified path in expression.
  static QualifiedPathInExpression create_error ()
  {
    return QualifiedPathInExpression (QualifiedPathType::create_error (), {},
				      {}, UNDEF_LOCATION);
  }

  location_t get_locus () const override final { return locus; }

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if path_type is error, so base stripping on that.
  void mark_for_strip () override
  {
    path_type = QualifiedPathType::create_error ();
  }
  bool is_marked_for_strip () const override { return is_error (); }

  // TODO: is this better? Or is a "vis_pattern" better?
  QualifiedPathType &get_qualified_path_type ()
  {
    rust_assert (!path_type.is_error ());
    return path_type;
  }

  const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
  std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  NodeId get_node_id () const override { return _node_id; }

  Expr::Kind get_expr_kind () const override
  {
    return Expr::Kind::QualifiedPathInExpression;
  }

protected:
  /* Use covariance to implement clone function as returning this object
   * rather than base */
  QualifiedPathInExpression *clone_pattern_impl () const final override
  {
    return clone_qual_path_in_expression_impl ();
  }

  /* Use covariance to implement clone function as returning this object
   * rather than base */
  QualifiedPathInExpression *
  clone_expr_without_block_impl () const final override
  {
    return clone_qual_path_in_expression_impl ();
  }

  /*virtual*/ QualifiedPathInExpression *
  clone_qual_path_in_expression_impl () const
  {
    return new QualifiedPathInExpression (*this);
  }
};

/* Represents a qualified path in a type; used for disambiguating trait
 * function calls */
class QualifiedPathInType : public TypeNoBounds
{
  QualifiedPathType path_type;
  std::unique_ptr<TypePathSegment> associated_segment;
  std::vector<std::unique_ptr<TypePathSegment>> segments;
  location_t locus;

protected:
  /* Use covariance to implement clone function as returning this object
   * rather than base */
  QualifiedPathInType *clone_type_no_bounds_impl () const override
  {
    return new QualifiedPathInType (*this);
  }

public:
  QualifiedPathInType (
    QualifiedPathType qual_path_type,
    std::unique_ptr<TypePathSegment> associated_segment,
    std::vector<std::unique_ptr<TypePathSegment>> path_segments,
    location_t locus)
    : path_type (std::move (qual_path_type)),
      associated_segment (std::move (associated_segment)),
      segments (std::move (path_segments)), locus (locus)
  {}

  // Copy constructor with vector clone
  QualifiedPathInType (QualifiedPathInType const &other)
    : path_type (other.path_type), locus (other.locus)
  {
    auto seg = other.associated_segment->clone_type_path_segment_impl ();
    associated_segment = std::unique_ptr<TypePathSegment> (seg);

    segments.reserve (other.segments.size ());
    for (const auto &e : other.segments)
      segments.push_back (e->clone_type_path_segment ());
  }

  // Overloaded assignment operator with vector clone
  QualifiedPathInType &operator= (QualifiedPathInType const &other)
  {
    auto seg = other.associated_segment->clone_type_path_segment_impl ();
    associated_segment = std::unique_ptr<TypePathSegment> (seg);

    path_type = other.path_type;
    locus = other.locus;

    segments.reserve (other.segments.size ());
    for (const auto &e : other.segments)
      segments.push_back (e->clone_type_path_segment ());

    return *this;
  }

  // move constructors
  QualifiedPathInType (QualifiedPathInType &&other) = default;
  QualifiedPathInType &operator= (QualifiedPathInType &&other) = default;

  // Returns whether qualified path in type is in an error state.
  bool is_error () const { return path_type.is_error (); }

  // Creates an error state qualified path in type.
  static QualifiedPathInType create_error ()
  {
    return QualifiedPathInType (
      QualifiedPathType::create_error (), nullptr,
      std::vector<std::unique_ptr<TypePathSegment>> (), UNDEF_LOCATION);
  }

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_pattern" better?
  QualifiedPathType &get_qualified_path_type ()
  {
    rust_assert (!path_type.is_error ());
    return path_type;
  }

  std::unique_ptr<TypePathSegment> &get_associated_segment ()
  {
    return associated_segment;
  }

  // TODO: this seems kinda dodgy
  std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
  {
    return segments;
  }
  const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
  {
    return segments;
  }

  location_t get_locus () const override final { return locus; }
};
} // namespace AST
} // namespace Rust

#endif
