]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Rework function special parameters
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Sun, 12 Nov 2023 20:44:07 +0000 (21:44 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 18:13:14 +0000 (19:13 +0100)
Make self param and variadic param Param, introduce Param class and make
function parameters param too.
Self can now be represented as a standard parameter and is thus no longer
required as a separate function attribute.
Prevent self pointers and allow self in standard functions during parsing
so they could be rejected at a later stage.

gcc/rust/ChangeLog:

* ast/rust-ast-collector.cc (TokenCollector::visit): Add visitor for
VariadicParam and remove Self parameter visitor from Function visit.
* expand/rust-cfg-strip.cc (CfgStrip::maybe_strip_self_param): Remove
function.
(CfgStrip::maybe_strip_trait_method_decl): Remove self parameter visit.
(CfgStrip::maybe_strip_function_params): Handle new function
parameters.
(CfgStrip::visit): Handle VariadicParam, SelfParam and FunctionParam.
* expand/rust-expand-visitor.cc (ExpandVisitor::expand_self_param):
Remove function.
(ExpandVisitor::expand_trait_method_decl): Do not visit self parameter.
(ExpandVisitor::visit): Add visit for VariadicParam, FunctionParam and
SelfParam.
(ExpandVisitor::expand_function_params): Visit parameters instead.
* expand/rust-expand-visitor.h: Update function prototypes.
* resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Update visit
with new parameters.
(ResolveTraitItems::visit): Likewise.
* resolve/rust-early-name-resolver.cc (EarlyNameResolver::visit):
Update visit functions with the new visitor functions for VariadicParam
SelfParam and FunctionParam.
* resolve/rust-early-name-resolver.h: Update function prototypes.
* ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Update visitor
according to the new function parameter structures.
* ast/rust-ast-visitor.h: Update prototypes and add visitor virtual
functions for SelfParam, FunctionParam and VariadicParam.
* ast/rust-ast.cc (Function::Function): Move constructor in
implementation instead of header.
(Function::operator=): Likewise.
(Function::as_string): Update function with pointer dereference.
(VariadicParam::as_string): Likewise.
(TraitFunctionDecl::as_string): Likewise.
(TraitMethodDecl::as_string): Likewise.
(FunctionParam::accept_vis): Add function for visitor.
(SelfParam::accept_vis): Likewise.
(VariadicParam::accept_vis): Likewise.
(TraitItemFunc::TraitItemFunc): Move constructor to implementation
file.
(TraitItemFunc::operator=): Likewise.
(TraitItemMethod::TraitItemMethod): Likewise.
(TraitItemMethod::operator=): Likewise.
* ast/rust-item.h (class Function): Remove self optional member.
(class TraitMethodDecl): Likewise.
(class TraitFunctionDecl): Likewise.
(class Param): Add abstract parameter class.
(class SelfParam): Inherit from Param and remove parameter common
members.
(class FunctionParam): Likewise.
(class VariadicParam): Likewise.
(struct Visibility): Move structure declaration.
(class VisItem):  Likewise.
* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
a self parameter check during AST validation.
* checks/errors/rust-ast-validation.h: Add function prototype.
* expand/rust-derive-clone.cc (DeriveClone::clone_fn): Update function
constructor.
* hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_self): Rework
function for the new parameters.
(ASTLoweringBase::visit): Add visit functions for VariadicParam,
FunctionParam and SelfParam.
* hir/rust-ast-lower-base.h: Update function prototypes.
* parse/rust-parse-impl.h (Parser::parse_function): Update function
according to new function representation.
(Parser::parse_function_param): Return vector of abstract param instead
of FunctionParam.
(Parser::parse_method): Update according to new representation.
(Parser::parse_trait_item): Likewise.
(Parser::parse_self_param): Error out with
self pointers and prevent the lexer from eating regular function
parameters. Update return type.
* parse/rust-parse.h: Update function return types.
* ast/rust-ast-collector.h: Add VariadicParam visit prototype.
* ast/rust-ast.h (struct Visibility): Move struct declaration.
(class VisItem): Likewise.
* ast/rust-expr.h: Update included files.
* checks/errors/rust-feature-gate.h: Add visitor functions for
SelfParam, FunctionParam and VariadicParam.
* expand/rust-cfg-strip.h: Update function prototypes.
* expand/rust-derive.h: Likewise.
* hir/rust-ast-lower-implitem.h: Handle special arguments.
* hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise.
* metadata/rust-export-metadata.cc (ExportContext::emit_function):
Likewise.
* resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Add visitor
functions.
* resolve/rust-ast-resolve-base.h: Update prototypes.
* resolve/rust-ast-resolve-stmt.h: Handle new parameter kind.
* resolve/rust-default-resolver.cc (DefaultResolver::visit): Likewise.
* resolve/rust-default-resolver.h: Update prototype.
* util/rust-attributes.cc (AttributeChecker::visit): Add visitor
functions for SelfParam and VariadicParam.
* util/rust-attributes.h: Add visit prototypes.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
34 files changed:
gcc/rust/ast/rust-ast-collector.cc
gcc/rust/ast/rust-ast-collector.h
gcc/rust/ast/rust-ast-visitor.cc
gcc/rust/ast/rust-ast-visitor.h
gcc/rust/ast/rust-ast.cc
gcc/rust/ast/rust-ast.h
gcc/rust/ast/rust-expr.h
gcc/rust/ast/rust-item.h
gcc/rust/checks/errors/rust-ast-validation.cc
gcc/rust/checks/errors/rust-ast-validation.h
gcc/rust/checks/errors/rust-feature-gate.h
gcc/rust/expand/rust-cfg-strip.cc
gcc/rust/expand/rust-cfg-strip.h
gcc/rust/expand/rust-derive-clone.cc
gcc/rust/expand/rust-derive.h
gcc/rust/expand/rust-expand-visitor.cc
gcc/rust/expand/rust-expand-visitor.h
gcc/rust/hir/rust-ast-lower-base.cc
gcc/rust/hir/rust-ast-lower-base.h
gcc/rust/hir/rust-ast-lower-implitem.h
gcc/rust/hir/rust-ast-lower-item.cc
gcc/rust/metadata/rust-export-metadata.cc
gcc/rust/parse/rust-parse-impl.h
gcc/rust/parse/rust-parse.h
gcc/rust/resolve/rust-ast-resolve-base.cc
gcc/rust/resolve/rust-ast-resolve-base.h
gcc/rust/resolve/rust-ast-resolve-item.cc
gcc/rust/resolve/rust-ast-resolve-stmt.h
gcc/rust/resolve/rust-default-resolver.cc
gcc/rust/resolve/rust-default-resolver.h
gcc/rust/resolve/rust-early-name-resolver.cc
gcc/rust/resolve/rust-early-name-resolver.h
gcc/rust/util/rust-attributes.cc
gcc/rust/util/rust-attributes.h

index 83260720aff7df48db8df9a0a4ed2c2bfc340e42..05c9630bf523ac9ad911d541f0b4b4635777b6fe 100644 (file)
@@ -16,6 +16,7 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 #include "rust-ast-collector.h"
+#include "rust-item.h"
 
 namespace Rust {
 namespace AST {
@@ -190,6 +191,17 @@ TokenCollector::visit (FunctionParam &param)
     }
 }
 
+void
+TokenCollector::visit (VariadicParam &param)
+{
+  if (param.has_pattern ())
+    {
+      visit (param.get_pattern ());
+      push (Rust::Token::make (COLON, UNDEF_LOCATION));
+    }
+  push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION));
+}
+
 void
 TokenCollector::visit (Attribute &attrib)
 {
@@ -1783,13 +1795,6 @@ TokenCollector::visit (Function &function)
 
   push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
 
-  if (function.has_self_param ())
-    {
-      visit (function.get_self_param ());
-      if (!function.get_function_params ().empty ())
-       push (Rust::Token::make (COMMA, UNDEF_LOCATION));
-    }
-
   visit_items_joined_by_separator (function.get_function_params ());
   push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
 
@@ -2069,13 +2074,7 @@ TokenCollector::visit (TraitItemMethod &item)
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
   push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
 
-  visit (method.get_self_param ());
-
-  if (!method.get_function_params ().empty ())
-    {
-      push (Rust::Token::make (COMMA, UNDEF_LOCATION));
-      visit_items_joined_by_separator (method.get_function_params (), COMMA);
-    }
+  visit_items_joined_by_separator (method.get_function_params (), COMMA);
 
   push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
 
index 47655286dd9eca44e248266bd29082b43aca55e7..20ffd8e65abf283a80f0eaa96d2effcfdea010fb 100644 (file)
@@ -163,6 +163,7 @@ public:
   void visit (Literal &lit, location_t locus = UNDEF_LOCATION);
 
   void visit (FunctionParam &param);
+  void visit (VariadicParam &param);
   void visit (Attribute &attrib);
   void visit (Visibility &vis);
   void visit (std::vector<std::unique_ptr<GenericParam>> &params);
index b4d1011a03eae6b8c3685dc7631604b6b2e06846..d8395820892e432f6a6c01aaba14ec88cac09b26 100644 (file)
@@ -707,12 +707,6 @@ void
 DefaultASTVisitor::visit (AST::FunctionQualifiers &qualifiers)
 {}
 
-void
-DefaultASTVisitor::visit (AST::SelfParam &self)
-{
-  visit (self.get_lifetime ());
-}
-
 void
 DefaultASTVisitor::visit (AST::WhereClause &where)
 {
@@ -726,7 +720,18 @@ DefaultASTVisitor::visit (AST::FunctionParam &param)
   if (param.has_name ())
     visit (param.get_pattern ());
 
-  if (!param.is_variadic ())
+  visit (param.get_type ());
+}
+
+void
+DefaultASTVisitor::visit (AST::SelfParam &param)
+{
+  visit_outer_attrs (param);
+
+  if (param.has_lifetime ())
+    visit (param.get_lifetime ());
+
+  if (param.has_type ())
     visit (param.get_type ());
 }
 
@@ -1438,6 +1443,13 @@ DefaultASTVisitor::visit (AST::BareFunctionType &type)
     visit (type.get_return_type ());
 }
 
+void
+DefaultASTVisitor::visit (AST::VariadicParam &param)
+{
+  if (param.has_pattern ())
+    visit (param.get_pattern ());
+}
+
 void
 ContextualASTVisitor::visit (AST::Crate &crate)
 {
index d6340e745c9d2e9e66452bc1b1437c3bf8777ebb..e5be44157ed63bc9379dfada951892b424fc2d85 100644 (file)
@@ -23,6 +23,7 @@
 // full include not required - only forward decls
 #include "rust-ast-full-decls.h"
 #include "rust-ast.h"
+#include "rust-item.h"
 #include "rust-system.h"
 
 namespace Rust {
@@ -129,6 +130,10 @@ public:
 
   // rust-item.h
   virtual void visit (TypeParam &param) = 0;
+  virtual void visit (SelfParam &param) = 0;
+  virtual void visit (FunctionParam &param) = 0;
+  virtual void visit (VariadicParam &param) = 0;
+
   // virtual void visit(WhereClauseItem& item) = 0;
   virtual void visit (LifetimeWhereClauseItem &item) = 0;
   virtual void visit (TypeBoundWhereClauseItem &item) = 0;
@@ -386,6 +391,9 @@ protected:
   virtual void visit (AST::SliceType &type) override;
   virtual void visit (AST::InferredType &type) override;
   virtual void visit (AST::BareFunctionType &type) override;
+  virtual void visit (AST::SelfParam &self) override;
+  virtual void visit (AST::FunctionParam &param) override;
+  virtual void visit (AST::VariadicParam &param) override;
 
   template <typename T> void visit (T &node);
 
@@ -406,9 +414,7 @@ protected:
   virtual void visit (AST::MatchArm &arm);
   virtual void visit (AST::Visibility &vis);
   virtual void visit (AST::FunctionQualifiers &qualifiers);
-  virtual void visit (AST::SelfParam &self);
   virtual void visit (AST::WhereClause &where);
-  virtual void visit (AST::FunctionParam &param);
   virtual void visit (AST::StructField &field);
   virtual void visit (AST::TupleField &field);
   virtual void visit (AST::TraitFunctionDecl &decl);
index cc0d6ec996f0b17140e1da99cbbd652e13bf60cc..43820d38e283a70c8d582ecbf3d82c1f784ac0f3 100644 (file)
@@ -1090,6 +1090,62 @@ Union::as_string () const
   return str;
 }
 
+Function::Function (Function const &other)
+  : VisItem (other), qualifiers (other.qualifiers),
+    function_name (other.function_name), where_clause (other.where_clause),
+    locus (other.locus), is_default (other.is_default)
+{
+  // guard to prevent null dereference (always required)
+  if (other.return_type != nullptr)
+    return_type = other.return_type->clone_type ();
+
+  // guard to prevent null dereference (only required if error state)
+  if (other.function_body != nullptr)
+    function_body = other.function_body->clone_block_expr ();
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  function_params.reserve (other.function_params.size ());
+  for (const auto &e : other.function_params)
+    function_params.push_back (e->clone_param ());
+}
+
+Function &
+Function::operator= (Function const &other)
+{
+  VisItem::operator= (other);
+  function_name = other.function_name;
+  qualifiers = other.qualifiers;
+  where_clause = other.where_clause;
+  // visibility = other.visibility->clone_visibility();
+  // outer_attrs = other.outer_attrs;
+  locus = other.locus;
+  is_default = other.is_default;
+
+  // guard to prevent null dereference (always required)
+  if (other.return_type != nullptr)
+    return_type = other.return_type->clone_type ();
+  else
+    return_type = nullptr;
+
+  // guard to prevent null dereference (only required if error state)
+  if (other.function_body != nullptr)
+    function_body = other.function_body->clone_block_expr ();
+  else
+    function_body = nullptr;
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  function_params.reserve (other.function_params.size ());
+  for (const auto &e : other.function_params)
+    function_params.push_back (e->clone_param ());
+
+  return *this;
+}
 std::string
 Function::as_string () const
 {
@@ -1149,7 +1205,7 @@ Function::as_string () const
       str += "(";
       for (; i != e; i++)
        {
-         str += (*i).as_string ();
+         str += (*i)->as_string ();
          if (e != i + 1)
            str += ", ";
        }
@@ -2245,6 +2301,33 @@ FunctionParam::as_string () const
   return param_name->as_string () + " : " + type->as_string ();
 }
 
+void
+FunctionParam::accept_vis (ASTVisitor &vis)
+{
+  vis.visit (*this);
+}
+
+void
+SelfParam::accept_vis (ASTVisitor &vis)
+{
+  vis.visit (*this);
+}
+
+void
+VariadicParam::accept_vis (ASTVisitor &vis)
+{
+  vis.visit (*this);
+}
+
+std::string
+VariadicParam::as_string () const
+{
+  if (has_pattern ())
+    return get_pattern ()->as_string () + " : ...";
+  else
+    return "...";
+}
+
 std::string
 FunctionQualifiers::as_string () const
 {
@@ -3013,6 +3096,33 @@ NamedFunctionParam::as_string () const
   return str;
 }
 
+TraitItemFunc::TraitItemFunc (TraitItemFunc const &other)
+  : TraitItem (other.locus), outer_attrs (other.outer_attrs), decl (other.decl)
+{
+  node_id = other.node_id;
+
+  // guard to prevent null dereference
+  if (other.block_expr != nullptr)
+    block_expr = other.block_expr->clone_block_expr ();
+}
+
+TraitItemFunc &
+TraitItemFunc::operator= (TraitItemFunc const &other)
+{
+  TraitItem::operator= (other);
+  outer_attrs = other.outer_attrs;
+  decl = other.decl;
+  locus = other.locus;
+  node_id = other.node_id;
+
+  // guard to prevent null dereference
+  if (other.block_expr != nullptr)
+    block_expr = other.block_expr->clone_block_expr ();
+  else
+    block_expr = nullptr;
+
+  return *this;
+}
 std::string
 TraitItemFunc::as_string () const
 {
@@ -3062,7 +3172,7 @@ TraitFunctionDecl::as_string () const
   if (has_params ())
     {
       for (const auto &param : function_params)
-       str += "\n  " + param.as_string ();
+       str += "\n  " + param->as_string ();
     }
   else
     {
@@ -3084,6 +3194,34 @@ TraitFunctionDecl::as_string () const
   return str;
 }
 
+TraitItemMethod::TraitItemMethod (TraitItemMethod const &other)
+  : TraitItem (other.locus), outer_attrs (other.outer_attrs), decl (other.decl)
+{
+  node_id = other.node_id;
+
+  // guard to prevent null dereference
+  if (other.block_expr != nullptr)
+    block_expr = other.block_expr->clone_block_expr ();
+}
+
+TraitItemMethod &
+TraitItemMethod::operator= (TraitItemMethod const &other)
+{
+  TraitItem::operator= (other);
+  outer_attrs = other.outer_attrs;
+  decl = other.decl;
+  locus = other.locus;
+  node_id = other.node_id;
+
+  // guard to prevent null dereference
+  if (other.block_expr != nullptr)
+    block_expr = other.block_expr->clone_block_expr ();
+  else
+    block_expr = nullptr;
+
+  return *this;
+}
+
 std::string
 TraitItemMethod::as_string () const
 {
@@ -3129,13 +3267,11 @@ TraitMethodDecl::as_string () const
        }
     }
 
-  str += "\n Self param: " + self_param.as_string ();
-
   str += "\n Function params: ";
   if (has_params ())
     {
       for (const auto &param : function_params)
-       str += "\n  " + param.as_string ();
+       str += "\n  " + param->as_string ();
     }
   else
     {
index 938268dd83a4a25dc25135b1d5a250ff91ae6d5b..67ae92fb42dbde871d75ad3023075a5ad2582aed 100644 (file)
@@ -1042,6 +1042,173 @@ protected:
   Item *clone_stmt_impl () const final override { return clone_item_impl (); }
 };
 
+// Visibility of item - if the item has it, then it is some form of public
+struct Visibility
+{
+public:
+  enum VisType
+  {
+    PRIV,
+    PUB,
+    PUB_CRATE,
+    PUB_SELF,
+    PUB_SUPER,
+    PUB_IN_PATH
+  };
+
+private:
+  VisType vis_type;
+  // Only assigned if vis_type is IN_PATH
+  SimplePath in_path;
+  location_t locus;
+
+  // should this store location info?
+
+public:
+  // Creates a Visibility - TODO make constructor protected or private?
+  Visibility (VisType vis_type, SimplePath in_path, location_t locus)
+    : vis_type (vis_type), in_path (std::move (in_path)), locus (locus)
+  {}
+
+  VisType get_vis_type () const { return vis_type; }
+
+  // Returns whether visibility is in an error state.
+  bool is_error () const
+  {
+    return vis_type == PUB_IN_PATH && in_path.is_empty ();
+  }
+
+  // Returns whether a visibility has a path
+  bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; }
+
+  // Returns whether visibility is public or not.
+  bool is_public () const { return vis_type != PRIV && !is_error (); }
+
+  location_t get_locus () const { return locus; }
+
+  // empty?
+  // Creates an error visibility.
+  static Visibility create_error ()
+  {
+    return Visibility (PUB_IN_PATH, SimplePath::create_empty (),
+                      UNDEF_LOCATION);
+  }
+
+  // Unique pointer custom clone function
+  /*std::unique_ptr<Visibility> clone_visibility() const {
+      return std::unique_ptr<Visibility>(clone_visibility_impl());
+  }*/
+
+  /* TODO: think of a way to only allow valid Visibility states - polymorphism
+   * is one idea but may be too resource-intensive. */
+
+  // Creates a public visibility with no further features/arguments.
+  // empty?
+  static Visibility create_public (location_t pub_vis_location)
+  {
+    return Visibility (PUB, SimplePath::create_empty (), pub_vis_location);
+  }
+
+  // Creates a public visibility with crate-relative paths
+  static Visibility create_crate (location_t crate_tok_location,
+                                 location_t crate_vis_location)
+  {
+    return Visibility (PUB_CRATE,
+                      SimplePath::from_str ("crate", crate_tok_location),
+                      crate_vis_location);
+  }
+
+  // Creates a public visibility with self-relative paths
+  static Visibility create_self (location_t self_tok_location,
+                                location_t self_vis_location)
+  {
+    return Visibility (PUB_SELF,
+                      SimplePath::from_str ("self", self_tok_location),
+                      self_vis_location);
+  }
+
+  // Creates a public visibility with parent module-relative paths
+  static Visibility create_super (location_t super_tok_location,
+                                 location_t super_vis_location)
+  {
+    return Visibility (PUB_SUPER,
+                      SimplePath::from_str ("super", super_tok_location),
+                      super_vis_location);
+  }
+
+  // Creates a private visibility
+  static Visibility create_private ()
+  {
+    return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION);
+  }
+
+  // Creates a public visibility with a given path or whatever.
+  static Visibility create_in_path (SimplePath in_path,
+                                   location_t in_path_vis_location)
+  {
+    return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location);
+  }
+
+  std::string as_string () const;
+  const SimplePath &get_path () const { return in_path; }
+  SimplePath &get_path () { return in_path; }
+
+protected:
+  // Clone function implementation - not currently virtual but may be if
+  // polymorphism used
+  /*virtual*/ Visibility *clone_visibility_impl () const
+  {
+    return new Visibility (*this);
+  }
+};
+// Item that supports visibility - abstract base class
+class VisItem : public Item
+{
+  Visibility visibility;
+  std::vector<Attribute> outer_attrs;
+
+protected:
+  // Visibility constructor
+  VisItem (Visibility visibility,
+          std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
+    : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs))
+  {}
+
+  // Visibility copy constructor
+  VisItem (VisItem const &other)
+    : visibility (other.visibility), outer_attrs (other.outer_attrs)
+  {}
+
+  // Overload assignment operator to clone
+  VisItem &operator= (VisItem const &other)
+  {
+    visibility = other.visibility;
+    outer_attrs = other.outer_attrs;
+
+    return *this;
+  }
+
+  // move constructors
+  VisItem (VisItem &&other) = default;
+  VisItem &operator= (VisItem &&other) = default;
+
+public:
+  /* Does the item have some kind of public visibility (non-default
+   * visibility)? */
+  bool has_visibility () const { return visibility.is_public (); }
+
+  std::string as_string () const override;
+
+  // TODO: this mutable getter seems really dodgy. Think up better way.
+  Visibility &get_visibility () { return visibility; }
+  const Visibility &get_visibility () const { return visibility; }
+
+  std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+  const std::vector<Attribute> &get_outer_attrs () const override
+  {
+    return outer_attrs;
+  }
+};
 // forward decl of ExprWithoutBlock
 class ExprWithoutBlock;
 
index 4dc240c4aa7560188107bd89fd7cbc86eac8210e..4830ae0d2d3843764341079493247f43646c763a 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "rust-ast.h"
 #include "rust-path.h"
+#include "rust-macro.h"
 #include "rust-operators.h"
 
 namespace Rust {
index 6d9791e7de79518d109c5ec1cdcc1446e5a50e85..8b53bc63a835540c7d38422113730fa523b4a278 100644 (file)
@@ -20,6 +20,8 @@
 #define RUST_AST_ITEM_H
 
 #include "rust-ast.h"
+#include "rust-hir-map.h"
+#include "rust-mapping-common.h"
 #include "rust-path.h"
 #include "rust-common.h"
 #include "rust-expr.h"
@@ -376,8 +378,46 @@ public:
   }
 };
 
+// Abstract class Param
+class Param : public Visitable
+{
+public:
+  Param (std::vector<Attribute> outer_attrs, location_t locus)
+    : outer_attrs (std::move (outer_attrs)), locus (locus),
+      node_id (Analysis::Mappings::get ()->get_next_node_id ())
+  {}
+
+  virtual ~Param () = default;
+
+  std::unique_ptr<Param> clone_param () const
+  {
+    return std::unique_ptr<Param> (clone_param_impl ());
+  }
+
+  virtual bool is_variadic () const { return false; }
+
+  virtual bool is_self () const { return false; }
+
+  NodeId get_node_id () const { return node_id; }
+
+  location_t get_locus () const { return locus; }
+
+  std::vector<Attribute> get_outer_attrs () const { return outer_attrs; }
+
+  std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+
+  virtual Param *clone_param_impl () const = 0;
+
+  virtual std::string as_string () const = 0;
+
+protected:
+  std::vector<Attribute> outer_attrs;
+  location_t locus;
+  NodeId node_id;
+};
+
 // A self parameter in a method
-class SelfParam
+class SelfParam : public Param
 {
   bool has_ref;
   bool is_mut;
@@ -387,14 +427,10 @@ class SelfParam
   // bool has_type; // only possible if not ref
   std::unique_ptr<Type> type;
 
-  NodeId node_id;
-
-  location_t locus;
-
   // Unrestricted constructor used for error state
   SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type)
-    : has_ref (has_ref), is_mut (is_mut), lifetime (std::move (lifetime)),
-      type (type), node_id (Analysis::Mappings::get ()->get_next_node_id ())
+    : Param ({}, UNDEF_LOCATION), has_ref (has_ref), is_mut (is_mut),
+      lifetime (std::move (lifetime)), type (type)
   {}
   // this is ok as no outside classes can ever call this
 
@@ -423,22 +459,20 @@ public:
 
   // Type-based self parameter (not ref, no lifetime)
   SelfParam (std::unique_ptr<Type> type, bool is_mut, location_t locus)
-    : has_ref (false), is_mut (is_mut), lifetime (Lifetime::error ()),
-      type (std::move (type)),
-      node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
+    : Param ({}, locus), has_ref (false), is_mut (is_mut),
+      lifetime (Lifetime::error ()), type (std::move (type))
   {}
 
   // Lifetime-based self parameter (is ref, no type)
   SelfParam (Lifetime lifetime, bool is_mut, location_t locus)
-    : has_ref (true), is_mut (is_mut), lifetime (std::move (lifetime)),
-      node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
+    : Param ({}, locus), has_ref (true), is_mut (is_mut),
+      lifetime (std::move (lifetime))
   {}
 
   // Copy constructor requires clone
   SelfParam (SelfParam const &other)
-    : has_ref (other.has_ref), is_mut (other.is_mut), lifetime (other.lifetime),
-      node_id (Analysis::Mappings::get ()->get_next_node_id ()),
-      locus (other.locus)
+    : Param (other.get_outer_attrs (), other.get_locus ()),
+      has_ref (other.has_ref), is_mut (other.is_mut), lifetime (other.lifetime)
   {
     node_id = other.node_id;
     if (other.type != nullptr)
@@ -453,6 +487,7 @@ public:
     lifetime = other.lifetime;
     locus = other.locus;
     node_id = other.node_id;
+    outer_attrs = other.outer_attrs;
 
     if (other.type != nullptr)
       type = other.type->clone_type ();
@@ -466,10 +501,12 @@ public:
   SelfParam (SelfParam &&other) = default;
   SelfParam &operator= (SelfParam &&other) = default;
 
-  std::string as_string () const;
+  std::string as_string () const override;
 
   location_t get_locus () const { return locus; }
 
+  bool is_self () const override { return true; }
+
   bool get_has_ref () const { return has_ref; };
   bool get_is_mut () const { return is_mut; }
 
@@ -484,6 +521,13 @@ public:
     rust_assert (has_type ());
     return type;
   }
+
+  void accept_vis (ASTVisitor &vis) override;
+
+  SelfParam *clone_param_impl () const override
+  {
+    return new SelfParam (*this);
+  }
 };
 
 // Qualifiers for function, i.e. const, unsafe, extern etc.
@@ -521,41 +565,84 @@ public:
   location_t get_locus () const { return locus; }
 };
 
-// A function parameter
-class FunctionParam
+class VariadicParam : public Param
 {
-  std::vector<Attribute> outer_attrs;
-  location_t locus;
   std::unique_ptr<Pattern> param_name;
-  std::unique_ptr<Type> type;
-  bool variadic;
 
 public:
-  FunctionParam (std::unique_ptr<Pattern> param_name,
-                std::unique_ptr<Type> param_type,
+  VariadicParam (std::unique_ptr<Pattern> param_name,
                 std::vector<Attribute> outer_attrs, location_t locus)
-    : outer_attrs (std::move (outer_attrs)), locus (locus),
-      param_name (std::move (param_name)), type (std::move (param_type)),
-      variadic (false),
-      node_id (Analysis::Mappings::get ()->get_next_node_id ())
+    : Param (std::move (outer_attrs), std::move (locus)),
+      param_name (std::move (param_name))
   {}
 
-  FunctionParam (std::vector<Attribute> outer_attrs, location_t locus)
-    : outer_attrs (std::move (outer_attrs)), locus (locus),
-      param_name (nullptr), type (nullptr), variadic (true),
-      node_id (Analysis::Mappings::get ()->get_next_node_id ())
+  VariadicParam (std::vector<Attribute> outer_attrs, location_t locus)
+    : Param (std::move (outer_attrs), std::move (locus)), param_name (nullptr)
   {}
 
+  VariadicParam (VariadicParam const &other)
+    : Param (other.get_outer_attrs (), other.locus)
+  {
+    if (other.param_name != nullptr)
+      param_name = other.param_name->clone_pattern ();
+  }
+
+  VariadicParam &operator= (VariadicParam const &other)
+  {
+    outer_attrs = other.outer_attrs;
+    locus = other.locus;
+    node_id = other.node_id;
+    if (other.param_name != nullptr)
+      param_name = other.param_name->clone_pattern ();
+    else
+      param_name = nullptr;
+
+    return *this;
+  }
+
+  bool is_variadic () const override { return true; }
+
+  VariadicParam *clone_param_impl () const override
+  {
+    return new VariadicParam (*this);
+  }
+
+  std::unique_ptr<Pattern> &get_pattern ()
+  {
+    rust_assert (param_name != nullptr);
+    return param_name;
+  }
+
+  const std::unique_ptr<Pattern> &get_pattern () const
+  {
+    rust_assert (param_name != nullptr);
+    return param_name;
+  }
+
+  bool has_pattern () const { return param_name != nullptr; }
+
+  void accept_vis (ASTVisitor &vis) override;
+
+  std::string as_string () const override;
+};
+
+// A function parameter
+class FunctionParam : public Param
+{
+  std::unique_ptr<Pattern> param_name;
+  std::unique_ptr<Type> type;
+
+public:
   FunctionParam (std::unique_ptr<Pattern> param_name,
+                std::unique_ptr<Type> param_type,
                 std::vector<Attribute> outer_attrs, location_t locus)
-    : outer_attrs (std::move (outer_attrs)), locus (locus),
-      param_name (std::move (param_name)), type (nullptr), variadic (true),
-      node_id (Analysis::Mappings::get ()->get_next_node_id ())
+    : Param (std::move (outer_attrs), locus),
+      param_name (std::move (param_name)), type (std::move (param_type))
   {}
 
   // Copy constructor uses clone
   FunctionParam (FunctionParam const &other)
-    : locus (other.locus), variadic (other.variadic), node_id (other.node_id)
+    : Param (other.get_outer_attrs (), other.locus)
   {
     // guard to prevent nullptr dereference
     if (other.param_name != nullptr)
@@ -569,7 +656,6 @@ public:
   {
     locus = other.locus;
     node_id = other.node_id;
-    variadic = other.variadic;
 
     // guard to prevent nullptr dereference
     if (other.param_name != nullptr)
@@ -589,13 +675,7 @@ public:
   FunctionParam &operator= (FunctionParam &&other) = default;
 
   // Returns whether FunctionParam is in an invalid state.
-  bool is_error () const
-  {
-    if (variadic)
-      return false;
-    else
-      return param_name == nullptr || type == nullptr;
-  }
+  bool is_error () const { return param_name == nullptr || type == nullptr; }
 
   // Creates an error FunctionParam.
   static FunctionParam create_error ()
@@ -603,9 +683,7 @@ public:
     return FunctionParam (nullptr, nullptr, {}, UNDEF_LOCATION);
   }
 
-  std::string as_string () const;
-
-  location_t get_locus () const { return locus; }
+  std::string as_string () const override;
 
   // TODO: seems kinda dodgy. Think of better way.
   std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
@@ -627,181 +705,12 @@ public:
     return type;
   }
 
-  bool is_variadic () const { return variadic; }
-
-  NodeId get_node_id () const { return node_id; }
-
-protected:
-  NodeId node_id;
-};
-
-// Visibility of item - if the item has it, then it is some form of public
-struct Visibility
-{
-public:
-  enum VisType
-  {
-    PRIV,
-    PUB,
-    PUB_CRATE,
-    PUB_SELF,
-    PUB_SUPER,
-    PUB_IN_PATH
-  };
-
-private:
-  VisType vis_type;
-  // Only assigned if vis_type is IN_PATH
-  SimplePath in_path;
-  location_t locus;
-
-  // should this store location info?
-
-public:
-  // Creates a Visibility - TODO make constructor protected or private?
-  Visibility (VisType vis_type, SimplePath in_path, location_t locus)
-    : vis_type (vis_type), in_path (std::move (in_path)), locus (locus)
-  {}
-
-  VisType get_vis_type () const { return vis_type; }
-
-  // Returns whether visibility is in an error state.
-  bool is_error () const
-  {
-    return vis_type == PUB_IN_PATH && in_path.is_empty ();
-  }
-
-  // Returns whether a visibility has a path
-  bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; }
-
-  // Returns whether visibility is public or not.
-  bool is_public () const { return vis_type != PRIV && !is_error (); }
-
-  location_t get_locus () const { return locus; }
-
-  // empty?
-  // Creates an error visibility.
-  static Visibility create_error ()
+  FunctionParam *clone_param_impl () const override
   {
-    return Visibility (PUB_IN_PATH, SimplePath::create_empty (),
-                      UNDEF_LOCATION);
+    return new FunctionParam (*this);
   }
 
-  // Unique pointer custom clone function
-  /*std::unique_ptr<Visibility> clone_visibility() const {
-      return std::unique_ptr<Visibility>(clone_visibility_impl());
-  }*/
-
-  /* TODO: think of a way to only allow valid Visibility states - polymorphism
-   * is one idea but may be too resource-intensive. */
-
-  // Creates a public visibility with no further features/arguments.
-  // empty?
-  static Visibility create_public (location_t pub_vis_location)
-  {
-    return Visibility (PUB, SimplePath::create_empty (), pub_vis_location);
-  }
-
-  // Creates a public visibility with crate-relative paths
-  static Visibility create_crate (location_t crate_tok_location,
-                                 location_t crate_vis_location)
-  {
-    return Visibility (PUB_CRATE,
-                      SimplePath::from_str ("crate", crate_tok_location),
-                      crate_vis_location);
-  }
-
-  // Creates a public visibility with self-relative paths
-  static Visibility create_self (location_t self_tok_location,
-                                location_t self_vis_location)
-  {
-    return Visibility (PUB_SELF,
-                      SimplePath::from_str ("self", self_tok_location),
-                      self_vis_location);
-  }
-
-  // Creates a public visibility with parent module-relative paths
-  static Visibility create_super (location_t super_tok_location,
-                                 location_t super_vis_location)
-  {
-    return Visibility (PUB_SUPER,
-                      SimplePath::from_str ("super", super_tok_location),
-                      super_vis_location);
-  }
-
-  // Creates a private visibility
-  static Visibility create_private ()
-  {
-    return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION);
-  }
-
-  // Creates a public visibility with a given path or whatever.
-  static Visibility create_in_path (SimplePath in_path,
-                                   location_t in_path_vis_location)
-  {
-    return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location);
-  }
-
-  std::string as_string () const;
-  const SimplePath &get_path () const { return in_path; }
-  SimplePath &get_path () { return in_path; }
-
-protected:
-  // Clone function implementation - not currently virtual but may be if
-  // polymorphism used
-  /*virtual*/ Visibility *clone_visibility_impl () const
-  {
-    return new Visibility (*this);
-  }
-};
-
-// Item that supports visibility - abstract base class
-class VisItem : public Item
-{
-  Visibility visibility;
-  std::vector<Attribute> outer_attrs;
-
-protected:
-  // Visibility constructor
-  VisItem (Visibility visibility,
-          std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
-    : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs))
-  {}
-
-  // Visibility copy constructor
-  VisItem (VisItem const &other)
-    : visibility (other.visibility), outer_attrs (other.outer_attrs)
-  {}
-
-  // Overload assignment operator to clone
-  VisItem &operator= (VisItem const &other)
-  {
-    visibility = other.visibility;
-    outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
-
-  // move constructors
-  VisItem (VisItem &&other) = default;
-  VisItem &operator= (VisItem &&other) = default;
-
-public:
-  /* Does the item have some kind of public visibility (non-default
-   * visibility)? */
-  bool has_visibility () const { return visibility.is_public (); }
-
-  std::string as_string () const override;
-
-  // TODO: this mutable getter seems really dodgy. Think up better way.
-  Visibility &get_visibility () { return visibility; }
-  const Visibility &get_visibility () const { return visibility; }
-
-  std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
-  const std::vector<Attribute> &get_outer_attrs () const override
-  {
-    return outer_attrs;
-  }
+  void accept_vis (ASTVisitor &vis) override;
 };
 
 // Rust module item - abstract base class
@@ -1372,8 +1281,7 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem
   FunctionQualifiers qualifiers;
   Identifier function_name;
   std::vector<std::unique_ptr<GenericParam>> generic_params;
-  tl::optional<SelfParam> self_param;
-  std::vector<FunctionParam> function_params;
+  std::vector<std::unique_ptr<Param>> function_params;
   std::unique_ptr<Type> return_type;
   WhereClause where_clause;
   std::unique_ptr<BlockExpr> function_body;
@@ -1395,13 +1303,15 @@ public:
   // Returns whether function has a where clause.
   bool has_where_clause () const { return !where_clause.is_empty (); }
 
-  bool has_self_param () const { return self_param.has_value (); }
+  bool has_self_param () const
+  {
+    return function_params.size () > 0 && function_params[0]->is_self ();
+  }
 
   // Mega-constructor with all possible fields
   Function (Identifier function_name, FunctionQualifiers qualifiers,
            std::vector<std::unique_ptr<GenericParam>> generic_params,
-           tl::optional<SelfParam> self_param,
-           std::vector<FunctionParam> function_params,
+           std::vector<std::unique_ptr<Param>> function_params,
            std::unique_ptr<Type> return_type, WhereClause where_clause,
            std::unique_ptr<BlockExpr> function_body, Visibility vis,
            std::vector<Attribute> outer_attrs, location_t locus,
@@ -1410,7 +1320,6 @@ public:
       qualifiers (std::move (qualifiers)),
       function_name (std::move (function_name)),
       generic_params (std::move (generic_params)),
-      self_param (std::move (self_param)),
       function_params (std::move (function_params)),
       return_type (std::move (return_type)),
       where_clause (std::move (where_clause)),
@@ -1421,58 +1330,10 @@ public:
   // TODO: add constructor with less fields
 
   // Copy constructor with clone
-  Function (Function const &other)
-    : VisItem (other), qualifiers (other.qualifiers),
-      function_name (other.function_name), self_param (other.self_param),
-      function_params (other.function_params),
-      where_clause (other.where_clause), locus (other.locus),
-      is_default (other.is_default)
-  {
-    // guard to prevent null dereference (always required)
-    if (other.return_type != nullptr)
-      return_type = other.return_type->clone_type ();
-
-    // guard to prevent null dereference (only required if error state)
-    if (other.function_body != nullptr)
-      function_body = other.function_body->clone_block_expr ();
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-  }
+  Function (Function const &other);
 
   // Overloaded assignment operator to clone
-  Function &operator= (Function const &other)
-  {
-    VisItem::operator= (other);
-    function_name = other.function_name;
-    qualifiers = other.qualifiers;
-    self_param = other.self_param;
-    function_params = other.function_params;
-    where_clause = other.where_clause;
-    // visibility = other.visibility->clone_visibility();
-    // outer_attrs = other.outer_attrs;
-    locus = other.locus;
-    is_default = other.is_default;
-
-    // guard to prevent null dereference (always required)
-    if (other.return_type != nullptr)
-      return_type = other.return_type->clone_type ();
-    else
-      return_type = nullptr;
-
-    // guard to prevent null dereference (only required if error state)
-    if (other.function_body != nullptr)
-      function_body = other.function_body->clone_block_expr ();
-    else
-      function_body = nullptr;
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-
-    return *this;
-  }
+  Function &operator= (Function const &other);
 
   // move constructors
   Function (Function &&other) = default;
@@ -1485,7 +1346,7 @@ public:
   bool is_variadic () const
   {
     return function_params.size () != 0
-          && function_params.back ().is_variadic ();
+          && function_params.back ()->is_variadic ();
   }
 
   // Invalid if block is null, so base stripping on that.
@@ -1495,8 +1356,11 @@ public:
     return function_body == nullptr;
   }
 
-  std::vector<FunctionParam> &get_function_params () { return function_params; }
-  const std::vector<FunctionParam> &get_function_params () const
+  std::vector<std::unique_ptr<Param>> &get_function_params ()
+  {
+    return function_params;
+  }
+  const std::vector<std::unique_ptr<Param>> &get_function_params () const
   {
     return function_params;
   }
@@ -1533,15 +1397,15 @@ public:
     return return_type;
   }
 
-  SelfParam &get_self_param ()
+  std::unique_ptr<Param> &get_self_param ()
   {
     rust_assert (has_self_param ());
-    return self_param.value ();
+    return function_params[0];
   }
-  const SelfParam &get_self_param () const
+  const std::unique_ptr<Param> &get_self_param () const
   {
     rust_assert (has_self_param ());
-    return self_param.value ();
+    return function_params[0];
   }
 
 protected:
@@ -2668,7 +2532,7 @@ class TraitFunctionDecl
 
   // bool has_params;
   // FunctionParams function_params;
-  std::vector<FunctionParam> function_params; // inlined
+  std::vector<std::unique_ptr<Param>> function_params; // inlined
 
   // bool has_return_type;
   std::unique_ptr<Type> return_type;
@@ -2696,7 +2560,7 @@ public:
   // Mega-constructor
   TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers,
                     std::vector<std::unique_ptr<GenericParam>> generic_params,
-                    std::vector<FunctionParam> function_params,
+                    std::vector<std::unique_ptr<Param>> function_params,
                     std::unique_ptr<Type> return_type,
                     WhereClause where_clause)
     : qualifiers (std::move (qualifiers)),
@@ -2710,7 +2574,7 @@ public:
   // Copy constructor with clone
   TraitFunctionDecl (TraitFunctionDecl const &other)
     : qualifiers (other.qualifiers), function_name (other.function_name),
-      function_params (other.function_params), where_clause (other.where_clause)
+      where_clause (other.where_clause)
   {
     // guard to prevent nullptr dereference
     if (other.return_type != nullptr)
@@ -2719,6 +2583,10 @@ public:
     generic_params.reserve (other.generic_params.size ());
     for (const auto &e : other.generic_params)
       generic_params.push_back (e->clone_generic_param ());
+
+    function_params.reserve (other.function_params.size ());
+    for (const auto &e : other.function_params)
+      function_params.push_back (e->clone_param ());
   }
 
   ~TraitFunctionDecl () = default;
@@ -2728,7 +2596,6 @@ public:
   {
     function_name = other.function_name;
     qualifiers = other.qualifiers;
-    function_params = other.function_params;
     where_clause = other.where_clause;
 
     // guard to prevent nullptr dereference
@@ -2741,6 +2608,10 @@ public:
     for (const auto &e : other.generic_params)
       generic_params.push_back (e->clone_generic_param ());
 
+    function_params.reserve (other.function_params.size ());
+    for (const auto &e : other.function_params)
+      function_params.push_back (e->clone_param ());
+
     return *this;
   }
 
@@ -2755,8 +2626,11 @@ public:
   bool is_marked_for_strip () const { return function_name.empty (); }
 
   // TODO: this mutable getter seems really dodgy. Think up better way.
-  std::vector<FunctionParam> &get_function_params () { return function_params; }
-  const std::vector<FunctionParam> &get_function_params () const
+  std::vector<std::unique_ptr<Param>> &get_function_params ()
+  {
+    return function_params;
+  }
+  const std::vector<std::unique_ptr<Param>> &get_function_params () const
   {
     return function_params;
   }
@@ -2798,34 +2672,11 @@ public:
   {}
 
   // Copy constructor with clone
-  TraitItemFunc (TraitItemFunc const &other)
-    : TraitItem (other.locus), outer_attrs (other.outer_attrs),
-      decl (other.decl)
-  {
-    node_id = other.node_id;
-
-    // guard to prevent null dereference
-    if (other.block_expr != nullptr)
-      block_expr = other.block_expr->clone_block_expr ();
-  }
+  TraitItemFunc (TraitItemFunc const &other);
 
   // Overloaded assignment operator to clone
-  TraitItemFunc &operator= (TraitItemFunc const &other)
-  {
-    TraitItem::operator= (other);
-    outer_attrs = other.outer_attrs;
-    decl = other.decl;
-    locus = other.locus;
-    node_id = other.node_id;
-
-    // guard to prevent null dereference
-    if (other.block_expr != nullptr)
-      block_expr = other.block_expr->clone_block_expr ();
-    else
-      block_expr = nullptr;
 
-    return *this;
-  }
+  TraitItemFunc &operator= (TraitItemFunc const &other);
 
   // move constructors
   TraitItemFunc (TraitItemFunc &&other) = default;
@@ -2875,11 +2726,9 @@ class TraitMethodDecl
   // Generics generic_params;
   std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
 
-  SelfParam self_param;
-
   // bool has_params;
   // FunctionParams function_params;
-  std::vector<FunctionParam> function_params; // inlined
+  std::vector<std::unique_ptr<Param>> function_params; // inlined
 
   // bool has_return_type;
   std::unique_ptr<Type> return_type;
@@ -2907,13 +2756,11 @@ public:
   // Mega-constructor
   TraitMethodDecl (Identifier function_name, FunctionQualifiers qualifiers,
                   std::vector<std::unique_ptr<GenericParam>> generic_params,
-                  SelfParam self_param,
-                  std::vector<FunctionParam> function_params,
+                  std::vector<std::unique_ptr<Param>> function_params,
                   std::unique_ptr<Type> return_type, WhereClause where_clause)
     : qualifiers (std::move (qualifiers)),
       function_name (std::move (function_name)),
       generic_params (std::move (generic_params)),
-      self_param (std::move (self_param)),
       function_params (std::move (function_params)),
       return_type (std::move (return_type)),
       where_clause (std::move (where_clause))
@@ -2922,7 +2769,6 @@ public:
   // Copy constructor with clone
   TraitMethodDecl (TraitMethodDecl const &other)
     : qualifiers (other.qualifiers), function_name (other.function_name),
-      self_param (other.self_param), function_params (other.function_params),
       where_clause (other.where_clause)
   {
     // guard to prevent nullptr dereference
@@ -2932,6 +2778,10 @@ public:
     generic_params.reserve (other.generic_params.size ());
     for (const auto &e : other.generic_params)
       generic_params.push_back (e->clone_generic_param ());
+
+    function_params.reserve (other.function_params.size ());
+    for (const auto &e : other.function_params)
+      function_params.push_back (e->clone_param ());
   }
 
   ~TraitMethodDecl () = default;
@@ -2941,8 +2791,6 @@ public:
   {
     function_name = other.function_name;
     qualifiers = other.qualifiers;
-    self_param = other.self_param;
-    function_params = other.function_params;
     where_clause = other.where_clause;
 
     // guard to prevent nullptr dereference
@@ -2955,6 +2803,10 @@ public:
     for (const auto &e : other.generic_params)
       generic_params.push_back (e->clone_generic_param ());
 
+    function_params.reserve (other.function_params.size ());
+    for (const auto &e : other.function_params)
+      function_params.push_back (e->clone_param ());
+
     return *this;
   }
 
@@ -2969,8 +2821,11 @@ public:
   bool is_marked_for_strip () const { return function_name.empty (); }
 
   // TODO: this mutable getter seems really dodgy. Think up better way.
-  std::vector<FunctionParam> &get_function_params () { return function_params; }
-  const std::vector<FunctionParam> &get_function_params () const
+  std::vector<std::unique_ptr<Param>> &get_function_params ()
+  {
+    return function_params;
+  }
+  const std::vector<std::unique_ptr<Param>> &get_function_params () const
   {
     return function_params;
   }
@@ -2990,8 +2845,21 @@ public:
   // TODO: is this better? Or is a "vis_block" better?
   WhereClause &get_where_clause () { return where_clause; }
 
-  SelfParam &get_self_param () { return self_param; }
-  const SelfParam &get_self_param () const { return self_param; }
+  bool has_self () const
+  {
+    return !function_params.empty () && function_params[0]->is_self ();
+  }
+
+  std::unique_ptr<Param> &get_self_param ()
+  {
+    rust_assert (has_self ());
+    return function_params[0];
+  }
+  const std::unique_ptr<Param> &get_self_param () const
+  {
+    rust_assert (has_self ());
+    return function_params[0];
+  }
 
   FunctionQualifiers get_qualifiers () const { return qualifiers; }
 
@@ -3016,34 +2884,9 @@ public:
   {}
 
   // Copy constructor with clone
-  TraitItemMethod (TraitItemMethod const &other)
-    : TraitItem (other.locus), outer_attrs (other.outer_attrs),
-      decl (other.decl)
-  {
-    node_id = other.node_id;
-
-    // guard to prevent null dereference
-    if (other.block_expr != nullptr)
-      block_expr = other.block_expr->clone_block_expr ();
-  }
-
+  TraitItemMethod (TraitItemMethod const &other);
   // Overloaded assignment operator to clone
-  TraitItemMethod &operator= (TraitItemMethod const &other)
-  {
-    TraitItem::operator= (other);
-    outer_attrs = other.outer_attrs;
-    decl = other.decl;
-    locus = other.locus;
-    node_id = other.node_id;
-
-    // guard to prevent null dereference
-    if (other.block_expr != nullptr)
-      block_expr = other.block_expr->clone_block_expr ();
-    else
-      block_expr = nullptr;
-
-    return *this;
-  }
+  TraitItemMethod &operator= (TraitItemMethod const &other);
 
   // move constructors
   TraitItemMethod (TraitItemMethod &&other) = default;
index a903297d19b80331f95342cb392429e201242f0a..f6ce45eaccab28a276fdee0197c3d52d00dd47e7 100644 (file)
@@ -81,4 +81,19 @@ ASTValidation::visit (AST::ExternalFunctionItem &item)
   AST::ContextualASTVisitor::visit (item);
 }
 
+void
+ASTValidation::visit (AST::Function &function)
+{
+  std::set<Context> valid_context
+    = {Context::INHERENT_IMPL, Context::TRAIT_IMPL};
+
+  if (valid_context.find (context.back ()) == valid_context.end ()
+      && function.has_self_param ())
+    rust_error_at (
+      function.get_self_param ()->get_locus (),
+      "%<self%> parameter is only allowed in associated functions");
+
+  AST::ContextualASTVisitor::visit (function);
+}
+
 } // namespace Rust
index 6028b21ff00643dd54203fa8467bc09599c5eabc..44995eb1fbce954eab70a4d2ebe84a031863a084 100644 (file)
@@ -37,6 +37,7 @@ public:
   virtual void visit (AST::Lifetime &lifetime);
   virtual void visit (AST::LoopLabel &label);
   virtual void visit (AST::ExternalFunctionItem &item);
+  virtual void visit (AST::Function &function);
 };
 
 } // namespace Rust
index de0170e9d03383f7a530b2bcfb0900e3741dddea..1ebd3c9e05fbc747eca72c2461d60dcb7683c041 100644 (file)
@@ -183,6 +183,9 @@ public:
   void visit (AST::SliceType &type) override {}
   void visit (AST::InferredType &type) override {}
   void visit (AST::BareFunctionType &type) override {}
+  void visit (AST::FunctionParam &param) override {}
+  void visit (AST::VariadicParam &param) override {}
+  void visit (AST::SelfParam &param) override {}
 
 private:
   void gate (Feature::Name name, location_t loc, const std::string &error_msg);
index 9ef2468ecf6514c3f86d8b157a177c5a82eafcdb..fd1156546185804eb61fa078835aa6b3a06a02f4 100644 (file)
@@ -218,34 +218,37 @@ CfgStrip::maybe_strip_tuple_fields (std::vector<AST::TupleField> &fields)
 }
 
 void
-CfgStrip::maybe_strip_function_params (std::vector<AST::FunctionParam> &params)
+CfgStrip::maybe_strip_function_params (
+  std::vector<std::unique_ptr<AST::Param>> &params)
 {
   for (auto it = params.begin (); it != params.end ();)
     {
-      auto &param = *it;
-
-      auto &param_attrs = param.get_outer_attrs ();
-      expand_cfg_attrs (param_attrs);
-      if (fails_cfg_with_expand (param_attrs))
+      if (!(*it)->is_self () && !(*it)->is_variadic ())
        {
-         it = params.erase (it);
-         continue;
-       }
+         auto param = static_cast<AST::FunctionParam *> (it->get ());
 
-      // TODO: should an unwanted strip lead to break out of loop?
-      auto &pattern = param.get_pattern ();
-      pattern->accept_vis (*this);
-      if (pattern->is_marked_for_strip ())
-       rust_error_at (pattern->get_locus (),
-                      "cannot strip pattern in this position");
+         auto &param_attrs = param->get_outer_attrs ();
+         expand_cfg_attrs (param_attrs);
+         if (fails_cfg_with_expand (param_attrs))
+           {
+             it = params.erase (it);
+             continue;
+           }
 
-      auto &type = param.get_type ();
-      type->accept_vis (*this);
+         // TODO: should an unwanted strip lead to break out of loop?
+         auto &pattern = param->get_pattern ();
+         pattern->accept_vis (*this);
+         if (pattern->is_marked_for_strip ())
+           rust_error_at (pattern->get_locus (),
+                          "cannot strip pattern in this position");
 
-      if (type->is_marked_for_strip ())
-       rust_error_at (type->get_locus (),
-                      "cannot strip type in this position");
+         auto &type = param->get_type ();
+         type->accept_vis (*this);
 
+         if (type->is_marked_for_strip ())
+           rust_error_at (type->get_locus (),
+                          "cannot strip type in this position");
+       }
       // increment
       ++it;
     }
@@ -359,22 +362,6 @@ CfgStrip::CfgStrip::maybe_strip_closure_params (
     }
 }
 
-void
-CfgStrip::maybe_strip_self_param (AST::SelfParam &self_param)
-{
-  if (self_param.has_type ())
-    {
-      auto &type = self_param.get_type ();
-      type->accept_vis (*this);
-
-      if (type->is_marked_for_strip ())
-       rust_error_at (type->get_locus (),
-                      "cannot strip type in this position");
-    }
-  /* TODO: maybe check for invariants being violated - e.g. both type and
-   * lifetime? */
-}
-
 void
 CfgStrip::maybe_strip_where_clause (AST::WhereClause &where_clause)
 {
@@ -415,11 +402,6 @@ CfgStrip::maybe_strip_trait_method_decl (AST::TraitMethodDecl &decl)
   for (auto &param : decl.get_generic_params ())
     param->accept_vis (*this);
 
-  /* assuming you can't strip self param - wouldn't be a method
-   * anymore. spec allows outer attrs on self param, but doesn't
-   * specify whether cfg is used. */
-  maybe_strip_self_param (decl.get_self_param ());
-
   /* strip function parameters if required - this is specifically
    * allowed by spec */
   maybe_strip_function_params (decl.get_function_params ());
@@ -2029,13 +2011,6 @@ CfgStrip::visit (AST::Function &function)
   for (auto &param : function.get_generic_params ())
     param->accept_vis (*this);
 
-  /* assuming you can't strip self param - wouldn't be a method
-   * anymore. spec allows outer attrs on self param, but doesn't
-   * specify whether cfg is used. */
-  // TODO: verify this
-  if (function.has_self_param ())
-    maybe_strip_self_param (function.get_self_param ());
-
   /* strip function parameters if required - this is specifically
    * allowed by spec */
   maybe_strip_function_params (function.get_function_params ());
@@ -3167,4 +3142,28 @@ CfgStrip::visit (AST::BareFunctionType &type)
   // no where clause, apparently
 }
 
+void
+CfgStrip::visit (AST::VariadicParam &type)
+{}
+
+void
+CfgStrip::visit (AST::FunctionParam &type)
+{}
+
+void
+CfgStrip::visit (AST::SelfParam &param)
+{
+  if (param.has_type ())
+    {
+      auto &type = param.get_type ();
+      type->accept_vis (*this);
+
+      if (type->is_marked_for_strip ())
+       rust_error_at (type->get_locus (),
+                      "cannot strip type in this position");
+    }
+  /* TODO: maybe check for invariants being violated - e.g. both type and
+   * lifetime? */
+}
+
 } // namespace Rust
index a06026e1c0a6db60aa2271e56ce59e387d3dfc6c..32dbee6f780c28596763a5a0718e80411df97017 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "rust-ast-visitor.h"
 #include "rust-ast.h"
+#include "rust-item.h"
 
 namespace Rust {
 // Visitor used to maybe_strip attributes.
@@ -32,7 +33,8 @@ public:
 
   void maybe_strip_struct_fields (std::vector<AST::StructField> &fields);
   void maybe_strip_tuple_fields (std::vector<AST::TupleField> &fields);
-  void maybe_strip_function_params (std::vector<AST::FunctionParam> &params);
+  void maybe_strip_function_params (
+    std::vector<std::unique_ptr<AST::Param>> &params);
   void maybe_strip_generic_args (AST::GenericArgs &args);
   void maybe_strip_qualified_path_type (AST::QualifiedPathType &path_type);
   void maybe_strip_closure_params (std::vector<AST::ClosureParam> &params);
@@ -222,5 +224,8 @@ public:
   void visit (AST::SliceType &type) override;
   void visit (AST::InferredType &) override;
   void visit (AST::BareFunctionType &type) override;
+  void visit (AST::VariadicParam &type) override;
+  void visit (AST::FunctionParam &type) override;
+  void visit (AST::SelfParam &type) override;
 };
 } // namespace Rust
index 28ce402dde7e5cc40043cfb0c5e981f236388da7..cc198eecf5d92f57fd4e9eed035be9a92c5af93f 100644 (file)
@@ -17,6 +17,7 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-derive-clone.h"
+#include "rust-item.h"
 
 namespace Rust {
 namespace AST {
@@ -50,13 +51,17 @@ DeriveClone::clone_fn (std::unique_ptr<Expr> &&clone_expr)
                   loc, loc));
   auto big_self_type = builder.single_type_path ("Self");
 
+  std::unique_ptr<SelfParam> self (new SelfParam (Lifetime::error (),
+                                                 /* is_mut */ false, loc));
+
+  std::vector<std::unique_ptr<Param>> params;
+  params.push_back (std::move (self));
+
   return std::unique_ptr<TraitImplItem> (
     new Function ({"clone"}, builder.fn_qualifiers (), /* generics */ {},
-                 tl::optional<SelfParam> (tl::in_place, Lifetime::error (),
-                                          /* is_mut */ false, loc),
-                 /* function params */ {}, std::move (big_self_type),
-                 WhereClause::create_empty (), std::move (block),
-                 Visibility::create_private (), {}, loc));
+                 /* function params */ std::move (params),
+                 std::move (big_self_type), WhereClause::create_empty (),
+                 std::move (block), Visibility::create_private (), {}, loc));
 }
 
 /**
index 915c0545cbe55c16d056068b5f9e304349e8701c..d5c8b44442ddea671a7a497ff95d63b3b5e54880 100644 (file)
@@ -220,6 +220,9 @@ private:
   virtual void visit (SliceType &type) override final{};
   virtual void visit (InferredType &type) override final{};
   virtual void visit (BareFunctionType &type) override final{};
+  virtual void visit (SelfParam &param) override final{};
+  virtual void visit (FunctionParam &param) override final{};
+  virtual void visit (VariadicParam &param) override final{};
 };
 
 } // namespace AST
index 0dd6f592dba0118321718fe206a04d1e07965394..3f598b7f21ce224e25d15ae771f033837c16cc5b 100644 (file)
@@ -373,12 +373,11 @@ ExpandVisitor::expand_tuple_fields (std::vector<AST::TupleField> &fields)
 
 // FIXME: This can definitely be refactored with the method above
 void
-ExpandVisitor::expand_function_params (std::vector<AST::FunctionParam> &params)
+ExpandVisitor::expand_function_params (
+  std::vector<std::unique_ptr<AST::Param>> &params)
 {
-  for (auto &param : params)
-    {
-      maybe_expand_type (param.get_type ());
-    }
+  for (auto &p : params)
+    visit (p);
 }
 
 void
@@ -431,16 +430,6 @@ ExpandVisitor::expand_closure_params (std::vector<AST::ClosureParam> &params)
     }
 }
 
-void
-ExpandVisitor::expand_self_param (AST::SelfParam &self_param)
-{
-  if (self_param.has_type ())
-    maybe_expand_type (self_param.get_type ());
-
-  /* TODO: maybe check for invariants being violated - e.g. both type and
-   * lifetime? */
-}
-
 void
 ExpandVisitor::expand_where_clause (AST::WhereClause &where_clause)
 {
@@ -472,11 +461,6 @@ ExpandVisitor::expand_trait_method_decl (AST::TraitMethodDecl &decl)
   for (auto &param : decl.get_generic_params ())
     visit (param);
 
-  /* assuming you can't strip self param - wouldn't be a method
-   * anymore. spec allows outer attrs on self param, but doesn't
-   * specify whether cfg is used. */
-  expand_self_param (decl.get_self_param ());
-
   /* strip function parameters if required - this is specifically
    * allowed by spec */
   expand_function_params (decl.get_function_params ());
@@ -1022,8 +1006,6 @@ ExpandVisitor::visit (AST::Function &function)
   for (auto &param : function.get_generic_params ())
     visit (param);
 
-  if (function.has_self_param ())
-    expand_self_param (function.get_self_param ());
   expand_function_params (function.get_function_params ());
 
   if (function.has_return_type ())
@@ -1566,6 +1548,25 @@ ExpandVisitor::visit (AST::BareFunctionType &type)
     visit (type.get_return_type ());
 }
 
+void
+ExpandVisitor::visit (AST::VariadicParam &param)
+{}
+
+void
+ExpandVisitor::visit (AST::FunctionParam &param)
+{
+  maybe_expand_type (param.get_type ());
+}
+
+void
+ExpandVisitor::visit (AST::SelfParam &param)
+{
+  /* TODO: maybe check for invariants being violated - e.g. both type and
+   * lifetime? */
+  if (param.has_type ())
+    maybe_expand_type (param.get_type ());
+}
+
 template <typename T>
 void
 ExpandVisitor::expand_inner_attribute (T &item, AST::SimplePath &path)
index d7612acd385f8f9ae55f51a3849616b3101e723b..74f2673655fd4edc7117b6305d5450874ed2db86 100644 (file)
@@ -67,7 +67,8 @@ public:
    * Expand all macro invocations in lieu of types within a list of function
    * parameters
    */
-  void expand_function_params (std::vector<AST::FunctionParam> &params);
+  void
+  expand_function_params (std::vector<std::unique_ptr<AST::Param>> &params);
 
   /**
    * Expand all macro invocations in lieu of types within a list of generic
@@ -82,7 +83,6 @@ public:
 
   // FIXME: Add documentation
   void expand_closure_params (std::vector<AST::ClosureParam> &params);
-  void expand_self_param (AST::SelfParam &self_param);
   void expand_where_clause (AST::WhereClause &where_clause);
   void expand_trait_function_decl (AST::TraitFunctionDecl &decl);
   void expand_trait_method_decl (AST::TraitMethodDecl &decl);
@@ -347,6 +347,9 @@ public:
   void visit (AST::SliceType &type) override;
   void visit (AST::InferredType &) override;
   void visit (AST::BareFunctionType &type) override;
+  void visit (AST::VariadicParam &type) override;
+  void visit (AST::FunctionParam &type) override;
+  void visit (AST::SelfParam &type) override;
 
   template <typename T>
   void expand_inner_attribute (T &item, AST::SimplePath &Path);
index 1343a53667ce7977bef5423891b8e469c4b4f1ce..f5eed256a5e741db4efef81d3e2a6163dff77b27 100644 (file)
@@ -21,6 +21,8 @@
 #include "rust-ast-lower-pattern.h"
 #include "rust-ast-lower-extern.h"
 #include "rust-attribute-values.h"
+#include "rust-item.h"
+#include "rust-system.h"
 
 namespace Rust {
 namespace HIR {
@@ -515,6 +517,18 @@ void
 ASTLoweringBase::visit (AST::BareFunctionType &)
 {}
 
+void
+ASTLoweringBase::visit (AST::FunctionParam &param)
+{}
+
+void
+ASTLoweringBase::visit (AST::VariadicParam &param)
+{}
+
+void
+ASTLoweringBase::visit (AST::SelfParam &param)
+{}
+
 HIR::Lifetime
 ASTLoweringBase::lower_lifetime (AST::Lifetime &lifetime)
 {
@@ -629,28 +643,31 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args)
 }
 
 HIR::SelfParam
-ASTLoweringBase::lower_self (AST::SelfParam &self)
+ASTLoweringBase::lower_self (std::unique_ptr<AST::Param> &param)
 {
+  rust_assert (param->is_self ());
+
+  auto self = static_cast<AST::SelfParam *> (param.get ());
   auto crate_num = mappings->get_current_crate ();
-  Analysis::NodeMapping mapping (crate_num, self.get_node_id (),
+  Analysis::NodeMapping mapping (crate_num, self->get_node_id (),
                                 mappings->get_next_hir_id (crate_num),
                                 mappings->get_next_localdef_id (crate_num));
 
-  if (self.has_type ())
+  if (self->has_type ())
     {
-      HIR::Type *type = ASTLoweringType::translate (self.get_type ().get ());
+      HIR::Type *type = ASTLoweringType::translate (self->get_type ().get ());
       return HIR::SelfParam (mapping, std::unique_ptr<HIR::Type> (type),
-                            self.get_is_mut (), self.get_locus ());
+                            self->get_is_mut (), self->get_locus ());
     }
-  else if (!self.get_has_ref ())
+  else if (!self->get_has_ref ())
     {
       return HIR::SelfParam (mapping, std::unique_ptr<HIR::Type> (nullptr),
-                            self.get_is_mut (), self.get_locus ());
+                            self->get_is_mut (), self->get_locus ());
     }
 
-  AST::Lifetime l = self.get_lifetime ();
-  return HIR::SelfParam (mapping, lower_lifetime (l), self.get_is_mut (),
-                        self.get_locus ());
+  AST::Lifetime l = self->get_lifetime ();
+  return HIR::SelfParam (mapping, lower_lifetime (l), self->get_is_mut (),
+                        self->get_locus ());
 }
 
 HIR::Type *
index 1bb2731b8605a233374ed2e10d45f6fd73a671f3..d52afd3421f8280324d8f83121503525592e2c13 100644 (file)
@@ -251,6 +251,9 @@ public:
   virtual void visit (AST::SliceType &type);
   virtual void visit (AST::InferredType &type);
   virtual void visit (AST::BareFunctionType &type);
+  virtual void visit (AST::FunctionParam &param);
+  virtual void visit (AST::VariadicParam &param);
+  virtual void visit (AST::SelfParam &param);
 
 protected:
   ASTLoweringBase ()
@@ -274,7 +277,7 @@ protected:
 
   HIR::GenericArgsBinding lower_binding (AST::GenericArgsBinding &binding);
 
-  HIR::SelfParam lower_self (AST::SelfParam &self);
+  HIR::SelfParam lower_self (std::unique_ptr<AST::Param> &self);
 
   HIR::Type *lower_type_no_bounds (AST::TypeNoBounds *type);
 
index 490676a55ded88c5f527d0fd0de7211c70a5b4e4..096a30e1e42307382869f55bb211bf66842a72d1 100644 (file)
@@ -23,6 +23,7 @@
 #include "rust-ast-lower-expr.h"
 #include "rust-ast-lower-pattern.h"
 #include "rust-ast-lower-block.h"
+#include "rust-item.h"
 
 namespace Rust {
 namespace HIR {
@@ -141,22 +142,26 @@ public:
                                    : nullptr;
 
     std::vector<HIR::FunctionParam> function_params;
-    for (auto &param : function.get_function_params ())
+    for (auto &p : function.get_function_params ())
       {
+       if (p->is_self () || p->is_variadic ())
+         continue;
+       auto param = static_cast<AST::FunctionParam *> (p.get ());
+
        auto translated_pattern = std::unique_ptr<HIR::Pattern> (
-         ASTLoweringPattern::translate (param.get_pattern ().get ()));
+         ASTLoweringPattern::translate (param->get_pattern ().get ()));
        auto translated_type = std::unique_ptr<HIR::Type> (
-         ASTLoweringType::translate (param.get_type ().get ()));
+         ASTLoweringType::translate (param->get_type ().get ()));
 
        auto crate_num = mappings->get_current_crate ();
-       Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+       Analysis::NodeMapping mapping (crate_num, param->get_node_id (),
                                       mappings->get_next_hir_id (crate_num),
                                       UNKNOWN_LOCAL_DEFID);
 
        auto hir_param
          = HIR::FunctionParam (mapping, std::move (translated_pattern),
                                std::move (translated_type),
-                               param.get_locus ());
+                               param->get_locus ());
        function_params.push_back (std::move (hir_param));
       }
 
@@ -255,22 +260,27 @@ public:
                               : nullptr;
 
     std::vector<HIR::FunctionParam> function_params;
-    for (auto &param : ref.get_function_params ())
+    for (auto &p : ref.get_function_params ())
       {
+       if (p->is_variadic () || p->is_self ())
+         continue;
+
+       auto param = static_cast<AST::FunctionParam *> (p.get ());
+
        auto translated_pattern = std::unique_ptr<HIR::Pattern> (
-         ASTLoweringPattern::translate (param.get_pattern ().get ()));
+         ASTLoweringPattern::translate (param->get_pattern ().get ()));
        auto translated_type = std::unique_ptr<HIR::Type> (
-         ASTLoweringType::translate (param.get_type ().get ()));
+         ASTLoweringType::translate (param->get_type ().get ()));
 
        auto crate_num = mappings->get_current_crate ();
-       Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+       Analysis::NodeMapping mapping (crate_num, param->get_node_id (),
                                       mappings->get_next_hir_id (crate_num),
                                       UNKNOWN_LOCAL_DEFID);
 
        auto hir_param
          = HIR::FunctionParam (mapping, std::move (translated_pattern),
                                std::move (translated_type),
-                               param.get_locus ());
+                               param->get_locus ());
        function_params.push_back (std::move (hir_param));
       }
 
@@ -329,22 +339,27 @@ public:
     HIR::SelfParam self_param = lower_self (ref.get_self_param ());
 
     std::vector<HIR::FunctionParam> function_params;
-    for (auto &param : ref.get_function_params ())
+    for (auto &p : ref.get_function_params ())
       {
+       if (p->is_variadic () || p->is_self ())
+         continue;
+
+       auto param = static_cast<AST::FunctionParam *> (p.get ());
+
        auto translated_pattern = std::unique_ptr<HIR::Pattern> (
-         ASTLoweringPattern::translate (param.get_pattern ().get ()));
+         ASTLoweringPattern::translate (param->get_pattern ().get ()));
        auto translated_type = std::unique_ptr<HIR::Type> (
-         ASTLoweringType::translate (param.get_type ().get ()));
+         ASTLoweringType::translate (param->get_type ().get ()));
 
        auto crate_num = mappings->get_current_crate ();
-       Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+       Analysis::NodeMapping mapping (crate_num, param->get_node_id (),
                                       mappings->get_next_hir_id (crate_num),
                                       UNKNOWN_LOCAL_DEFID);
 
        auto hir_param
          = HIR::FunctionParam (mapping, std::move (translated_pattern),
                                std::move (translated_type),
-                               param.get_locus ());
+                               param->get_locus ());
        function_params.push_back (hir_param);
       }
 
index 6d91c23e8d23c009989f59ae2349c5a82de8286c..8d6ab7cd3506449b866776b8ddcfae02a2b63f90 100644 (file)
@@ -26,6 +26,7 @@
 #include "rust-ast-lower-expr.h"
 #include "rust-ast-lower-pattern.h"
 #include "rust-ast-lower-block.h"
+#include "rust-item.h"
 
 namespace Rust {
 namespace HIR {
@@ -420,21 +421,25 @@ ASTLoweringItem::visit (AST::Function &function)
                                  : nullptr;
 
   std::vector<HIR::FunctionParam> function_params;
-  for (auto &param : function.get_function_params ())
+  for (auto &p : function.get_function_params ())
     {
+      if (p->is_variadic () || p->is_self ())
+       continue;
+      auto param = static_cast<AST::FunctionParam *> (p.get ());
+
       auto translated_pattern = std::unique_ptr<HIR::Pattern> (
-       ASTLoweringPattern::translate (param.get_pattern ().get ()));
+       ASTLoweringPattern::translate (param->get_pattern ().get ()));
       auto translated_type = std::unique_ptr<HIR::Type> (
-       ASTLoweringType::translate (param.get_type ().get ()));
+       ASTLoweringType::translate (param->get_type ().get ()));
 
       auto crate_num = mappings->get_current_crate ();
-      Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+      Analysis::NodeMapping mapping (crate_num, param->get_node_id (),
                                     mappings->get_next_hir_id (crate_num),
                                     UNKNOWN_LOCAL_DEFID);
 
       auto hir_param
        = HIR::FunctionParam (mapping, std::move (translated_pattern),
-                             std::move (translated_type), param.get_locus ());
+                             std::move (translated_type), param->get_locus ());
       function_params.push_back (std::move (hir_param));
     }
 
index 73c3abfe0a28d62a272bd4fe1da2e4fdda5d2b0d..a946c67422d803d5c3557619108f409489b95855 100644 (file)
 #include "rust-hir-map.h"
 #include "rust-ast-dump.h"
 #include "rust-abi.h"
+#include "rust-item.h"
 #include "rust-object-export.h"
 
 #include "md5.h"
+#include "rust-system.h"
 
 namespace Rust {
 namespace Metadata {
@@ -107,15 +109,18 @@ ExportContext::emit_function (const HIR::Function &fn)
        }
 
       std::vector<AST::NamedFunctionParam> function_params;
-      for (AST::FunctionParam &param : function.get_function_params ())
+      for (auto &p : function.get_function_params ())
        {
-         std::string name = param.get_pattern ()->as_string ();
+         if (p->is_variadic () || p->is_self ())
+           rust_unreachable ();
+         auto param = static_cast<AST::FunctionParam *> (p.get ());
+         std::string name = param->get_pattern ()->as_string ();
          std::unique_ptr<AST::Type> param_type
-           = param.get_type ()->clone_type ();
+           = param->get_type ()->clone_type ();
 
-         AST::NamedFunctionParam p (name, std::move (param_type), {},
-                                    param.get_locus ());
-         function_params.push_back (std::move (p));
+         AST::NamedFunctionParam np (name, std::move (param_type), {},
+                                     param->get_locus ());
+         function_params.push_back (std::move (np));
        }
 
       AST::ExternalItem *external_item
index 21795bb4ca0e81fab21ec98ab3e9c811d13a03a2..0e50c9eb17a54f84ad25f04b27cfb9687be5031d 100644 (file)
@@ -2879,12 +2879,21 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
       return nullptr;
     }
 
+  std::unique_ptr<AST::Param> initial_param = parse_self_param ();
+  if (initial_param != nullptr)
+    skip_token (COMMA);
+
   // parse function parameters (only if next token isn't right paren)
-  std::vector<AST::FunctionParam> function_params;
+  std::vector<std::unique_ptr<AST::Param>> function_params;
+
   if (lexer.peek_token ()->get_id () != RIGHT_PAREN)
     function_params
       = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
 
+  if (initial_param != nullptr)
+    function_params.insert (function_params.begin (),
+                           std::move (initial_param));
+
   if (!skip_token (RIGHT_PAREN))
     {
       Error error (lexer.peek_token ()->get_locus (),
@@ -2907,11 +2916,10 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
 
   return std::unique_ptr<AST::Function> (
     new AST::Function (std::move (function_name), std::move (qualifiers),
-                      std::move (generic_params),
-                      tl::optional<AST::SelfParam> (),
-                      std::move (function_params), std::move (return_type),
-                      std::move (where_clause), std::move (block_expr),
-                      std::move (vis), std::move (outer_attrs), locus));
+                      std::move (generic_params), std::move (function_params),
+                      std::move (return_type), std::move (where_clause),
+                      std::move (block_expr), std::move (vis),
+                      std::move (outer_attrs), locus));
 }
 
 // Parses function or method qualifiers (i.e. const, unsafe, and extern).
@@ -3525,18 +3533,18 @@ Parser<ManagedTokenSource>::parse_type_param ()
  * has end token handling. */
 template <typename ManagedTokenSource>
 template <typename EndTokenPred>
-std::vector<AST::FunctionParam>
+std::vector<std::unique_ptr<AST::Param>>
 Parser<ManagedTokenSource>::parse_function_params (EndTokenPred is_end_token)
 {
-  std::vector<AST::FunctionParam> params;
+  std::vector<std::unique_ptr<AST::Param>> params;
 
   if (is_end_token (lexer.peek_token ()->get_id ()))
     return params;
 
-  AST::FunctionParam initial_param = parse_function_param ();
+  auto initial_param = parse_function_param ();
 
   // Return empty parameter list if no parameter there
-  if (initial_param.is_error ())
+  if (initial_param == nullptr)
     {
       // TODO: is this an error?
       return params;
@@ -3558,15 +3566,15 @@ Parser<ManagedTokenSource>::parse_function_params (EndTokenPred is_end_token)
        break;
 
       // now, as right paren would break, function param is required
-      AST::FunctionParam param = parse_function_param ();
-      if (param.is_error ())
+      auto param = parse_function_param ();
+      if (param == nullptr)
        {
          Error error (lexer.peek_token ()->get_locus (),
                       "failed to parse function param (in function params)");
          add_error (std::move (error));
 
          // skip somewhere?
-         return std::vector<AST::FunctionParam> ();
+         return std::vector<std::unique_ptr<AST::Param>> ();
        }
 
       params.push_back (std::move (param));
@@ -3581,7 +3589,7 @@ Parser<ManagedTokenSource>::parse_function_params (EndTokenPred is_end_token)
 /* Parses a single regular (i.e. non-generic) parameter in a function or
  * method, i.e. the "name: type" bit. Also handles it not existing. */
 template <typename ManagedTokenSource>
-AST::FunctionParam
+std::unique_ptr<AST::Param>
 Parser<ManagedTokenSource>::parse_function_param ()
 {
   // parse outer attributes if they exist
@@ -3593,7 +3601,8 @@ Parser<ManagedTokenSource>::parse_function_param ()
   if (lexer.peek_token ()->get_id () == ELLIPSIS) // Unnamed variadic
     {
       lexer.skip_token (); // Skip ellipsis
-      return AST::FunctionParam (std::move (outer_attrs), locus);
+      return Rust::make_unique<AST::VariadicParam> (
+       AST::VariadicParam (std::move (outer_attrs), locus));
     }
 
   std::unique_ptr<AST::Pattern> param_pattern = parse_pattern ();
@@ -3602,32 +3611,32 @@ Parser<ManagedTokenSource>::parse_function_param ()
   if (param_pattern == nullptr)
     {
       // skip after something
-      return AST::FunctionParam::create_error ();
+      return nullptr;
     }
 
   if (!skip_token (COLON))
     {
       // skip after something
-      return AST::FunctionParam::create_error ();
+      return nullptr;
     }
 
   if (lexer.peek_token ()->get_id () == ELLIPSIS) // Named variadic
     {
       lexer.skip_token (); // Skip ellipsis
-      return AST::FunctionParam (std::move (param_pattern),
-                                std::move (outer_attrs), locus);
+      return Rust::make_unique<AST::VariadicParam> (
+       AST::VariadicParam (std::move (param_pattern), std::move (outer_attrs),
+                           locus));
     }
   else
     {
       std::unique_ptr<AST::Type> param_type = parse_type ();
       if (param_type == nullptr)
        {
-         // skip?
-         return AST::FunctionParam::create_error ();
+         return nullptr;
        }
-      return AST::FunctionParam (std::move (param_pattern),
-                                std::move (param_type),
-                                std::move (outer_attrs), locus);
+      return Rust::make_unique<AST::FunctionParam> (
+       AST::FunctionParam (std::move (param_pattern), std::move (param_type),
+                           std::move (outer_attrs), locus));
     }
 }
 
@@ -5051,13 +5060,14 @@ Parser<ManagedTokenSource>::parse_trait_item ()
 
        /* now for function vs method disambiguation - method has opening
         * "self" param */
-       AST::SelfParam self_param = parse_self_param ();
+       std::unique_ptr<AST::Param> initial_param = parse_self_param ();
        /* FIXME: ensure that self param doesn't accidently consume tokens for
         * a function */
        bool is_method = false;
-       if (!self_param.is_error ())
+       if (initial_param != nullptr)
          {
-           is_method = true;
+           if (initial_param->is_self ())
+             is_method = true;
 
            /* skip comma so function and method regular params can be parsed
             * in same way */
@@ -5066,7 +5076,7 @@ Parser<ManagedTokenSource>::parse_trait_item ()
          }
 
        // parse trait function params
-       std::vector<AST::FunctionParam> function_params
+       std::vector<std::unique_ptr<AST::Param>> function_params
          = parse_function_params (
            [] (TokenId id) { return id == RIGHT_PAREN; });
 
@@ -5076,6 +5086,10 @@ Parser<ManagedTokenSource>::parse_trait_item ()
            return nullptr;
          }
 
+       if (initial_param != nullptr)
+         function_params.insert (function_params.begin (),
+                                 std::move (initial_param));
+
        // parse return type (optional)
        std::unique_ptr<AST::Type> return_type = parse_function_return_type ();
 
@@ -5114,7 +5128,6 @@ Parser<ManagedTokenSource>::parse_trait_item ()
            AST::TraitMethodDecl method_decl (std::move (ident),
                                              std::move (qualifiers),
                                              std::move (generic_params),
-                                             std::move (self_param),
                                              std::move (function_params),
                                              std::move (return_type),
                                              std::move (where_clause));
@@ -5592,14 +5605,15 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
 
   // now for function vs method disambiguation - method has opening "self"
   // param
-  AST::SelfParam self_param = parse_self_param ();
+  std::unique_ptr<AST::Param> initial_param = parse_self_param ();
   /* FIXME: ensure that self param doesn't accidently consume tokens for a
    * function one idea is to lookahead up to 4 tokens to see whether self is
    * one of them */
   bool is_method = false;
-  if (!self_param.is_error ())
+  if (initial_param != nullptr)
     {
-      is_method = true;
+      if (initial_param->is_self ())
+       is_method = true;
 
       /* skip comma so function and method regular params can be parsed in
        * same way */
@@ -5608,9 +5622,13 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
     }
 
   // parse trait function params
-  std::vector<AST::FunctionParam> function_params
+  std::vector<std::unique_ptr<AST::Param>> function_params
     = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
 
+  if (initial_param != nullptr)
+    function_params.insert (function_params.begin (),
+                           std::move (initial_param));
+
   if (!skip_token (RIGHT_PAREN))
     {
       skip_after_end_block ();
@@ -5650,18 +5668,18 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
   // do actual if instead of ternary for return value optimisation
   if (is_method)
     {
-      return std::unique_ptr<AST::Function> (new AST::Function (
-       std::move (ident), std::move (qualifiers), std::move (generic_params),
-       tl::optional<AST::SelfParam> (tl::in_place, std::move (self_param)),
-       std::move (function_params), std::move (return_type),
-       std::move (where_clause), std::move (body), std::move (vis),
-       std::move (outer_attrs), locus));
+      return std::unique_ptr<AST::Function> (
+       new AST::Function (std::move (ident), std::move (qualifiers),
+                          std::move (generic_params),
+                          std::move (function_params), std::move (return_type),
+                          std::move (where_clause), std::move (body),
+                          std::move (vis), std::move (outer_attrs), locus));
     }
   else
     {
       return std::unique_ptr<AST::Function> (
        new AST::Function (std::move (ident), std::move (qualifiers),
-                          std::move (generic_params), tl::nullopt,
+                          std::move (generic_params),
                           std::move (function_params), std::move (return_type),
                           std::move (where_clause), std::move (body),
                           std::move (vis), std::move (outer_attrs), locus));
@@ -5795,13 +5813,14 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
 
   // now for function vs method disambiguation - method has opening "self"
   // param
-  AST::SelfParam self_param = parse_self_param ();
+  std::unique_ptr<AST::Param> initial_param = parse_self_param ();
   // FIXME: ensure that self param doesn't accidently consume tokens for a
   // function
   bool is_method = false;
-  if (!self_param.is_error ())
+  if (initial_param != nullptr)
     {
-      is_method = true;
+      if (initial_param->is_self ())
+       is_method = true;
 
       // skip comma so function and method regular params can be parsed in
       // same way
@@ -5819,7 +5838,7 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
     "started to parse function params in function or method trait impl item");
 
   // parse trait function params (only if next token isn't right paren)
-  std::vector<AST::FunctionParam> function_params;
+  std::vector<std::unique_ptr<AST::Param>> function_params;
   if (lexer.peek_token ()->get_id () != RIGHT_PAREN)
     {
       function_params
@@ -5838,6 +5857,10 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
        }
     }
 
+  if (initial_param != nullptr)
+    function_params.insert (function_params.begin (),
+                           std::move (initial_param));
+
   // DEBUG
   rust_debug ("successfully parsed function params in function or method "
              "trait impl item");
@@ -5886,24 +5909,12 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
       return nullptr;
     }
 
-  // do actual if instead of ternary for return value optimisation
-  if (is_method)
-    {
-      return std::unique_ptr<AST::Function> (new AST::Function (
-       std::move (ident), std::move (qualifiers), std::move (generic_params),
-       tl::optional<AST::SelfParam> (tl::in_place, std::move (self_param)),
-       std::move (function_params), std::move (return_type),
-       std::move (where_clause), std::move (body), std::move (vis),
-       std::move (outer_attrs), locus, is_default));
-    }
-  else
-    {
-      return std::unique_ptr<AST::Function> (new AST::Function (
-       std::move (ident), std::move (qualifiers), std::move (generic_params),
-       tl::nullopt, std::move (function_params), std::move (return_type),
-       std::move (where_clause), std::move (body), std::move (vis),
-       std::move (outer_attrs), locus, is_default));
-    }
+  return std::unique_ptr<AST::Function> (
+    new AST::Function (std::move (ident), std::move (qualifiers),
+                      std::move (generic_params), std::move (function_params),
+                      std::move (return_type), std::move (where_clause),
+                      std::move (body), std::move (vis),
+                      std::move (outer_attrs), locus, is_default));
 }
 
 // Parses an extern block of declarations.
@@ -7097,7 +7108,7 @@ Parser<ManagedTokenSource>::parse_qualified_path_in_type ()
 
 // Parses a self param. Also handles self param not existing.
 template <typename ManagedTokenSource>
-AST::SelfParam
+std::unique_ptr<AST::Param>
 Parser<ManagedTokenSource>::parse_self_param ()
 {
   bool has_reference = false;
@@ -7105,6 +7116,42 @@ Parser<ManagedTokenSource>::parse_self_param ()
 
   location_t locus = lexer.peek_token ()->get_locus ();
 
+  // TODO: Feels off, find a better way to clearly express this
+  std::vector<std::vector<TokenId>> ptrs
+    = {{ASTERISK, SELF} /* *self */,
+       {ASTERISK, CONST, SELF} /* *const self */,
+       {ASTERISK, MUT, SELF} /* *mut self */};
+
+  for (auto &s : ptrs)
+    {
+      size_t i = 0;
+      for (i = 0; i > s.size (); i++)
+       if (lexer.peek_token (i)->get_id () != s[i])
+         break;
+      if (i == s.size ())
+       rust_error_at (lexer.peek_token ()->get_locus (),
+                      "cannot pass %<self%> by raw pointer");
+    }
+
+  // Trying to find those patterns:
+  //
+  // &'lifetime mut self
+  // &'lifetime self
+  // & mut self
+  // & self
+  // mut self
+  // self
+  //
+  // If not found, it is probably a function, exit and let function parsing
+  // handle it.
+  bool is_self = false;
+  for (size_t i = 0; i < 5; i++)
+    if (lexer.peek_token (i)->get_id () == SELF)
+      is_self = true;
+
+  if (!is_self)
+    return nullptr;
+
   // test if self is a reference parameter
   if (lexer.peek_token ()->get_id () == AMP)
     {
@@ -7124,7 +7171,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
              add_error (std::move (error));
 
              // skip after somewhere?
-             return AST::SelfParam::create_error ();
+             return nullptr;
            }
        }
     }
@@ -7142,7 +7189,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
   if (self_tok->get_id () != SELF)
     {
       // skip after somewhere?
-      return AST::SelfParam::create_error ();
+      return nullptr;
     }
   lexer.skip_token ();
 
@@ -7161,7 +7208,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
          add_error (std::move (error));
 
          // skip after somewhere?
-         return AST::SelfParam::create_error ();
+         return nullptr;
        }
     }
 
@@ -7174,114 +7221,20 @@ Parser<ManagedTokenSource>::parse_self_param ()
       add_error (std::move (error));
 
       // skip after somewhere?
-      return AST::SelfParam::create_error ();
+      return nullptr;
     }
 
   if (has_reference)
     {
-      return AST::SelfParam (std::move (lifetime), has_mut, locus);
+      return Rust::make_unique<AST::SelfParam> (std::move (lifetime), has_mut,
+                                               locus);
     }
   else
     {
       // note that type may be nullptr here and that's fine
-      return AST::SelfParam (std::move (type), has_mut, locus);
-    }
-}
-
-/* Parses a method. Note that this function is probably useless because using
- * lookahead to determine whether a function is a method is a PITA (maybe not
- * even doable), so most places probably parse a "function or method" and then
- * resolve it into whatever it is afterward. As such, this is only here for
- * algorithmically defining the grammar rule. */
-template <typename ManagedTokenSource>
-std::unique_ptr<AST::Function>
-Parser<ManagedTokenSource>::parse_method ()
-{
-  location_t locus = lexer.peek_token ()->get_locus ();
-  /* Note: as a result of the above, this will not attempt to disambiguate a
-   * function parse qualifiers */
-  AST::FunctionQualifiers qualifiers = parse_function_qualifiers ();
-
-  skip_token (FN_TOK);
-
-  const_TokenPtr ident_tok = expect_token (IDENTIFIER);
-  if (ident_tok == nullptr)
-    {
-      skip_after_next_block ();
-      return nullptr;
+      return Rust::make_unique<AST::SelfParam> (std::move (type), has_mut,
+                                               locus);
     }
-  Identifier method_name{ident_tok};
-
-  // parse generic params - if exist
-  std::vector<std::unique_ptr<AST::GenericParam>> generic_params
-    = parse_generic_params_in_angles ();
-
-  if (!skip_token (LEFT_PAREN))
-    {
-      Error error (lexer.peek_token ()->get_locus (),
-                  "method missing opening parentheses before parameter list");
-      add_error (std::move (error));
-
-      skip_after_next_block ();
-      return nullptr;
-    }
-
-  // parse self param
-  AST::SelfParam self_param = parse_self_param ();
-  if (self_param.is_error ())
-    {
-      Error error (lexer.peek_token ()->get_locus (),
-                  "could not parse self param in method");
-      add_error (std::move (error));
-
-      skip_after_next_block ();
-      return nullptr;
-    }
-
-  // skip comma if it exists
-  if (lexer.peek_token ()->get_id () == COMMA)
-    lexer.skip_token ();
-
-  // parse function parameters
-  std::vector<AST::FunctionParam> function_params
-    = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
-
-  if (!skip_token (RIGHT_PAREN))
-    {
-      Error error (lexer.peek_token ()->get_locus (),
-                  "method declaration missing closing parentheses after "
-                  "parameter list");
-      add_error (std::move (error));
-
-      skip_after_next_block ();
-      return nullptr;
-    }
-
-  // parse function return type - if exists
-  std::unique_ptr<AST::Type> return_type = parse_function_return_type ();
-
-  // parse where clause - if exists
-  AST::WhereClause where_clause = parse_where_clause ();
-
-  // parse block expression
-  std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr ();
-  if (block_expr == nullptr)
-    {
-      Error error (lexer.peek_token ()->get_locus (),
-                  "method declaration missing block expression");
-      add_error (std::move (error));
-
-      skip_after_end_block ();
-      return nullptr;
-    }
-
-  // does not parse visibility, but this method isn't used, so doesn't matter
-  return std::unique_ptr<AST::Function> (new AST::Function (
-    std::move (method_name), std::move (qualifiers), std::move (generic_params),
-    tl::optional<AST::SelfParam> (tl::in_place, std::move (self_param)),
-    std::move (function_params), std::move (return_type),
-    std::move (where_clause), std::move (block_expr),
-    AST::Visibility::create_error (), AST::AttrVec (), locus));
 }
 
 /* Parses an expression or macro statement. */
index 3ff9b99caed0a96806b2b22ac22403ff02e2e50e..9e924e0015ce4895d72b632c891899651129f742 100644 (file)
@@ -164,7 +164,7 @@ public:
   std::unique_ptr<AST::InherentImplItem> parse_inherent_impl_item ();
   std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item ();
   AST::PathInExpression parse_path_in_expression ();
-  std::vector<std::unique_ptr<AST::LifetimeParam> > parse_lifetime_params ();
+  std::vector<std::unique_ptr<AST::LifetimeParam>> parse_lifetime_params ();
   AST::Visibility parse_visibility ();
   std::unique_ptr<AST::IdentifierPattern> parse_identifier_pattern ();
   std::unique_ptr<AST::Token> parse_identifier_or_keyword_token ();
@@ -246,17 +246,17 @@ private:
   std::unique_ptr<AST::Function> parse_function (AST::Visibility vis,
                                                 AST::AttrVec outer_attrs);
   AST::FunctionQualifiers parse_function_qualifiers ();
-  std::vector<std::unique_ptr<AST::GenericParam> >
+  std::vector<std::unique_ptr<AST::GenericParam>>
   parse_generic_params_in_angles ();
   template <typename EndTokenPred>
-  std::vector<std::unique_ptr<AST::GenericParam> >
+  std::vector<std::unique_ptr<AST::GenericParam>>
   parse_generic_params (EndTokenPred is_end_token);
   template <typename EndTokenPred>
   std::unique_ptr<AST::GenericParam>
   parse_generic_param (EndTokenPred is_end_token);
 
   template <typename EndTokenPred>
-  std::vector<std::unique_ptr<AST::LifetimeParam> >
+  std::vector<std::unique_ptr<AST::LifetimeParam>>
   parse_lifetime_params (EndTokenPred is_end_token);
   std::vector<AST::LifetimeParam> parse_lifetime_params_objs ();
   template <typename EndTokenPred>
@@ -268,15 +268,15 @@ private:
     std::string error_msg = "failed to parse generic param in generic params")
     -> std::vector<decltype (parsing_function ())>;
   AST::LifetimeParam parse_lifetime_param ();
-  std::vector<std::unique_ptr<AST::TypeParam> > parse_type_params ();
+  std::vector<std::unique_ptr<AST::TypeParam>> parse_type_params ();
   template <typename EndTokenPred>
-  std::vector<std::unique_ptr<AST::TypeParam> >
+  std::vector<std::unique_ptr<AST::TypeParam>>
   parse_type_params (EndTokenPred is_end_token);
   std::unique_ptr<AST::TypeParam> parse_type_param ();
   template <typename EndTokenPred>
-  std::vector<AST::FunctionParam>
+  std::vector<std::unique_ptr<AST::Param>>
   parse_function_params (EndTokenPred is_end_token);
-  AST::FunctionParam parse_function_param ();
+  std::unique_ptr<AST::Param> parse_function_param ();
   std::unique_ptr<AST::Type> parse_function_return_type ();
   AST::WhereClause parse_where_clause ();
   std::unique_ptr<AST::WhereClauseItem> parse_where_clause_item ();
@@ -286,9 +286,9 @@ private:
   parse_type_bound_where_clause_item ();
   std::vector<AST::LifetimeParam> parse_for_lifetimes ();
   template <typename EndTokenPred>
-  std::vector<std::unique_ptr<AST::TypeParamBound> >
+  std::vector<std::unique_ptr<AST::TypeParamBound>>
   parse_type_param_bounds (EndTokenPred is_end_token);
-  std::vector<std::unique_ptr<AST::TypeParamBound> > parse_type_param_bounds ();
+  std::vector<std::unique_ptr<AST::TypeParamBound>> parse_type_param_bounds ();
   std::unique_ptr<AST::TypeParamBound> parse_type_param_bound ();
   std::unique_ptr<AST::TraitBound> parse_trait_bound ();
   std::vector<AST::Lifetime> parse_lifetime_bounds ();
@@ -317,9 +317,9 @@ private:
   AST::TupleField parse_tuple_field ();
   std::unique_ptr<AST::Enum> parse_enum (AST::Visibility vis,
                                         AST::AttrVec outer_attrs);
-  std::vector<std::unique_ptr<AST::EnumItem> > parse_enum_items ();
+  std::vector<std::unique_ptr<AST::EnumItem>> parse_enum_items ();
   template <typename EndTokenPred>
-  std::vector<std::unique_ptr<AST::EnumItem> >
+  std::vector<std::unique_ptr<AST::EnumItem>>
   parse_enum_items (EndTokenPred is_end_token);
   std::unique_ptr<AST::EnumItem> parse_enum_item ();
   std::unique_ptr<AST::Union> parse_union (AST::Visibility vis,
@@ -334,7 +334,7 @@ private:
   parse_trait_type (AST::AttrVec outer_attrs);
   std::unique_ptr<AST::TraitItemConst>
   parse_trait_const (AST::AttrVec outer_attrs);
-  AST::SelfParam parse_self_param ();
+  std::unique_ptr<AST::Param> parse_self_param ();
   std::unique_ptr<AST::Impl> parse_impl (AST::Visibility vis,
                                         AST::AttrVec outer_attrs);
   std::unique_ptr<AST::InherentImplItem>
@@ -594,7 +594,7 @@ private:
   parse_match_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
                    location_t pratt_parsed_loc = UNKNOWN_LOCATION);
   AST::MatchArm parse_match_arm ();
-  std::vector<std::unique_ptr<AST::Pattern> >
+  std::vector<std::unique_ptr<AST::Pattern>>
   parse_match_arm_patterns (TokenId end_token_id);
   std::unique_ptr<AST::Expr> parse_labelled_loop_expr (const_TokenPtr tok,
                                                       AST::AttrVec outer_attrs
@@ -692,7 +692,7 @@ public:
 
   // Parse items without parsing an entire crate. This function is the main
   // parsing loop of AST::Crate::parse_crate().
-  std::vector<std::unique_ptr<AST::Item> > parse_items ();
+  std::vector<std::unique_ptr<AST::Item>> parse_items ();
 
   // Main entry point for parser.
   std::unique_ptr<AST::Crate> parse_crate ();
index 34ebbc7dfba1b584d47db6fda21cf5476e7ee3dc..1283d77d22bbf80da3be7c8f35c54116c6e45ea0 100644 (file)
@@ -646,5 +646,17 @@ void
 ResolverBase::visit (AST::BareFunctionType &)
 {}
 
+void
+ResolverBase::visit (AST::SelfParam &)
+{}
+
+void
+ResolverBase::visit (AST::VariadicParam &)
+{}
+
+void
+ResolverBase::visit (AST::FunctionParam &)
+{}
+
 } // namespace Resolver
 } // namespace Rust
index f9ae7011eae7edd6fa31b6554c7719c4af28b505..7883049877164787f3f121a36fbe06a36ee36dd2 100644 (file)
@@ -196,6 +196,9 @@ public:
   void visit (AST::SliceType &);
   void visit (AST::InferredType &);
   void visit (AST::BareFunctionType &);
+  void visit (AST::FunctionParam &param);
+  void visit (AST::VariadicParam &param);
+  void visit (AST::SelfParam &param);
 
 protected:
   ResolverBase ()
index 4c6958d0b81040878e31d332ce8c54a0e12bb6ce..1fc6b920c5e42e71add905f34bddebd3a33736b0 100644 (file)
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-ast-resolve-item.h"
+#include "rust-ast-full-decls.h"
 #include "rust-ast-resolve-toplevel.h"
 #include "rust-ast-resolve-type.h"
 #include "rust-ast-resolve-pattern.h"
 #include "rust-ast-resolve-path.h"
 
+#include "rust-item.h"
 #include "selftest.h"
 
 namespace Rust {
@@ -87,11 +89,26 @@ ResolveTraitItems::visit (AST::TraitItemFunc &func)
 
   // we make a new scope so the names of parameters are resolved and shadowed
   // correctly
-  for (auto &param : function.get_function_params ())
+  for (auto &p : function.get_function_params ())
     {
-      ResolveType::go (param.get_type ().get ());
-      PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param,
-                             bindings);
+      if (p->is_variadic ())
+       {
+         auto param = static_cast<AST::VariadicParam *> (p.get ());
+         PatternDeclaration::go (param->get_pattern ().get (),
+                                 Rib::ItemType::Param, bindings);
+       }
+      else if (p->is_self ())
+       {
+         auto param = static_cast<AST::SelfParam *> (p.get ());
+         ResolveType::go (param->get_type ().get ());
+       }
+      else
+       {
+         auto param = static_cast<AST::FunctionParam *> (p.get ());
+         ResolveType::go (param->get_type ().get ());
+         PatternDeclaration::go (param->get_pattern ().get (),
+                                 Rib::ItemType::Param, bindings);
+       }
     }
 
   if (function.has_where_clause ())
@@ -133,43 +150,55 @@ ResolveTraitItems::visit (AST::TraitItemMethod &func)
     ResolveType::go (function.get_return_type ().get ());
 
   // self turns into (self: Self) as a function param
-  AST::SelfParam &self_param = function.get_self_param ();
-  // FIXME: which location should be used for Rust::Identifier `self`?
-  AST::IdentifierPattern self_pattern (self_param.get_node_id (), {"self"},
-                                      self_param.get_locus (),
-                                      self_param.get_has_ref (),
-                                      self_param.get_is_mut (),
-                                      std::unique_ptr<AST::Pattern> (nullptr));
-  PatternDeclaration::go (&self_pattern, Rib::ItemType::Param);
-
-  if (self_param.has_type ())
-    {
-      // This shouldn't happen the parser should already error for this
-      rust_assert (!self_param.get_has_ref ());
-      ResolveType::go (self_param.get_type ().get ());
-    }
-  else
-    {
-      // here we implicitly make self have a type path of Self
-      std::vector<std::unique_ptr<AST::TypePathSegment>> segments;
-      segments.push_back (std::unique_ptr<AST::TypePathSegment> (
-       new AST::TypePathSegment ("Self", false, self_param.get_locus ())));
-
-      AST::TypePath self_type_path (std::move (segments),
-                                   self_param.get_locus ());
-      ResolveType::go (&self_type_path);
-    }
-
   std::vector<PatternBinding> bindings
     = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
 
   // we make a new scope so the names of parameters are resolved and shadowed
   // correctly
-  for (auto &param : function.get_function_params ())
+  for (auto &p : function.get_function_params ())
     {
-      ResolveType::go (param.get_type ().get ());
-      PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param,
-                             bindings);
+      if (p->is_variadic ())
+       {
+         auto param = static_cast<AST::VariadicParam *> (p.get ());
+         PatternDeclaration::go (param->get_pattern ().get (),
+                                 Rib::ItemType::Param, bindings);
+       }
+      else if (p->is_self ())
+       {
+         auto param = static_cast<AST::SelfParam *> (p.get ());
+         // FIXME: which location should be used for Rust::Identifier `self`?
+         AST::IdentifierPattern self_pattern (
+           param->get_node_id (), {"self"}, param->get_locus (),
+           param->get_has_ref (), param->get_is_mut (),
+           std::unique_ptr<AST::Pattern> (nullptr));
+
+         PatternDeclaration::go (&self_pattern, Rib::ItemType::Param);
+
+         if (param->has_type ())
+           {
+             // This shouldn't happen the parser should already error for this
+             rust_assert (!param->get_has_ref ());
+             ResolveType::go (param->get_type ().get ());
+           }
+         else
+           {
+             // here we implicitly make self have a type path of Self
+             std::vector<std::unique_ptr<AST::TypePathSegment>> segments;
+             segments.push_back (std::unique_ptr<AST::TypePathSegment> (
+               new AST::TypePathSegment ("Self", false, param->get_locus ())));
+
+             AST::TypePath self_type_path (std::move (segments),
+                                           param->get_locus ());
+             ResolveType::go (&self_type_path);
+           }
+       }
+      else
+       {
+         auto param = static_cast<AST::FunctionParam *> (p.get ());
+         ResolveType::go (param->get_type ().get ());
+         PatternDeclaration::go (param->get_pattern ().get (),
+                                 Rib::ItemType::Param, bindings);
+       }
     }
 
   if (function.has_where_clause ())
@@ -527,29 +556,32 @@ ResolveItem::visit (AST::Function &function)
   if (function.has_self_param ())
     {
       // self turns into (self: Self) as a function param
-      AST::SelfParam &self_param = function.get_self_param ();
+      std::unique_ptr<AST::Param> &s_param = function.get_self_param ();
+      auto self_param = static_cast<AST::SelfParam *> (s_param.get ());
+
       // FIXME: which location should be used for Rust::Identifier `self`?
       AST::IdentifierPattern self_pattern (
-       self_param.get_node_id (), {"self"}, self_param.get_locus (),
-       self_param.get_has_ref (), self_param.get_is_mut (),
+       self_param->get_node_id (), {"self"}, self_param->get_locus (),
+       self_param->get_has_ref (), self_param->get_is_mut (),
        std::unique_ptr<AST::Pattern> (nullptr));
       PatternDeclaration::go (&self_pattern, Rib::ItemType::Param);
 
-      if (self_param.has_type ())
+      if (self_param->has_type ())
        {
          // This shouldn't happen the parser should already error for this
-         rust_assert (!self_param.get_has_ref ());
-         ResolveType::go (self_param.get_type ().get ());
+         rust_assert (!self_param->get_has_ref ());
+         ResolveType::go (self_param->get_type ().get ());
        }
       else
        {
          // here we implicitly make self have a type path of Self
          std::vector<std::unique_ptr<AST::TypePathSegment>> segments;
          segments.push_back (std::unique_ptr<AST::TypePathSegment> (
-           new AST::TypePathSegment ("Self", false, self_param.get_locus ())));
+           new AST::TypePathSegment ("Self", false,
+                                     self_param->get_locus ())));
 
          AST::TypePath self_type_path (std::move (segments),
-                                       self_param.get_locus ());
+                                       self_param->get_locus ());
          ResolveType::go (&self_type_path);
        }
     }
@@ -559,11 +591,28 @@ ResolveItem::visit (AST::Function &function)
 
   // we make a new scope so the names of parameters are resolved and shadowed
   // correctly
-  for (auto &param : function.get_function_params ())
+  for (auto &p : function.get_function_params ())
     {
-      ResolveType::go (param.get_type ().get ());
-      PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param,
-                             bindings);
+      if (p->is_variadic ())
+       {
+         auto param = static_cast<AST::VariadicParam *> (p.get ());
+         if (param->has_pattern ())
+           PatternDeclaration::go (param->get_pattern ().get (),
+                                   Rib::ItemType::Param, bindings);
+       }
+      else if (p->is_self ())
+       {
+         auto param = static_cast<AST::SelfParam *> (p.get ());
+         if (param->has_type ())
+           ResolveType::go (param->get_type ().get ());
+       }
+      else
+       {
+         auto param = static_cast<AST::FunctionParam *> (p.get ());
+         ResolveType::go (param->get_type ().get ());
+         PatternDeclaration::go (param->get_pattern ().get (),
+                                 Rib::ItemType::Param, bindings);
+       }
     }
 
   // resolve the function body
index 6d5f5324fb0fe63d44f4bc00330bfcce03dfa111..293c98fd6f29265b7c35d2237a7fedc2398793fa 100644 (file)
@@ -23,6 +23,7 @@
 #include "rust-ast-resolve-type.h"
 #include "rust-ast-resolve-pattern.h"
 #include "rust-ast-resolve-expr.h"
+#include "rust-item.h"
 
 namespace Rust {
 namespace Resolver {
@@ -352,11 +353,28 @@ public:
 
     // we make a new scope so the names of parameters are resolved and shadowed
     // correctly
-    for (auto &param : function.get_function_params ())
+    for (auto &p : function.get_function_params ())
       {
-       ResolveType::go (param.get_type ().get ());
-       PatternDeclaration::go (param.get_pattern ().get (),
-                               Rib::ItemType::Param, bindings);
+       if (p->is_variadic ())
+         {
+           auto param = static_cast<AST::VariadicParam *> (p.get ());
+           PatternDeclaration::go (param->get_pattern ().get (),
+                                   Rib::ItemType::Param, bindings);
+         }
+
+       else if (p->is_self ())
+         {
+           auto param = static_cast<AST::SelfParam *> (p.get ());
+           ResolveType::go (param->get_type ().get ());
+         }
+       else
+         {
+           auto param = static_cast<AST::FunctionParam *> (p.get ());
+
+           ResolveType::go (param->get_type ().get ());
+           PatternDeclaration::go (param->get_pattern ().get (),
+                                   Rib::ItemType::Param, bindings);
+         }
       }
 
     // resolve the function body
index fc81001689b2e70ed216e5944e5054bd59f1fd20..1ab174b6caa43a4c424a41c8d6a1d98e11242566 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "rust-default-resolver.h"
 #include "rust-ast-full.h"
+#include "rust-item.h"
 
 namespace Rust {
 namespace Resolver2_0 {
@@ -55,10 +56,25 @@ void
 DefaultResolver::visit (AST::Function &function)
 {
   auto def_fn = [this, &function] () {
-    for (auto &param : function.get_function_params ())
+    for (auto &p : function.get_function_params ())
       {
-       param.get_pattern ()->accept_vis (*this);
-       param.get_type ()->accept_vis (*this);
+       if (p->is_variadic ())
+         {
+           auto param = static_cast<AST::VariadicParam *> (p.get ());
+           param->get_pattern ()->accept_vis (*this);
+         }
+       else if (p->is_self ())
+         {
+           auto param = static_cast<AST::SelfParam *> (p.get ());
+           param->get_type ()->accept_vis (*this);
+           param->get_lifetime ().accept_vis (*this);
+         }
+       else
+         {
+           auto param = static_cast<AST::FunctionParam *> (p.get ());
+           param->get_pattern ()->accept_vis (*this);
+           param->get_type ()->accept_vis (*this);
+         }
       }
 
     function.get_definition ()->accept_vis (*this);
@@ -801,5 +817,17 @@ void
 DefaultResolver::visit (AST::BareFunctionType &)
 {}
 
+void
+DefaultResolver::visit (AST::SelfParam &)
+{}
+
+void
+DefaultResolver::visit (AST::FunctionParam &)
+{}
+
+void
+DefaultResolver::visit (AST::VariadicParam &)
+{}
+
 } // namespace Resolver2_0
 } // namespace Rust
index 8af9513b25c3e43d554d0840c853ddd45cd573a1..49255d3bc26c48c0bf306caa2e9e73e00ba8d70c 100644 (file)
@@ -197,6 +197,9 @@ public:
   void visit (AST::SliceType &);
   void visit (AST::InferredType &);
   void visit (AST::BareFunctionType &);
+  void visit (AST::FunctionParam &);
+  void visit (AST::VariadicParam &);
+  void visit (AST::SelfParam &);
 
 protected:
   DefaultResolver (NameResolutionContext &ctx) : ctx (ctx) {}
index 455da3030f8f85319cfe7020c679f22948f66faa..38a16408436a41a701cf20962bb33e860a969a8e 100644 (file)
@@ -662,11 +662,8 @@ EarlyNameResolver::visit (AST::Function &function)
     for (auto &generic : function.get_generic_params ())
       generic->accept_vis (*this);
 
-  if (function.has_self_param () && function.get_self_param ().has_type ())
-    function.get_self_param ().get_type ()->accept_vis (*this);
-
-  for (auto &param : function.get_function_params ())
-    param.get_type ()->accept_vis (*this);
+  for (auto &p : function.get_function_params ())
+    p->accept_vis (*this);
 
   if (function.has_return_type ())
     function.get_return_type ()->accept_vis (*this);
@@ -758,8 +755,8 @@ EarlyNameResolver::visit (AST::TraitItemFunc &item)
   for (auto &generic : decl.get_generic_params ())
     generic->accept_vis (*this);
 
-  for (auto &param : decl.get_function_params ())
-    param.get_type ()->accept_vis (*this);
+  for (auto &p : decl.get_function_params ())
+    p->accept_vis (*this);
 
   if (item.has_definition ())
     item.get_definition ()->accept_vis (*this);
@@ -777,8 +774,8 @@ EarlyNameResolver::visit (AST::TraitItemMethod &item)
   for (auto &generic : decl.get_generic_params ())
     generic->accept_vis (*this);
 
-  for (auto &param : decl.get_function_params ())
-    param.get_type ()->accept_vis (*this);
+  for (auto &p : decl.get_function_params ())
+    p->accept_vis (*this);
 
   if (item.has_definition ())
     item.get_definition ()->accept_vis (*this);
@@ -1232,5 +1229,28 @@ EarlyNameResolver::visit (AST::BareFunctionType &type)
     type.get_return_type ()->accept_vis (*this);
 }
 
+void
+EarlyNameResolver::visit (AST::VariadicParam &param)
+{
+  if (param.has_pattern ())
+    param.get_pattern ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::FunctionParam &param)
+{
+  param.get_pattern ()->accept_vis (*this);
+  param.get_type ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::SelfParam &param)
+{
+  if (param.has_type ())
+    param.get_type ()->accept_vis (*this);
+  if (param.has_lifetime ())
+    param.get_lifetime ().accept_vis (*this);
+}
+
 } // namespace Resolver
 } // namespace Rust
index 41728c6fc1fe45ed044db67cb7e15dfebb17b35d..cebc6e4b5afa3763516a13a57b51fa3db4d6e2b2 100644 (file)
@@ -277,6 +277,10 @@ private:
   virtual void visit (AST::SliceType &type);
   virtual void visit (AST::InferredType &type);
   virtual void visit (AST::BareFunctionType &type);
+
+  virtual void visit (AST::VariadicParam &type);
+  virtual void visit (AST::FunctionParam &type);
+  virtual void visit (AST::SelfParam &type);
 };
 
 } // namespace Resolver
index 3966ccd904e5957d39a703fbfc4178846b4a0b95..981bc738d6caf2eb96934a8cdcb596b5c7484f99 100644 (file)
@@ -996,5 +996,17 @@ void
 AttributeChecker::visit (AST::BareFunctionType &)
 {}
 
+void
+AttributeChecker::visit (AST::SelfParam &)
+{}
+
+void
+AttributeChecker::visit (AST::VariadicParam &)
+{}
+
+void
+AttributeChecker::visit (AST::FunctionParam &)
+{}
+
 } // namespace Analysis
 } // namespace Rust
index 5a93e1c5db9f28ffc7d76e8facc22c9828b81e65..9db371e81c695309d81b8c7c48eb3aaf06d3c87a 100644 (file)
@@ -264,6 +264,9 @@ private:
   void visit (AST::SliceType &type);
   void visit (AST::InferredType &type);
   void visit (AST::BareFunctionType &type);
+  void visit (AST::FunctionParam &param);
+  void visit (AST::VariadicParam &param);
+  void visit (AST::SelfParam &param);
 };
 
 } // namespace Analysis