diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index 83260720aff7..05c9630bf523 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -16,6 +16,7 @@
// along with GCC; see the file COPYING3. If not see
// .
#include "rust-ast-collector.h"
+#include "rust-item.h"
namespace Rust {
namespace AST {
@@ -190,6 +191,17 @@ TokenCollector::visit (FunctionParam ¶m)
}
}
+void
+TokenCollector::visit (VariadicParam ¶m)
+{
+ 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));
diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h
index 47655286dd9e..20ffd8e65abf 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -163,6 +163,7 @@ class TokenCollector : public ASTVisitor
void visit (Literal &lit, location_t locus = UNDEF_LOCATION);
void visit (FunctionParam ¶m);
+ void visit (VariadicParam ¶m);
void visit (Attribute &attrib);
void visit (Visibility &vis);
void visit (std::vector> ¶ms);
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index b4d1011a03ea..d8395820892e 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -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 ¶m)
if (param.has_name ())
visit (param.get_pattern ());
- if (!param.is_variadic ())
+ visit (param.get_type ());
+}
+
+void
+DefaultASTVisitor::visit (AST::SelfParam ¶m)
+{
+ 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 ¶m)
+{
+ if (param.has_pattern ())
+ visit (param.get_pattern ());
+}
+
void
ContextualASTVisitor::visit (AST::Crate &crate)
{
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index 48b3de57e3ac..00886f616e30 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -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 @@ class ASTVisitor
// rust-item.h
virtual void visit (TypeParam ¶m) = 0;
+ virtual void visit (SelfParam ¶m) = 0;
+ virtual void visit (FunctionParam ¶m) = 0;
+ virtual void visit (VariadicParam ¶m) = 0;
+
// virtual void visit(WhereClauseItem& item) = 0;
virtual void visit (LifetimeWhereClauseItem &item) = 0;
virtual void visit (TypeBoundWhereClauseItem &item) = 0;
@@ -386,6 +391,9 @@ class DefaultASTVisitor : public ASTVisitor
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 ¶m) override;
+ virtual void visit (AST::VariadicParam ¶m) override;
template void visit (T &node);
@@ -406,9 +414,7 @@ class DefaultASTVisitor : public ASTVisitor
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 ¶m);
virtual void visit (AST::StructField &field);
virtual void visit (AST::TupleField &field);
virtual void visit (AST::TraitFunctionDecl &decl);
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 9c6862e92610..d80c00298919 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -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 ¶m : 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 ¶m : function_params)
- str += "\n " + param.as_string ();
+ str += "\n " + param->as_string ();
}
else
{
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 0d00c489ba0a..cd0577ce3f5f 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1042,6 +1042,173 @@ class Item : public Stmt
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 clone_visibility() const {
+ return std::unique_ptr(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 outer_attrs;
+
+protected:
+ // Visibility constructor
+ VisItem (Visibility visibility,
+ std::vector outer_attrs = std::vector ())
+ : 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 &get_outer_attrs () override { return outer_attrs; }
+ const std::vector &get_outer_attrs () const override
+ {
+ return outer_attrs;
+ }
+};
// forward decl of ExprWithoutBlock
class ExprWithoutBlock;
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 4dc240c4aa75..4830ae0d2d38 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -3,6 +3,7 @@
#include "rust-ast.h"
#include "rust-path.h"
+#include "rust-macro.h"
#include "rust-operators.h"
namespace Rust {
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 0e38103e81d5..81bb17ea0d6e 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -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 @@ class WhereClause
}
};
+// Abstract class Param
+class Param : public Visitable
+{
+public:
+ Param (std::vector 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 clone_param () const
+ {
+ return std::unique_ptr (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 get_outer_attrs () const { return outer_attrs; }
+
+ std::vector &get_outer_attrs () { return outer_attrs; }
+
+ virtual Param *clone_param_impl () const = 0;
+
+ virtual std::string as_string () const = 0;
+
+protected:
+ std::vector 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;
- 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 @@ class SelfParam
// Type-based self parameter (not ref, no lifetime)
SelfParam (std::unique_ptr 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 @@ class SelfParam
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 @@ class SelfParam
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 @@ class SelfParam
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 @@ class FunctionQualifiers
location_t get_locus () const { return locus; }
};
-// A function parameter
-class FunctionParam
+class VariadicParam : public Param
{
- std::vector outer_attrs;
- location_t locus;
std::unique_ptr param_name;
- std::unique_ptr type;
- bool variadic;
public:
- FunctionParam (std::unique_ptr param_name,
- std::unique_ptr param_type,
+ VariadicParam (std::unique_ptr param_name,
std::vector 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 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 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 &get_pattern ()
+ {
+ rust_assert (param_name != nullptr);
+ return param_name;
+ }
+
+ const std::unique_ptr &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 param_name;
+ std::unique_ptr type;
+
+public:
FunctionParam (std::unique_ptr param_name,
+ std::unique_ptr param_type,
std::vector 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 @@ class FunctionParam
{
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 @@ class FunctionParam
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 @@ class FunctionParam
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 &get_outer_attrs () { return outer_attrs; }
@@ -627,181 +705,12 @@ class FunctionParam
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 clone_visibility() const {
- return std::unique_ptr(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 outer_attrs;
-
-protected:
- // Visibility constructor
- VisItem (Visibility visibility,
- std::vector outer_attrs = std::vector ())
- : 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 &get_outer_attrs () override { return outer_attrs; }
- const std::vector &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> generic_params;
- tl::optional self_param;
- std::vector function_params;
+ std::vector> function_params;
std::unique_ptr return_type;
WhereClause where_clause;
std::unique_ptr function_body;
@@ -1395,13 +1303,15 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem
// 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> generic_params,
- tl::optional self_param,
- std::vector function_params,
+ std::vector> function_params,
std::unique_ptr return_type, WhereClause where_clause,
std::unique_ptr function_body, Visibility vis,
std::vector outer_attrs, location_t locus,
@@ -1410,7 +1320,6 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem
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 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem
// 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 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem
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 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem
return function_body == nullptr;
}
- std::vector &get_function_params () { return function_params; }
- const std::vector &get_function_params () const
+ std::vector> &get_function_params ()
+ {
+ return function_params;
+ }
+ const std::vector> &get_function_params () const
{
return function_params;
}
@@ -1533,15 +1397,15 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem
return return_type;
}
- SelfParam &get_self_param ()
+ std::unique_ptr &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 &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 function_params; // inlined
+ std::vector> function_params; // inlined
// bool has_return_type;
std::unique_ptr return_type;
@@ -2696,7 +2560,7 @@ class TraitFunctionDecl
// Mega-constructor
TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers,
std::vector> generic_params,
- std::vector function_params,
+ std::vector> function_params,
std::unique_ptr return_type,
WhereClause where_clause)
: qualifiers (std::move (qualifiers)),
@@ -2710,7 +2574,7 @@ class TraitFunctionDecl
// 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 @@ class TraitFunctionDecl
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 @@ class TraitFunctionDecl
{
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 @@ class TraitFunctionDecl
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 @@ class TraitFunctionDecl
bool is_marked_for_strip () const { return function_name.empty (); }
// TODO: this mutable getter seems really dodgy. Think up better way.
- std::vector &get_function_params () { return function_params; }
- const std::vector &get_function_params () const
+ std::vector> &get_function_params ()
+ {
+ return function_params;
+ }
+ const std::vector> &get_function_params () const
{
return function_params;
}
@@ -2798,34 +2672,11 @@ class TraitItemFunc : public TraitItem
{}
// 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> generic_params; // inlined
- SelfParam self_param;
-
// bool has_params;
// FunctionParams function_params;
- std::vector function_params; // inlined
+ std::vector> function_params; // inlined
// bool has_return_type;
std::unique_ptr return_type;
@@ -2907,13 +2756,11 @@ class TraitMethodDecl
// Mega-constructor
TraitMethodDecl (Identifier function_name, FunctionQualifiers qualifiers,
std::vector> generic_params,
- SelfParam self_param,
- std::vector function_params,
+ std::vector> function_params,
std::unique_ptr 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 @@ class TraitMethodDecl
// 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 @@ class TraitMethodDecl
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 @@ class TraitMethodDecl
{
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 @@ class TraitMethodDecl
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 @@ class TraitMethodDecl
bool is_marked_for_strip () const { return function_name.empty (); }
// TODO: this mutable getter seems really dodgy. Think up better way.
- std::vector &get_function_params () { return function_params; }
- const std::vector &get_function_params () const
+ std::vector> &get_function_params ()
+ {
+ return function_params;
+ }
+ const std::vector> &get_function_params () const
{
return function_params;
}
@@ -2990,8 +2845,21 @@ class TraitMethodDecl
// 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 &get_self_param ()
+ {
+ rust_assert (has_self ());
+ return function_params[0];
+ }
+ const std::unique_ptr &get_self_param () const
+ {
+ rust_assert (has_self ());
+ return function_params[0];
+ }
FunctionQualifiers get_qualifiers () const { return qualifiers; }
@@ -3016,34 +2884,9 @@ class TraitItemMethod : public TraitItem
{}
// 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;
diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index a903297d19b8..f6ce45eaccab 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -81,4 +81,19 @@ ASTValidation::visit (AST::ExternalFunctionItem &item)
AST::ContextualASTVisitor::visit (item);
}
+void
+ASTValidation::visit (AST::Function &function)
+{
+ std::set 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 (),
+ "% parameter is only allowed in associated functions");
+
+ AST::ContextualASTVisitor::visit (function);
+}
+
} // namespace Rust
diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h
index 6028b21ff006..44995eb1fbce 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.h
+++ b/gcc/rust/checks/errors/rust-ast-validation.h
@@ -37,6 +37,7 @@ class ASTValidation : public AST::ContextualASTVisitor
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
diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/rust-feature-gate.h
index 298582d4e94d..ca61199403f1 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.h
+++ b/gcc/rust/checks/errors/rust-feature-gate.h
@@ -183,6 +183,9 @@ class FeatureGate : public AST::ASTVisitor
void visit (AST::SliceType &type) override {}
void visit (AST::InferredType &type) override {}
void visit (AST::BareFunctionType &type) override {}
+ void visit (AST::FunctionParam ¶m) override {}
+ void visit (AST::VariadicParam ¶m) override {}
+ void visit (AST::SelfParam ¶m) override {}
private:
void gate (Feature::Name name, location_t loc, const std::string &error_msg);
diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc
index 6bf3a2591963..7e50db6b1c57 100644
--- a/gcc/rust/expand/rust-cfg-strip.cc
+++ b/gcc/rust/expand/rust-cfg-strip.cc
@@ -218,34 +218,37 @@ CfgStrip::maybe_strip_tuple_fields (std::vector &fields)
}
void
-CfgStrip::maybe_strip_function_params (std::vector ¶ms)
+CfgStrip::maybe_strip_function_params (
+ std::vector> ¶ms)
{
for (auto it = params.begin (); it != params.end ();)
{
- auto ¶m = *it;
-
- auto ¶m_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 (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 ¶m_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 ¶m : 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 ¶m : 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 ¶m)
+{
+ 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
diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h
index b3bb3fbe4cee..47c977030459 100644
--- a/gcc/rust/expand/rust-cfg-strip.h
+++ b/gcc/rust/expand/rust-cfg-strip.h
@@ -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 @@ class CfgStrip : public AST::ASTVisitor
void maybe_strip_struct_fields (std::vector &fields);
void maybe_strip_tuple_fields (std::vector &fields);
- void maybe_strip_function_params (std::vector ¶ms);
+ void maybe_strip_function_params (
+ std::vector> ¶ms);
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 ¶ms);
@@ -222,5 +224,8 @@ class CfgStrip : public AST::ASTVisitor
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
diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc
index 28ce402dde7e..cc198eecf5d9 100644
--- a/gcc/rust/expand/rust-derive-clone.cc
+++ b/gcc/rust/expand/rust-derive-clone.cc
@@ -17,6 +17,7 @@
// .
#include "rust-derive-clone.h"
+#include "rust-item.h"
namespace Rust {
namespace AST {
@@ -50,13 +51,17 @@ DeriveClone::clone_fn (std::unique_ptr &&clone_expr)
loc, loc));
auto big_self_type = builder.single_type_path ("Self");
+ std::unique_ptr self (new SelfParam (Lifetime::error (),
+ /* is_mut */ false, loc));
+
+ std::vector> params;
+ params.push_back (std::move (self));
+
return std::unique_ptr (
new Function ({"clone"}, builder.fn_qualifiers (), /* generics */ {},
- tl::optional (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));
}
/**
diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h
index 915c0545cbe5..d5c8b44442dd 100644
--- a/gcc/rust/expand/rust-derive.h
+++ b/gcc/rust/expand/rust-derive.h
@@ -220,6 +220,9 @@ class DeriveVisitor : public AST::ASTVisitor
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 ¶m) override final{};
+ virtual void visit (FunctionParam ¶m) override final{};
+ virtual void visit (VariadicParam ¶m) override final{};
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc
index 0dd6f592dba0..3f598b7f21ce 100644
--- a/gcc/rust/expand/rust-expand-visitor.cc
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -373,12 +373,11 @@ ExpandVisitor::expand_tuple_fields (std::vector &fields)
// FIXME: This can definitely be refactored with the method above
void
-ExpandVisitor::expand_function_params (std::vector ¶ms)
+ExpandVisitor::expand_function_params (
+ std::vector> ¶ms)
{
- for (auto ¶m : params)
- {
- maybe_expand_type (param.get_type ());
- }
+ for (auto &p : params)
+ visit (p);
}
void
@@ -431,16 +430,6 @@ ExpandVisitor::expand_closure_params (std::vector ¶ms)
}
}
-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 ¶m : 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 ¶m : 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 ¶m)
+{}
+
+void
+ExpandVisitor::visit (AST::FunctionParam ¶m)
+{
+ maybe_expand_type (param.get_type ());
+}
+
+void
+ExpandVisitor::visit (AST::SelfParam ¶m)
+{
+ /* TODO: maybe check for invariants being violated - e.g. both type and
+ * lifetime? */
+ if (param.has_type ())
+ maybe_expand_type (param.get_type ());
+}
+
template
void
ExpandVisitor::expand_inner_attribute (T &item, AST::SimplePath &path)
diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h
index d7612acd385f..74f2673655fd 100644
--- a/gcc/rust/expand/rust-expand-visitor.h
+++ b/gcc/rust/expand/rust-expand-visitor.h
@@ -67,7 +67,8 @@ class ExpandVisitor : public AST::ASTVisitor
* Expand all macro invocations in lieu of types within a list of function
* parameters
*/
- void expand_function_params (std::vector ¶ms);
+ void
+ expand_function_params (std::vector> ¶ms);
/**
* Expand all macro invocations in lieu of types within a list of generic
@@ -82,7 +83,6 @@ class ExpandVisitor : public AST::ASTVisitor
// FIXME: Add documentation
void expand_closure_params (std::vector ¶ms);
- 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 @@ class ExpandVisitor : public AST::ASTVisitor
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
void expand_inner_attribute (T &item, AST::SimplePath &Path);
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index 5f6d6febb7f7..051dd607a592 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -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 ¶m)
+{}
+
+void
+ASTLoweringBase::visit (AST::VariadicParam ¶m)
+{}
+
+void
+ASTLoweringBase::visit (AST::SelfParam ¶m)
+{}
+
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 ¶m)
{
+ rust_assert (param->is_self ());
+
+ auto self = static_cast (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 (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 (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 *
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index a9411c22f50f..510d1c96cfee 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -251,6 +251,9 @@ class ASTLoweringBase : public AST::ASTVisitor
virtual void visit (AST::SliceType &type);
virtual void visit (AST::InferredType &type);
virtual void visit (AST::BareFunctionType &type);
+ virtual void visit (AST::FunctionParam ¶m);
+ virtual void visit (AST::VariadicParam ¶m);
+ virtual void visit (AST::SelfParam ¶m);
protected:
ASTLoweringBase ()
@@ -274,7 +277,7 @@ class ASTLoweringBase : public AST::ASTVisitor
HIR::GenericArgsBinding lower_binding (AST::GenericArgsBinding &binding);
- HIR::SelfParam lower_self (AST::SelfParam &self);
+ HIR::SelfParam lower_self (std::unique_ptr &self);
HIR::Type *lower_type_no_bounds (AST::TypeNoBounds *type);
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h
index 2a0d9fc0e436..91602c9efbb1 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.h
+++ b/gcc/rust/hir/rust-ast-lower-implitem.h
@@ -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 @@ class ASTLowerImplItem : public ASTLoweringBase
: nullptr;
std::vector function_params;
- for (auto ¶m : function.get_function_params ())
+ for (auto &p : function.get_function_params ())
{
+ if (p->is_self () || p->is_variadic ())
+ continue;
+ auto param = static_cast (p.get ());
+
auto translated_pattern = std::unique_ptr (
- ASTLoweringPattern::translate (param.get_pattern ().get ()));
+ ASTLoweringPattern::translate (param->get_pattern ().get ()));
auto translated_type = std::unique_ptr (
- 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 @@ class ASTLowerTraitItem : public ASTLoweringBase
: nullptr;
std::vector function_params;
- for (auto ¶m : ref.get_function_params ())
+ for (auto &p : ref.get_function_params ())
{
+ if (p->is_variadic () || p->is_self ())
+ continue;
+
+ auto param = static_cast (p.get ());
+
auto translated_pattern = std::unique_ptr (
- ASTLoweringPattern::translate (param.get_pattern ().get ()));
+ ASTLoweringPattern::translate (param->get_pattern ().get ()));
auto translated_type = std::unique_ptr (
- 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 @@ class ASTLowerTraitItem : public ASTLoweringBase
HIR::SelfParam self_param = lower_self (ref.get_self_param ());
std::vector function_params;
- for (auto ¶m : ref.get_function_params ())
+ for (auto &p : ref.get_function_params ())
{
+ if (p->is_variadic () || p->is_self ())
+ continue;
+
+ auto param = static_cast (p.get ());
+
auto translated_pattern = std::unique_ptr (
- ASTLoweringPattern::translate (param.get_pattern ().get ()));
+ ASTLoweringPattern::translate (param->get_pattern ().get ()));
auto translated_type = std::unique_ptr (
- 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);
}
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc
index d94383bd271d..c024acf60f98 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -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 function_params;
- for (auto ¶m : function.get_function_params ())
+ for (auto &p : function.get_function_params ())
{
+ if (p->is_variadic () || p->is_self ())
+ continue;
+ auto param = static_cast (p.get ());
+
auto translated_pattern = std::unique_ptr (
- ASTLoweringPattern::translate (param.get_pattern ().get ()));
+ ASTLoweringPattern::translate (param->get_pattern ().get ()));
auto translated_type = std::unique_ptr (
- 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));
}
diff --git a/gcc/rust/metadata/rust-export-metadata.cc b/gcc/rust/metadata/rust-export-metadata.cc
index 5f6aa1bd0bf9..09aad76e4c12 100644
--- a/gcc/rust/metadata/rust-export-metadata.cc
+++ b/gcc/rust/metadata/rust-export-metadata.cc
@@ -22,9 +22,11 @@
#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 function_params;
- for (AST::FunctionParam ¶m : 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 (p.get ());
+ std::string name = param->get_pattern ()->as_string ();
std::unique_ptr 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
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 44b4d7412648..64807b64eb28 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -2879,12 +2879,21 @@ Parser::parse_function (AST::Visibility vis,
return nullptr;
}
+ std::unique_ptr 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 function_params;
+ std::vector> 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::parse_function (AST::Visibility vis,
return std::unique_ptr (
new AST::Function (std::move (function_name), std::move (qualifiers),
- std::move (generic_params),
- tl::optional (),
- 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::parse_type_param ()
* has end token handling. */
template
template
-std::vector
+std::vector>
Parser::parse_function_params (EndTokenPred is_end_token)
{
- std::vector params;
+ std::vector> 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::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 ();
+ return std::vector> ();
}
params.push_back (std::move (param));
@@ -3581,7 +3589,7 @@ Parser::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
-AST::FunctionParam
+std::unique_ptr
Parser::parse_function_param ()
{
// parse outer attributes if they exist
@@ -3593,7 +3601,8 @@ Parser::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 (std::move (outer_attrs), locus));
}
std::unique_ptr param_pattern = parse_pattern ();
@@ -3602,32 +3611,32 @@ Parser::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 (std::move (param_pattern), std::move (outer_attrs),
+ locus));
}
else
{
std::unique_ptr 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 (std::move (param_pattern), std::move (param_type),
+ std::move (outer_attrs), locus));
}
}
@@ -5051,13 +5060,14 @@ Parser::parse_trait_item ()
/* now for function vs method disambiguation - method has opening
* "self" param */
- AST::SelfParam self_param = parse_self_param ();
+ std::unique_ptr 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::parse_trait_item ()
}
// parse trait function params
- std::vector function_params
+ std::vector> function_params
= parse_function_params (
[] (TokenId id) { return id == RIGHT_PAREN; });
@@ -5076,6 +5086,10 @@ Parser::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 return_type = parse_function_return_type ();
@@ -5114,7 +5128,6 @@ Parser::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::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 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::parse_inherent_impl_function_or_method (
}
// parse trait function params
- std::vector function_params
+ std::vector> 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::parse_inherent_impl_function_or_method (
// do actual if instead of ternary for return value optimisation
if (is_method)
{
- return std::unique_ptr (new AST::Function (
- std::move (ident), std::move (qualifiers), std::move (generic_params),
- tl::optional (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 (
+ 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 (
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::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 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::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 function_params;
+ std::vector> function_params;
if (lexer.peek_token ()->get_id () != RIGHT_PAREN)
{
function_params
@@ -5838,6 +5857,10 @@ Parser::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::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 (new AST::Function (
- std::move (ident), std::move (qualifiers), std::move (generic_params),
- tl::optional (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 (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 (
+ 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::parse_qualified_path_in_type ()
// Parses a self param. Also handles self param not existing.
template
-AST::SelfParam
+std::unique_ptr
Parser::parse_self_param ()
{
bool has_reference = false;
@@ -7105,6 +7116,42 @@ Parser::parse_self_param ()
location_t locus = lexer.peek_token ()->get_locus ();
+ // TODO: Feels off, find a better way to clearly express this
+ std::vector> 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 % 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::parse_self_param ()
add_error (std::move (error));
// skip after somewhere?
- return AST::SelfParam::create_error ();
+ return nullptr;
}
}
}
@@ -7142,7 +7189,7 @@ Parser::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::parse_self_param ()
add_error (std::move (error));
// skip after somewhere?
- return AST::SelfParam::create_error ();
+ return nullptr;
}
}
@@ -7174,114 +7221,20 @@ Parser::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 (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
-std::unique_ptr
-Parser::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 (std::move (type), has_mut,
+ locus);
}
- Identifier method_name{ident_tok};
-
- // parse generic params - if exist
- std::vector> 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 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 return_type = parse_function_return_type ();
-
- // parse where clause - if exists
- AST::WhereClause where_clause = parse_where_clause ();
-
- // parse block expression
- std::unique_ptr 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 (new AST::Function (
- std::move (method_name), std::move (qualifiers), std::move (generic_params),
- tl::optional (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. */
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 3ff9b99caed0..9e924e0015ce 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -164,7 +164,7 @@ template class Parser
std::unique_ptr parse_inherent_impl_item ();
std::unique_ptr parse_trait_impl_item ();
AST::PathInExpression parse_path_in_expression ();
- std::vector > parse_lifetime_params ();
+ std::vector> parse_lifetime_params ();
AST::Visibility parse_visibility ();
std::unique_ptr parse_identifier_pattern ();
std::unique_ptr parse_identifier_or_keyword_token ();
@@ -246,17 +246,17 @@ template class Parser
std::unique_ptr parse_function (AST::Visibility vis,
AST::AttrVec outer_attrs);
AST::FunctionQualifiers parse_function_qualifiers ();
- std::vector >
+ std::vector>
parse_generic_params_in_angles ();
template
- std::vector >
+ std::vector>
parse_generic_params (EndTokenPred is_end_token);
template
std::unique_ptr
parse_generic_param (EndTokenPred is_end_token);
template
- std::vector >
+ std::vector>
parse_lifetime_params (EndTokenPred is_end_token);
std::vector parse_lifetime_params_objs ();
template
@@ -268,15 +268,15 @@ template class Parser
std::string error_msg = "failed to parse generic param in generic params")
-> std::vector;
AST::LifetimeParam parse_lifetime_param ();
- std::vector > parse_type_params ();
+ std::vector> parse_type_params ();
template
- std::vector >
+ std::vector>
parse_type_params (EndTokenPred is_end_token);
std::unique_ptr parse_type_param ();
template
- std::vector
+ std::vector>
parse_function_params (EndTokenPred is_end_token);
- AST::FunctionParam parse_function_param ();
+ std::unique_ptr parse_function_param ();
std::unique_ptr parse_function_return_type ();
AST::WhereClause parse_where_clause ();
std::unique_ptr parse_where_clause_item ();
@@ -286,9 +286,9 @@ template class Parser
parse_type_bound_where_clause_item ();
std::vector parse_for_lifetimes ();
template
- std::vector >
+ std::vector>
parse_type_param_bounds (EndTokenPred is_end_token);
- std::vector > parse_type_param_bounds ();
+ std::vector> parse_type_param_bounds ();
std::unique_ptr parse_type_param_bound ();
std::unique_ptr parse_trait_bound ();
std::vector parse_lifetime_bounds ();
@@ -317,9 +317,9 @@ template class Parser
AST::TupleField parse_tuple_field ();
std::unique_ptr