aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorSimplyTheOther <simplytheother@gmail.com>2020-11-29 22:47:31 +0800
committerSimplyTheOther <simplytheother@gmail.com>2020-12-08 21:10:34 +0800
commitdb39766514144dbbad34d9db3977c3a72d1216c3 (patch)
treec7c470e4bf94ccb0105f8ad80ff85c7582ee9358 /gcc
parent9b252167a77316750f34c455222e5f30724e51e4 (diff)
downloadgcc-db39766514144dbbad34d9db3977c3a72d1216c3.zip
gcc-db39766514144dbbad34d9db3977c3a72d1216c3.tar.gz
gcc-db39766514144dbbad34d9db3977c3a72d1216c3.tar.bz2
Added new pattern stripping
Fixed get_locus_slow call in StructPatternField compile error Added and improved cfg stripping Fixed compilation errors
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/analysis/rust-type-resolution.cc22
-rw-r--r--gcc/rust/ast/rust-ast-full-test.cc86
-rw-r--r--gcc/rust/ast/rust-ast.h16
-rw-r--r--gcc/rust/ast/rust-expr.h50
-rw-r--r--gcc/rust/ast/rust-item.h272
-rw-r--r--gcc/rust/ast/rust-path.h86
-rw-r--r--gcc/rust/ast/rust-pattern.h194
-rw-r--r--gcc/rust/ast/rust-stmt.h7
-rw-r--r--gcc/rust/ast/rust-type.h21
-rw-r--r--gcc/rust/backend/rust-compile.cc24
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc786
-rw-r--r--gcc/rust/parse/rust-parse-impl.h82
-rw-r--r--gcc/rust/parse/rust-parse.h1
13 files changed, 1377 insertions, 270 deletions
diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc
index 5aa2905..439543e 100644
--- a/gcc/rust/analysis/rust-type-resolution.cc
+++ b/gcc/rust/analysis/rust-type-resolution.cc
@@ -594,7 +594,7 @@ TypeResolution::visit (AST::CallExpr &expr)
AST::Type *argument = typeBuffer.back ();
typeBuffer.pop_back ();
- if (!typesAreCompatible (it->type.get (), argument,
+ if (!typesAreCompatible (it->get_type ().get (), argument,
expr.get_params ()[offs]->get_locus_slow ()))
return;
offs--;
@@ -768,11 +768,11 @@ TypeResolution::visit (AST::Function &function)
for (auto &param : function.get_function_params ())
{
- if (!isTypeInScope (param.type.get (), param.get_locus ()))
+ if (!isTypeInScope (param.get_type ().get (), param.get_locus ()))
return;
auto before = letPatternBuffer.size ();
- param.param_name->accept_vis (*this);
+ param.get_pattern ()->accept_vis (*this);
if (letPatternBuffer.size () <= before)
{
rust_error_at (param.get_locus (), "failed to analyse parameter name");
@@ -781,11 +781,11 @@ TypeResolution::visit (AST::Function &function)
auto paramName = letPatternBuffer.back ();
letPatternBuffer.pop_back ();
- scope.InsertType (paramName.variable_ident, param.type.get ());
+ scope.InsertType (paramName.get_ident (), param.get_type ().get ());
}
// ensure the return type is resolved
- if (function.has_function_return_type ())
+ if (function.has_return_type ())
{
if (!isTypeInScope (function.get_return_type ().get (), function.get_locus ()))
return;
@@ -1015,12 +1015,12 @@ TypeResolution::visit (AST::LetStmt &stmt)
if (stmt.has_init_expr ())
{
auto before = typeBuffer.size ();
- stmt.init_expr->accept_vis (*this);
+ stmt.get_init_expr ()->accept_vis (*this);
if (typeBuffer.size () <= before)
{
rust_error_at (
- stmt.init_expr->get_locus_slow (),
+ stmt.get_init_expr ()->get_locus_slow (),
"unable to determine type for declaration from init expr");
return;
}
@@ -1030,7 +1030,7 @@ TypeResolution::visit (AST::LetStmt &stmt)
if (inferedType == NULL)
{
- rust_error_at (stmt.init_expr->get_locus_slow (),
+ rust_error_at (stmt.get_init_expr ()->get_locus_slow (),
"void type found for statement initialisation");
return;
}
@@ -1039,7 +1039,7 @@ TypeResolution::visit (AST::LetStmt &stmt)
if (stmt.has_type () && stmt.has_init_expr ())
{
if (!typesAreCompatible (stmt.type.get (), inferedType,
- stmt.init_expr->get_locus_slow ()))
+ stmt.get_init_expr ()->get_locus_slow ()))
{
return;
}
@@ -1059,9 +1059,9 @@ TypeResolution::visit (AST::LetStmt &stmt)
}
// get all the names part of this declaration and add the types to the scope
- stmt.variables_pattern->accept_vis (*this);
+ stmt.get_pattern ()->accept_vis (*this);
for (auto &pattern : letPatternBuffer)
- scope.InsertType (pattern.variable_ident, inferedType);
+ scope.InsertType (pattern.get_ident (), inferedType);
letPatternBuffer.clear ();
}
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc
index 5601a1a..26a3356 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -1103,7 +1103,7 @@ Function::as_string () const
if ("" != qstr)
str += qstr + " ";
- if (has_function_return_type ())
+ if (has_return_type ())
{
// DEBUG: null pointer check
if (return_type == nullptr)
@@ -1168,9 +1168,7 @@ Function::as_string () const
}
if (has_where_clause ())
- {
str += " where " + where_clause.as_string ();
- }
str += "\n";
@@ -1201,9 +1199,7 @@ WhereClause::as_string () const
else
{
for (const auto &item : where_clause_items)
- {
str += "\n " + item->as_string ();
- }
}
return str;
@@ -1228,9 +1224,7 @@ BlockExpr::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
str += "\n" + indent_spaces (stay) + attr.as_string ();
- }
}
// statements
@@ -1260,13 +1254,9 @@ BlockExpr::as_string () const
// final expression
str += "\n" + indent_spaces (stay) + "final expression: ";
if (expr == nullptr)
- {
str += "none";
- }
else
- {
str += "\n" + expr->as_string ();
- }
str += "\n" + indent_spaces (out) + "}";
return str;
@@ -1278,9 +1268,7 @@ TraitImpl::as_string () const
std::string str = VisItem::as_string ();
if (has_unsafe)
- {
str += "unsafe ";
- }
str += "impl ";
@@ -1293,20 +1281,14 @@ TraitImpl::as_string () const
else
{
for (const auto &param : generic_params)
- {
str += "\n " + param->as_string ();
- }
}
str += "\n Has exclam: ";
if (has_exclam)
- {
str += "true";
- }
else
- {
str += "false";
- }
str += "\n TypePath (to trait): " + trait_path.as_string ();
@@ -1314,13 +1296,9 @@ TraitImpl::as_string () const
str += "\n Where clause: ";
if (!has_where_clause ())
- {
str += "none";
- }
else
- {
str += where_clause.as_string ();
- }
// inner attributes
str += "\n inner attributes: ";
@@ -1333,9 +1311,7 @@ TraitImpl::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
str += "\n " + attr.as_string ();
- }
}
str += "\n trait impl items: ";
@@ -1346,9 +1322,7 @@ TraitImpl::as_string () const
else
{
for (const auto &item : impl_items)
- {
str += "\n " + item->as_string ();
- }
}
return str;
@@ -1464,9 +1438,7 @@ ExternBlock::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
str += "\n " + attr.as_string ();
- }
}
str += "\n external items: ";
@@ -1477,9 +1449,7 @@ ExternBlock::as_string () const
else
{
for (const auto &item : extern_items)
- {
str += "\n " + item->as_string ();
- }
}
return str;
@@ -1558,9 +1528,7 @@ PathInExpression::as_string () const
std::string str;
if (has_opening_scope_resolution)
- {
str = "::";
- }
return str + PathPattern::as_string ();
}
@@ -1591,9 +1559,7 @@ ClosureParam::as_string () const
std::string str (pattern->as_string ());
if (has_type_given ())
- {
str += " : " + type->as_string ();
- }
return str;
}
@@ -1603,13 +1569,9 @@ ClosureExpr::as_string () const
{
std::string str ("ClosureExpr:\n Has move: ");
if (has_move)
- {
str += "true";
- }
else
- {
str += "false";
- }
str += "\n Params: ";
if (params.empty ())
@@ -1619,9 +1581,7 @@ ClosureExpr::as_string () const
else
{
for (const auto &param : params)
- {
str += "\n " + param.as_string ();
- }
}
return str;
@@ -1645,9 +1605,7 @@ PathPattern::as_string () const
std::string str;
for (const auto &segment : segments)
- {
str += segment.as_string () + "::";
- }
// basically a hack - remove last two characters of string (remove final ::)
str.erase (str.length () - 2);
@@ -1662,9 +1620,7 @@ QualifiedPathType::as_string () const
str += type_to_invoke_on->as_string ();
if (has_as_clause ())
- {
str += " as " + trait_path.as_string ();
- }
return str + ">";
}
@@ -1681,14 +1637,10 @@ BorrowExpr::as_string () const
std::string str ("&");
if (double_borrow)
- {
str += "&";
- }
if (is_mut)
- {
str += "mut ";
- }
str += main_or_left_expr->as_string ();
@@ -1722,9 +1674,7 @@ GroupedExpr::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
str += "\n " + attr.as_string ();
- }
}
str += "\n Expr in parens: " + expr_in_parens->as_string ();
@@ -1744,9 +1694,7 @@ ContinueExpr::as_string () const
std::string str ("continue ");
if (has_label ())
- {
str += label.as_string ();
- }
return str;
}
@@ -1881,9 +1829,7 @@ MethodCallExpr::as_string () const
for (const auto &param : params)
{
if (param == nullptr)
- {
return "ERROR_MARK_STRING - method call expr param is null";
- }
str += "\n " + param->as_string ();
}
@@ -2022,9 +1968,7 @@ IfLetExpr::as_string () const
else
{
for (const auto &pattern : match_arm_patterns)
- {
str += "\n " + pattern->as_string ();
- }
}
str += "\n Scrutinee expr: " + value->as_string ();
@@ -2213,9 +2157,7 @@ CallExpr::as_string () const
for (const auto &param : params)
{
if (param == nullptr)
- {
return "ERROR_MARK_STRING - call expr param is null";
- }
str += "\n " + param->as_string ();
}
@@ -2231,13 +2173,9 @@ WhileLoopExpr::as_string () const
str += "\n Label: ";
if (!has_loop_label ())
- {
str += "none";
- }
else
- {
str += loop_label.as_string ();
- }
str += "\n Conditional expr: " + condition->as_string ();
@@ -2282,13 +2220,9 @@ LoopExpr::as_string () const
str += "\n Label: ";
if (!has_loop_label ())
- {
str += "none";
- }
else
- {
str += loop_label.as_string ();
- }
str += "\n Loop block: " + loop_block->as_string ();
@@ -2311,20 +2245,14 @@ ArrayExpr::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
str += "\n " + attr.as_string ();
- }
}
str += "\n Array elems: ";
if (!has_array_elems ())
- {
str += "none";
- }
else
- {
str += internal_elements->as_string ();
- }
return str;
}
@@ -2341,14 +2269,10 @@ BreakExpr::as_string () const
std::string str ("break ");
if (has_label ())
- {
str += label.as_string () + " ";
- }
if (has_break_expr ())
- {
str += break_expr->as_string ();
- }
return str;
}
@@ -2373,9 +2297,7 @@ MatchArm::as_string () const
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
- {
str += "\n " + attr.as_string ();
- }
}
str += "\nPatterns: ";
@@ -2386,20 +2308,14 @@ MatchArm::as_string () const
else
{
for (const auto &pattern : match_arm_patterns)
- {
str += "\n " + pattern->as_string ();
- }
}
str += "\nGuard expr: ";
if (!has_match_arm_guard ())
- {
str += "none";
- }
else
- {
str += guard_expr->as_string ();
- }
return str;
}
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index c186f22..b5e56ba 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -968,6 +968,14 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
+ // as only one kind of pattern can be stripped, have default of nothing
+ virtual void mark_for_strip () {}
+ virtual bool is_marked_for_strip () const { return false; }
+
+ /* HACK: slow way of getting location from base expression through virtual
+ * methods. */
+ virtual Location get_locus_slow () const = 0;
+
protected:
// Clone pattern implementation as pure virtual method
virtual Pattern *clone_pattern_impl () const = 0;
@@ -1002,6 +1010,12 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
+ // as only two kinds of types can be stripped, have default of nothing
+ virtual void mark_for_strip () {}
+ virtual bool is_marked_for_strip () const { return false; }
+
+ virtual Location get_locus_slow () const = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual Type *clone_type_impl () const = 0;
@@ -1081,7 +1095,7 @@ public:
{}
// Creates an "error" lifetime.
- static Lifetime error () { return Lifetime (NAMED, std::string ("")); }
+ static Lifetime error () { return Lifetime (NAMED, ""); }
// Returns true if the lifetime is in an error state.
bool is_error () const
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index df77611..34dfc25 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -669,6 +669,12 @@ public:
return main_or_left_expr;
}
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<TypeNoBounds> &get_type_to_cast_to () {
+ rust_assert (type_to_convert_to != nullptr);
+ return type_to_convert_to;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1375,6 +1381,7 @@ protected:
public:
const PathInExpression &get_struct_name () const { return struct_name; }
+ PathInExpression &get_struct_name () { return struct_name; }
std::string as_string () const override;
@@ -1828,8 +1835,8 @@ protected:
{}
public:
- // TODO: maybe remove and have string version gotten here directly
- PathInExpression get_enum_variant_path () const { return enum_variant_path; }
+ const PathInExpression& get_enum_variant_path () const { return enum_variant_path; }
+ PathInExpression& get_enum_variant_path () { return enum_variant_path; }
// Invalid if path is in error state, so base stripping on that.
void mark_for_strip () override { enum_variant_path = PathInExpression::create_error (); }
@@ -2305,7 +2312,8 @@ public:
return receiver;
}
- PathExprSegment get_method_name () const { return method_name; }
+ const PathExprSegment &get_method_name () const { return method_name; }
+ PathExprSegment &get_method_name () { return method_name; }
protected:
/* Use covariance to implement clone function as returning this object rather
@@ -2462,6 +2470,18 @@ public:
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Pattern> &get_pattern () {
+ rust_assert (pattern != nullptr);
+ return pattern;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (has_type_given ());
+ return type;
+ }
};
// Base closure definition expression AST node - abstract
@@ -2756,6 +2776,12 @@ public:
return expr;
}
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type () {
+ rust_assert (return_type != nullptr);
+ return return_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3667,6 +3693,10 @@ public:
return scrutinee;
}
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<std::unique_ptr<Pattern> > &get_patterns () const { return match_arm_patterns; }
+ std::vector<std::unique_ptr<Pattern> > &get_patterns () { return match_arm_patterns; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3728,6 +3758,12 @@ public:
return iterator_expr;
}
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Pattern> &get_pattern () {
+ rust_assert (pattern != nullptr);
+ return pattern;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3959,7 +3995,6 @@ class IfLetExpr : public ExprWithBlock
std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
std::unique_ptr<Expr> value;
std::unique_ptr<BlockExpr> if_block;
-
Location locus;
public:
@@ -4043,6 +4078,10 @@ public:
return if_block;
}
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<std::unique_ptr<Pattern> > &get_patterns () const { return match_arm_patterns; }
+ std::vector<std::unique_ptr<Pattern> > &get_patterns () { return match_arm_patterns; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base (or rather this or any derived object) */
@@ -4366,6 +4405,9 @@ public:
// TODO: this mutable getter seems really dodgy. Think up better way.
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+
+ const std::vector<std::unique_ptr<Pattern> > &get_patterns () const { return match_arm_patterns; }
+ std::vector<std::unique_ptr<Pattern> > &get_patterns () { return match_arm_patterns; }
};
/*
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 5891383..c47a6f5 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -123,6 +123,16 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
+ // TODO: mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () { return type_param_bounds; }
+ const std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () const { return type_param_bounds; }
+
protected:
// Clone function implementation as (not pure) virtual method
TypeParam *clone_generic_param_impl () const override
@@ -245,6 +255,16 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (bound_type != nullptr);
+ return bound_type;
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () { return type_param_bounds; }
+ const std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () const { return type_param_bounds; }
+
protected:
// Clone function implementation as (not pure) virtual method
TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override
@@ -299,6 +319,10 @@ public:
bool is_empty () const { return where_clause_items.empty (); }
std::string as_string () const;
+
+ // TODO: this mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<WhereClauseItem> > &get_items () { return where_clause_items; }
+ const std::vector<std::unique_ptr<WhereClauseItem> > &get_items () const { return where_clause_items; }
};
// A self parameter in a method
@@ -322,6 +346,8 @@ private:
{}
// this is ok as no outside classes can ever call this
+ // TODO: self param can have outer attributes
+
public:
// Returns whether the self-param has a type field.
bool has_type () const { return type != nullptr; }
@@ -332,21 +358,15 @@ public:
// Returns whether the self-param is in an error state.
bool is_error () const
{
- return has_type () && has_lifetime ();
+ return (has_type () && has_lifetime ()) || (has_lifetime () && !has_ref);
// not having either is not an error
}
// Creates an error state self-param.
static SelfParam create_error ()
{
- /* HACK: creates a dummy type. Since it's a unique pointer, it should
- * clean it up, but it still allocates memory, which is not ideal. */
- return SelfParam (Lifetime (Lifetime::STATIC), false, false,
- new QualifiedPathInType (
- QualifiedPathInType::create_error ()));
- /* FIXME: is there a reason why I didn't just create a null pointer? Is it
- * due to error being having both a type and a lifetime? If it is, wouldn't
- * something like "not has_ref and has lifetime" for error be better? */
+ // cannot have no ref but have a lifetime at the same time
+ return SelfParam (Lifetime (Lifetime::STATIC), false, false, nullptr);
}
// Type-based self parameter (not ref, no lifetime)
@@ -373,13 +393,16 @@ public:
// Overload assignment operator to use clone
SelfParam &operator= (SelfParam const &other)
{
- if (other.type != nullptr)
- type = other.type->clone_type ();
is_mut = other.is_mut;
has_ref = other.has_ref;
lifetime = other.lifetime;
locus = other.locus;
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+
return *this;
}
@@ -390,6 +413,12 @@ public:
std::string as_string () const;
Location get_locus () const { return locus; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (has_type ());
+ return type;
+ }
};
// Qualifiers for function, i.e. const, unsafe, extern etc.
@@ -437,11 +466,10 @@ struct FunctionParam
private:
std::vector<Attribute> outer_attrs;
Location locus;
-
-public:
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 locus)
: outer_attrs (std::move (outer_attrs)), locus (locus),
@@ -496,6 +524,18 @@ public:
// TODO: seems kinda dodgy. Think of better way.
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Pattern> &get_pattern () {
+ rust_assert (param_name != nullptr);
+ return param_name;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (type != nullptr);
+ return type;
+ }
};
// Visibility of item - if the item has it, then it is some form of public
@@ -740,12 +780,30 @@ public:
std::vector<FunctionParam> &get_function_params () { return function_params; }
const std::vector<FunctionParam> &get_function_params () const { return function_params; }
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params () { return generic_params; }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const { return generic_params; }
+
// TODO: is this better? Or is a "vis_block" better?
std::unique_ptr<BlockExpr> &get_definition () {
rust_assert (function_body != nullptr);
return function_body;
}
+ SelfParam &get_self_param () { return self_param; }
+ const SelfParam &get_self_param () const { return self_param; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type () {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause () {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1299,7 +1357,7 @@ public:
bool has_function_params () const { return !function_params.empty (); }
// Returns whether function has return type - if not, it is void.
- bool has_function_return_type () const { return return_type != nullptr; }
+ bool has_return_type () const { return return_type != nullptr; }
// Returns whether function has a where clause.
bool has_where_clause () const { return !where_clause.is_empty (); }
@@ -1390,6 +1448,9 @@ public:
std::vector<FunctionParam> &get_function_params () { return function_params; }
const std::vector<FunctionParam> &get_function_params () const { return function_params; }
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params () { return generic_params; }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const { return generic_params; }
+
// TODO: is this better? Or is a "vis_block" better?
std::unique_ptr<BlockExpr> &get_definition () {
rust_assert (function_body != nullptr);
@@ -1408,7 +1469,7 @@ public:
// TODO: is this better? Or is a "vis_block" better?
std::unique_ptr<Type> &get_return_type () {
- rust_assert (return_type != nullptr);
+ rust_assert (has_return_type ());
return return_type;
}
@@ -1518,6 +1579,21 @@ public:
void mark_for_strip () override { existing_type = nullptr; }
bool is_marked_for_strip () const override { return existing_type == nullptr; }
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params () { return generic_params; }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const { return generic_params; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause () {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type_aliased () {
+ rust_assert (existing_type != nullptr);
+ return existing_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1563,6 +1639,15 @@ public:
Identifier get_struct_name () const { return struct_name; }
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params () { return generic_params; }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const { return generic_params; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause () {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
Struct (Identifier struct_name,
std::vector<std::unique_ptr<GenericParam>> generic_params,
@@ -1819,6 +1904,12 @@ public:
// TODO: this mutable getter seems really dodgy. Think up better way.
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_field_type () {
+ rust_assert (field_type != nullptr);
+ return field_type;
+ }
};
// Rust tuple declared using struct keyword AST node
@@ -2112,6 +2203,15 @@ public:
std::vector<std::unique_ptr<EnumItem>> &get_variants () { return items; }
const std::vector<std::unique_ptr<EnumItem>> &get_variants () const { return items; }
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params () { return generic_params; }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const { return generic_params; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause () {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2197,6 +2297,15 @@ public:
std::vector<StructField> &get_variants () { return variants; }
const std::vector<StructField> &get_variants () const { return variants; }
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params () { return generic_params; }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const { return generic_params; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause () {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2282,6 +2391,12 @@ public:
return const_expr;
}
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2377,6 +2492,12 @@ public:
return expr;
}
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2488,6 +2609,21 @@ public:
// 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 { return function_params; }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params () { return generic_params; }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const { return generic_params; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type () {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause () {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
};
// Actual trait item function declaration within traits
@@ -2552,15 +2688,18 @@ public:
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
- std::vector<FunctionParam> &get_function_params () { return decl.get_function_params (); }
- const std::vector<FunctionParam> &get_function_params () const { return decl.get_function_params (); }
-
// TODO: is this better? Or is a "vis_block" better?
std::unique_ptr<BlockExpr> &get_definition () {
- rust_assert (has_definition());
+ rust_assert (has_definition ());
return block_expr;
}
+ // TODO: is this better? Or is a "vis_block" better?
+ TraitFunctionDecl &get_trait_function_decl () {
+ // TODO: maybe only allow access if not marked for strip?
+ return decl;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemFunc *clone_trait_item_impl () const override
@@ -2675,6 +2814,24 @@ public:
// 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 { return function_params; }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params () { return generic_params; }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const { return generic_params; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type () {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause () {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ SelfParam &get_self_param () { return self_param; }
+ const SelfParam &get_self_param () const { return self_param; }
};
// Actual trait item method declaration within traits
@@ -2740,8 +2897,11 @@ public:
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
- std::vector<FunctionParam> &get_function_params () { return decl.get_function_params (); }
- const std::vector<FunctionParam> &get_function_params () const { return decl.get_function_params (); }
+ // TODO: is this better? Or is a "vis_block" better?
+ TraitMethodDecl &get_trait_method_decl () {
+ // TODO: maybe only allow access if not marked for strip?
+ return decl;
+ }
// TODO: is this better? Or is a "vis_block" better?
std::unique_ptr<BlockExpr> &get_definition () {
@@ -2840,6 +3000,12 @@ public:
return expr;
}
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemConst *clone_trait_item_impl () const override
@@ -2916,6 +3082,10 @@ public:
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+ // TODO: mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () { return type_param_bounds; }
+ const std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () const { return type_param_bounds; }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemType *clone_trait_item_impl () const override
@@ -3044,6 +3214,18 @@ public:
const std::vector<std::unique_ptr<TraitItem>>& get_trait_items () const { return trait_items; }
std::vector<std::unique_ptr<TraitItem>>& get_trait_items () { return trait_items; }
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params () { return generic_params; }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const { return generic_params; }
+
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () { return type_param_bounds; }
+ const std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () const { return type_param_bounds; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause () {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -3091,6 +3273,21 @@ public:
const std::vector<Attribute>& get_inner_attrs () const { return inner_attrs; }
std::vector<Attribute>& get_inner_attrs () { return inner_attrs; }
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params () { return generic_params; }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const { return generic_params; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause () {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (trait_type != nullptr);
+ return trait_type;
+ }
+
protected:
// Mega-constructor
Impl (std::vector<std::unique_ptr<GenericParam>> generic_params,
@@ -3274,6 +3471,12 @@ public:
const std::vector<std::unique_ptr<TraitImplItem>>& get_impl_items () const { return impl_items; }
std::vector<std::unique_ptr<TraitImplItem>>& get_impl_items () { return impl_items; }
+ // TODO: is this better? Or is a "vis_block" better?
+ TypePath &get_trait_path () {
+ // TODO: assert that trait path is not empty?
+ return trait_path;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -3435,6 +3638,12 @@ public:
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (item_type != nullptr);
+ return item_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -3522,6 +3731,12 @@ public:
// TODO: this mutable getter seems really dodgy. Think up better way.
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (param_type != nullptr);
+ return param_type;
+ }
};
// A function item used in an extern block
@@ -3652,6 +3867,21 @@ public:
std::vector<NamedFunctionParam> &get_function_params () { return function_params; }
const std::vector<NamedFunctionParam> &get_function_params () const { return function_params; }
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params () { return generic_params; }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const { return generic_params; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause () {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type () {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index c59e6bd..b5d7869 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -45,7 +45,6 @@ struct GenericArgsBinding
private:
Identifier identifier;
std::unique_ptr<Type> type;
-
Location locus;
public:
@@ -100,6 +99,12 @@ public:
GenericArgsBinding &operator= (GenericArgsBinding &&other) = default;
std::string as_string () const;
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (type != nullptr);
+ return type;
+ }
};
// Generic arguments allowed in each path expression segment - inline?
@@ -166,6 +171,16 @@ public:
}
std::string as_string () const;
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::vector<std::unique_ptr<Type>> &get_type_args () {
+ return type_args;
+ }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::vector<GenericArgsBinding> &get_binding_args () {
+ return binding_args;
+ }
};
/* A segment of a path in expression, including an identifier aspect and maybe
@@ -221,6 +236,12 @@ public:
std::string as_string () const;
Location get_locus () const { return locus; }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ GenericArgs &get_generic_args () {
+ rust_assert (has_generic_args ());
+ return generic_args;
+ }
};
// AST node representing a pattern that involves a "path" - abstract base class
@@ -249,6 +270,10 @@ public:
bool is_single_segment () const { return segments.size () == 1; }
std::string as_string () const override;
+
+ // TODO: this seems kinda dodgy
+ std::vector<PathExprSegment> &get_segments () { return segments; }
+ const std::vector<PathExprSegment> &get_segments () const { return segments; }
};
/* AST node representing a path-in-expression pattern (path that allows generic
@@ -416,6 +441,12 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_pattern" better?
+ GenericArgs &get_generic_args () {
+ rust_assert (has_generic_args ());
+ return generic_args;
+ }
+
protected:
// Use covariance to override base class method
TypePathSegmentGeneric *clone_type_path_segment_impl () const override
@@ -504,6 +535,16 @@ public:
TypePathFunction &operator= (TypePathFunction &&other) = default;
std::string as_string () const;
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<std::unique_ptr<Type>> &get_params () const { return inputs; }
+ std::vector<std::unique_ptr<Type>> &get_params () { return inputs; }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Type> &get_return_type () {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
};
// Segment used in type path with a function argument
@@ -536,6 +577,12 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_pattern" better?
+ TypePathFunction &get_type_path_function () {
+ rust_assert (!function_path.is_error ());
+ return function_path;
+ }
+
protected:
// Use covariance to override base class method
TypePathSegmentFunction *clone_type_path_segment_impl () const override
@@ -547,7 +594,6 @@ protected:
// Path used inside types
class TypePath : public TypeNoBounds
{
-public:
bool has_opening_scope_resolution;
std::vector<std::unique_ptr<TypePathSegment>> segments;
Location locus;
@@ -622,8 +668,13 @@ public:
TraitBound *to_trait_bound (bool in_parens) const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: this seems kinda dodgy
+ std::vector<std::unique_ptr<TypePathSegment>> &get_segments () { return segments; }
+ const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const { return segments; }
};
struct QualifiedPathType
@@ -691,6 +742,18 @@ public:
std::string as_string () const;
Location get_locus () const { return locus; }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Type> &get_type () {
+ rust_assert (type_to_invoke_on != nullptr);
+ return type_to_invoke_on;
+ }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ TypePath &get_as_type_path () {
+ rust_assert (has_as_clause ());
+ return trait_path;
+ }
};
/* AST node representing a qualified path-in-expression pattern (path that
@@ -735,6 +798,12 @@ public:
void mark_for_strip () override { path_type = QualifiedPathType::create_error (); }
bool is_marked_for_strip () const override { return is_error (); }
+ // TODO: is this better? Or is a "vis_pattern" better?
+ QualifiedPathType &get_qualified_path_type () {
+ rust_assert (!path_type.is_error ());
+ return path_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -819,6 +888,19 @@ public:
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ QualifiedPathType &get_qualified_path_type () {
+ rust_assert (!path_type.is_error ());
+ return path_type;
+ }
+
+ // TODO: this seems kinda dodgy
+ std::vector<std::unique_ptr<TypePathSegment>> &get_segments () { return segments; }
+ const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const { return segments; }
+
+ Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
};
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index 63abe7a..5dd0429 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -34,6 +34,7 @@ public:
{}
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
@@ -49,7 +50,6 @@ protected:
// Identifier pattern AST node (bind value matched to a variable)
class IdentifierPattern : public Pattern
{
-public:
Identifier variable_ident;
bool is_ref;
bool is_mut;
@@ -59,6 +59,7 @@ public:
Location locus;
+public:
std::string as_string () const;
// Returns whether the IdentifierPattern has a pattern to bind.
@@ -104,9 +105,18 @@ public:
IdentifierPattern &operator= (IdentifierPattern &&other) = default;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Pattern> &get_pattern_to_bind () {
+ rust_assert (has_pattern_to_bind ());
+ return to_bind;
+ }
+
+ Identifier get_ident() const { return variable_ident; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -127,6 +137,7 @@ public:
WildcardPattern (Location locus) : locus (locus) {}
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
@@ -295,6 +306,7 @@ public:
RangePattern &operator= (RangePattern &&other) = default;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
@@ -345,8 +357,17 @@ public:
ReferencePattern (ReferencePattern &&other) = default;
ReferencePattern &operator= (ReferencePattern &&other) = default;
+ Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
+
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Pattern> &get_referenced_pattern () {
+ rust_assert (pattern != nullptr);
+ return pattern;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -356,6 +377,7 @@ protected:
}
};
+#if 0
// aka StructPatternEtCetera; potential element in struct pattern
struct StructPatternEtc
{
@@ -375,6 +397,7 @@ public:
return StructPatternEtc (std::vector<Attribute> ());
}
};
+#endif
// Base class for a single field in a struct pattern - abstract
class StructPatternField
@@ -398,6 +421,13 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
+ virtual void mark_for_strip () = 0;
+ virtual bool is_marked_for_strip () const = 0;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
protected:
StructPatternField (std::vector<Attribute> outer_attribs, Location locus)
: outer_attrs (std::move (outer_attribs)), locus (locus)
@@ -424,19 +454,27 @@ public:
// Copy constructor requires clone
StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other)
- : StructPatternField (other), index (other.index),
- tuple_pattern (other.tuple_pattern->clone_pattern ())
- {}
+ : StructPatternField (other), index (other.index)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.tuple_pattern != nullptr)
+ tuple_pattern = other.tuple_pattern->clone_pattern ();
+ }
// Overload assignment operator to perform clone
StructPatternFieldTuplePat &
operator= (StructPatternFieldTuplePat const &other)
{
StructPatternField::operator= (other);
- tuple_pattern = other.tuple_pattern->clone_pattern ();
index = other.index;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.tuple_pattern != nullptr)
+ tuple_pattern = other.tuple_pattern->clone_pattern ();
+ else
+ tuple_pattern = nullptr;
+
return *this;
}
@@ -449,6 +487,16 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // based on idea of tuple pattern no longer existing
+ void mark_for_strip () override { tuple_pattern = nullptr; }
+ bool is_marked_for_strip () const override { return tuple_pattern == nullptr; }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Pattern> &get_index_pattern () {
+ rust_assert (tuple_pattern != nullptr);
+ return tuple_pattern;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -475,9 +523,12 @@ public:
// Copy constructor requires clone
StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other)
- : StructPatternField (other), ident (other.ident),
- ident_pattern (other.ident_pattern->clone_pattern ())
- {}
+ : StructPatternField (other), ident (other.ident)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.ident_pattern != nullptr)
+ ident_pattern = other.ident_pattern->clone_pattern ();
+ }
// Overload assignment operator to clone
StructPatternFieldIdentPat &
@@ -485,9 +536,14 @@ public:
{
StructPatternField::operator= (other);
ident = other.ident;
- ident_pattern = other.ident_pattern->clone_pattern ();
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.ident_pattern != nullptr)
+ ident_pattern = other.ident_pattern->clone_pattern ();
+ else
+ ident_pattern = nullptr;
+
return *this;
}
@@ -500,6 +556,16 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // based on idea of identifier pattern no longer existing
+ void mark_for_strip () override { ident_pattern = nullptr; }
+ bool is_marked_for_strip () const override { return ident_pattern == nullptr; }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Pattern> &get_ident_pattern () {
+ rust_assert (ident_pattern != nullptr);
+ return ident_pattern;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -527,6 +593,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // based on idea of identifier no longer existing
+ void mark_for_strip () override { ident = {}; }
+ bool is_marked_for_strip () const override { return ident.empty (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -544,7 +614,8 @@ private:
std::vector<std::unique_ptr<StructPatternField>> fields;
bool has_struct_pattern_etc;
- StructPatternEtc etc;
+ std::vector<Attribute> struct_pattern_etc_attrs;
+ //StructPatternEtc etc;
// must have at least one of the two and maybe both
@@ -561,24 +632,26 @@ public:
return !has_struct_pattern_fields () && !has_struct_pattern_etc;
}
+ bool has_etc () const { return has_struct_pattern_etc; }
+
// Constructor for StructPatternElements with both (potentially)
StructPatternElements (
std::vector<std::unique_ptr<StructPatternField>> fields,
- StructPatternEtc etc)
+ std::vector<Attribute> etc_attrs)
: fields (std::move (fields)), has_struct_pattern_etc (true),
- etc (std::move (etc))
+ struct_pattern_etc_attrs (std::move (etc_attrs))
{}
// Constructor for StructPatternElements with no StructPatternEtc
StructPatternElements (
std::vector<std::unique_ptr<StructPatternField>> fields)
: fields (std::move (fields)), has_struct_pattern_etc (false),
- etc (StructPatternEtc::create_empty ())
+ struct_pattern_etc_attrs ()
{}
// Copy constructor with vector clone
StructPatternElements (StructPatternElements const &other)
- : has_struct_pattern_etc (other.has_struct_pattern_etc), etc (other.etc)
+ : has_struct_pattern_etc (other.has_struct_pattern_etc), struct_pattern_etc_attrs (other.struct_pattern_etc_attrs)
{
fields.reserve (other.fields.size ());
for (const auto &e : other.fields)
@@ -588,7 +661,7 @@ public:
// Overloaded assignment operator with vector clone
StructPatternElements &operator= (StructPatternElements const &other)
{
- etc = other.etc;
+ struct_pattern_etc_attrs = other.struct_pattern_etc_attrs;
has_struct_pattern_etc = other.has_struct_pattern_etc;
fields.reserve (other.fields.size ());
@@ -610,6 +683,20 @@ public:
}
std::string as_string () const;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<StructPatternField>> &get_struct_pattern_fields () { return fields; }
+ const std::vector<std::unique_ptr<StructPatternField>> &get_struct_pattern_fields () const { return fields; }
+
+ std::vector<Attribute> &get_etc_outer_attrs () { return struct_pattern_etc_attrs; }
+ const std::vector<Attribute> &get_etc_outer_attrs () const { return struct_pattern_etc_attrs; }
+
+ void strip_etc ()
+ {
+ has_struct_pattern_etc = false;
+ struct_pattern_etc_attrs.clear ();
+ struct_pattern_etc_attrs.shrink_to_fit ();
+ }
};
// Struct pattern AST node representation
@@ -640,9 +727,14 @@ public:
bool has_struct_pattern_elems () const { return !elems.is_empty (); }
Location get_locus () const { return path.get_locus (); }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ StructPatternElements &get_struct_pattern_elems () { return elems; }
+ const StructPatternElements &get_struct_pattern_elems () const { return elems; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -712,6 +804,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const { return patterns; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -768,6 +864,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () { return lower_patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const { return lower_patterns; }
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () { return upper_patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const { return upper_patterns; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -789,6 +893,9 @@ class TupleStructPattern : public Pattern
public:
std::string as_string () const override;
+ // Returns whether the pattern has tuple struct items.
+ bool has_items () const { return items != nullptr; }
+
TupleStructPattern (PathInExpression tuple_struct_path,
std::unique_ptr<TupleStructItems> items)
: path (std::move (tuple_struct_path)), items (std::move (items))
@@ -796,14 +903,23 @@ public:
// Copy constructor required to clone
TupleStructPattern (TupleStructPattern const &other)
- : path (other.path), items (other.items->clone_tuple_struct_items ())
- {}
+ : path (other.path)
+ {
+ // guard to protect from null dereference
+ if (other.items != nullptr)
+ items = other.items->clone_tuple_struct_items ();
+ }
// Operator overload assignment operator to clone
TupleStructPattern &operator= (TupleStructPattern const &other)
{
path = other.path;
- items = other.items->clone_tuple_struct_items ();
+
+ // guard to protect from null dereference
+ if (other.items != nullptr)
+ items = other.items->clone_tuple_struct_items ();
+ else
+ items = nullptr;
return *this;
}
@@ -813,9 +929,17 @@ public:
TupleStructPattern &operator= (TupleStructPattern &&other) = default;
Location get_locus () const { return path.get_locus (); }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::unique_ptr<TupleStructItems> &get_items ()
+ {
+ rust_assert (has_items ());
+ return items;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -921,6 +1045,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const { return patterns; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -979,6 +1107,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () { return lower_patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const { return lower_patterns; }
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () { return upper_patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const { return upper_patterns; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -993,7 +1129,6 @@ class TuplePattern : public Pattern
{
// bool has_tuple_pattern_items;
std::unique_ptr<TuplePatternItems> items;
-
Location locus;
public:
@@ -1030,9 +1165,17 @@ public:
}
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::unique_ptr<TuplePatternItems> &get_items ()
+ {
+ rust_assert (has_tuple_pattern_items ());
+ return items;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1078,9 +1221,17 @@ public:
GroupedPattern &operator= (GroupedPattern &&other) = default;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::unique_ptr<Pattern> &get_pattern_in_parens ()
+ {
+ rust_assert (pattern_in_parens != nullptr);
+ return pattern_in_parens;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1128,9 +1279,14 @@ public:
SlicePattern &operator= (SlicePattern &&other) = default;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_items () { return items; }
+ const std::vector<std::unique_ptr<Pattern>> &get_items () const { return items; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h
index 0bb1021..167828c 100644
--- a/gcc/rust/ast/rust-stmt.h
+++ b/gcc/rust/ast/rust-stmt.h
@@ -131,10 +131,15 @@ public:
// TODO: is this better? Or is a "vis_block" better?
std::unique_ptr<Expr> &get_init_expr () {
- rust_assert (init_expr != nullptr);
+ rust_assert (has_init_expr ());
return init_expr;
}
+ std::unique_ptr<Pattern> &get_pattern () {
+ rust_assert (variables_pattern != nullptr);
+ return variables_pattern;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 78b57eb..d5953a5 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -106,6 +106,7 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
};
@@ -164,6 +165,7 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
};
@@ -212,7 +214,7 @@ public:
}
// Creates a trait bound (clone of this one's trait bound) - HACK
- TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const override
+ TraitBound *to_trait_bound (bool) const override
{
/* NOTE: obviously it is unknown whether the internal type is a trait bound
* due to polymorphism, so just let the internal type handle it. As
@@ -221,6 +223,7 @@ public:
}
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
};
@@ -229,7 +232,6 @@ public:
class ImplTraitTypeOneBound : public TypeNoBounds
{
TraitBound trait_bound;
-
Location locus;
protected:
@@ -248,6 +250,7 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
};
@@ -258,7 +261,6 @@ class TraitObjectTypeOneBound : public TypeNoBounds
{
bool has_dyn;
TraitBound trait_bound;
-
Location locus;
protected:
@@ -279,14 +281,15 @@ public:
std::string as_string () const override;
// Creates a trait bound (clone of this one's trait bound) - HACK
- TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const override
+ TraitBound *to_trait_bound (bool) const override
{
/* NOTE: this assumes there is no dynamic dispatch specified- if there was,
* this cloning would not be required as parsing is unambiguous. */
- return new AST::TraitBound (trait_bound);
+ return new TraitBound (trait_bound);
}
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
};
@@ -335,6 +338,7 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
@@ -368,6 +372,7 @@ public:
std::string as_string () const override { return "! (never type)"; }
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
};
@@ -420,6 +425,7 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
@@ -480,6 +486,7 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
@@ -528,6 +535,7 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
@@ -574,6 +582,7 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
@@ -607,6 +616,7 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
};
@@ -755,6 +765,7 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index eb01b12..d684c7d 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -100,11 +100,11 @@ Compilation::compileVarDecl (Bfunction *fndecl, AST::LetStmt *stmt,
stmt->variables_pattern->accept_vis (*this);
for (auto &pattern : patternBuffer)
{
- auto var = backend->local_variable (fndecl, pattern.variable_ident,
+ auto var = backend->local_variable (fndecl, pattern.get_ident (),
translatedType, NULL /*decl_var*/,
false /*address_taken*/, stmt->locus);
vars.push_back (var);
- scope.InsertVar (pattern.variable_ident, var);
+ scope.InsertVar (pattern.get_ident (), var);
}
patternBuffer.clear ();
return true;
@@ -219,7 +219,7 @@ Compilation::visit (AST::TypePathSegmentFunction &segment)
void
Compilation::visit (AST::TypePath &path)
{
- if (path.segments.size () > 1)
+ if (path.get_segments ().size () > 1)
{
rust_error_at (path.get_locus (), "unable to compile multi segment types yet");
return;
@@ -953,7 +953,7 @@ Compilation::visit (AST::Function &function)
{
// translate the type
translatedType = NULL;
- param.type->accept_vis (*this);
+ param.get_type ()->accept_vis (*this);
if (translatedType == NULL)
{
rust_error_at (param.get_locus (), "failed to generate type for parameter");
@@ -961,7 +961,7 @@ Compilation::visit (AST::Function &function)
}
auto before = patternBuffer.size ();
- param.param_name->accept_vis (*this);
+ param.get_pattern ()->accept_vis (*this);
if (patternBuffer.size () <= before)
{
rust_error_at (param.get_locus (), "failed to analyse parameter name");
@@ -974,13 +974,13 @@ Compilation::visit (AST::Function &function)
auto paramName = patternBuffer.back ();
patternBuffer.pop_back ();
parameters.push_back (
- Backend::Btyped_identifier (paramName.variable_ident,
+ Backend::Btyped_identifier (paramName.get_ident (),
translatedType, param.get_locus ()));
}
}
Btype *returnType = NULL;
- if (function.has_function_return_type ())
+ if (function.has_return_type ())
{
translatedType = NULL;
function.get_return_type ()->accept_vis (*this);
@@ -1051,7 +1051,7 @@ Compilation::visit (AST::Function &function)
scope.PushBlock (code_block);
Bvariable *retDecl = NULL;
- if (function.has_function_return_type ())
+ if (function.has_return_type ())
{
bool address_is_taken = false;
Bstatement *ret_var_stmt = NULL;
@@ -1302,21 +1302,21 @@ Compilation::visit (AST::LetStmt &stmt)
for (auto &pattern : patternBuffer)
{
Bvariable *var = NULL;
- if (!scope.LookupVar (pattern.variable_ident, &var))
+ if (!scope.LookupVar (pattern.get_ident (), &var))
{
rust_error_at (stmt.get_locus (), "failed to find var decl for %s",
- pattern.variable_ident.c_str ());
+ pattern.get_ident ().c_str ());
return;
}
varBuffer.push_back (var);
Bexpression *init = NULL;
- VISIT_POP (stmt.init_expr->get_locus_slow (), stmt.init_expr, init,
+ VISIT_POP (stmt.get_init_expr ()->get_locus_slow (), stmt.get_init_expr (), init,
exprs);
if (init == NULL)
{
- rust_error_at (stmt.init_expr->get_locus_slow (),
+ rust_error_at (stmt.get_init_expr ()->get_locus_slow (),
"failed to compile init statement");
return;
}
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 7dd9750..2fe84cb 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -15,37 +15,197 @@ namespace Rust {
void expand_struct_fields(std::vector<AST::StructField>& fields) {
for (int i = 0; i < fields.size();) {
- auto& field_attrs = fields[i].get_outer_attrs();
+ auto& field = fields[i];
+
+ auto& field_attrs = field.get_outer_attrs();
expander.expand_cfg_attrs(field_attrs);
- if (expander.fails_cfg(field_attrs))
+ if (expander.fails_cfg(field_attrs)) {
fields.erase(fields.begin() + i);
- else
- i++;
+ continue;
+ }
+
+ // expand sub-types of type, but can't strip type itself
+ auto& type = field.get_field_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+
+ // if nothing else happens, increment
+ i++;
}
}
void expand_tuple_fields(std::vector<AST::TupleField>& fields) {
for (int i = 0; i < fields.size();) {
- auto& field_attrs = fields[i].get_outer_attrs();
+ auto& field = fields[i];
+
+ auto& field_attrs = field.get_outer_attrs();
expander.expand_cfg_attrs(field_attrs);
- if (expander.fails_cfg(field_attrs))
+ if (expander.fails_cfg(field_attrs)) {
fields.erase(fields.begin() + i);
- else
- i++;
+ continue;
+ }
+
+ // expand sub-types of type, but can't strip type itself
+ auto& type = field.get_field_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+
+ // if nothing else happens, increment
+ i++;
}
}
void expand_function_params(std::vector<AST::FunctionParam>& params) {
for (int i = 0; i < params.size();) {
- auto& param_attrs = params[i].get_outer_attrs();
+ auto& param = params[i];
+
+ auto& param_attrs = param.get_outer_attrs();
expander.expand_cfg_attrs(param_attrs);
- if (expander.fails_cfg(param_attrs))
+ if (expander.fails_cfg(param_attrs)) {
params.erase(params.begin() + i);
- else
- i++;
+ continue;
+ }
+
+ // 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_slow(), "cannot strip pattern in this position");
+
+ auto& type = param.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+
+ // increment
+ i++;
+ }
+ }
+
+ void expand_generic_args(AST::GenericArgs& args) {
+ // lifetime args can't be expanded
+
+ // expand type args - strip sub-types only
+ for (auto& type : args.get_type_args()) {
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+ }
+
+ // expand binding args - strip sub-types only
+ for (auto& binding : args.get_binding_args()) {
+ auto& type = binding.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+ }
+ }
+
+ void expand_qualified_path_type(AST::QualifiedPathType& path_type) {
+ auto& type = path_type.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+
+ if (path_type.has_as_clause()) {
+ auto& type_path = path_type.get_as_type_path();
+ visit(type_path);
+ if (type_path.is_marked_for_strip())
+ rust_error_at(type_path.get_locus(), "cannot strip type path in this position");
+ }
+ }
+
+ void expand_closure_params(std::vector<AST::ClosureParam>& params) {
+ for (int i = 0; i < params.size();) {
+ auto& param = params[i];
+
+ auto& param_attrs = param.get_outer_attrs();
+ expander.expand_cfg_attrs(param_attrs);
+ if (expander.fails_cfg(param_attrs)) {
+ params.erase(params.begin() + i);
+ continue;
+ }
+
+ auto& pattern = param.get_pattern();
+ pattern->accept_vis(*this);
+ if (pattern->is_marked_for_strip())
+ rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position");
+
+ if (param.has_type_given()) {
+ auto& type = param.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+ }
+
+ // increment if found nothing else so far
+ i++;
}
}
+ void expand_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_slow(), "cannot strip type in this position");
+ }
+ // TODO: maybe check for invariants being violated - e.g. both type and lifetime?
+ }
+
+ void expand_where_clause(AST::WhereClause& where_clause) {
+ // items cannot be stripped conceptually, so just accept visitor
+ for (auto& item : where_clause.get_items())
+ item->accept_vis(*this);
+ }
+
+ void expand_trait_function_decl(AST::TraitFunctionDecl& decl) {
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : decl.get_generic_params())
+ param->accept_vis(*this);
+
+ /* strip function parameters if required - this is specifically
+ * allowed by spec */
+ expand_function_params(decl.get_function_params());
+
+ if (decl.has_return_type()) {
+ auto& return_type = decl.get_return_type();
+ return_type->accept_vis(*this);
+ if (return_type->is_marked_for_strip())
+ rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position");
+ }
+
+ if (decl.has_where_clause())
+ expand_where_clause(decl.get_where_clause());
+ }
+
+ void expand_trait_method_decl(AST::TraitMethodDecl& decl) {
+ // just expand sub-stuff - can't actually strip generic params themselves
+ 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. */
+ 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());
+
+ if (decl.has_return_type()) {
+ auto& return_type = decl.get_return_type();
+ return_type->accept_vis(*this);
+ if (return_type->is_marked_for_strip())
+ rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position");
+ }
+
+ if (decl.has_where_clause())
+ expand_where_clause(decl.get_where_clause());
+ }
+
void visit(AST::Token& tok) override {
// shouldn't require?
}
@@ -77,7 +237,11 @@ namespace Rust {
return;
}
+ // can't strip simple path
+
// I don't think any macro token trees can be stripped in any way
+
+ // TODO: maybe have cfg! macro stripping behaviour here?
}
void visit(AST::PathInExpression& path) override {
@@ -87,18 +251,43 @@ namespace Rust {
path.mark_for_strip();
return;
}
+
+ for (auto& segment : path.get_segments()) {
+ if (segment.has_generic_args())
+ expand_generic_args(segment.get_generic_args());
+ }
}
void visit(AST::TypePathSegment& segment) override {
- // shouldn't require?
+ // shouldn't require
}
void visit(AST::TypePathSegmentGeneric& segment) override {
- // shouldn't require?
+ // TODO: strip inside generic args
+
+ if (!segment.has_generic_args())
+ return;
+
+ expand_generic_args(segment.get_generic_args());
}
void visit(AST::TypePathSegmentFunction& segment) override {
- // shouldn't require?
+ auto& type_path_function = segment.get_type_path_function();
+
+ for (auto& type : type_path_function.get_params()) {
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+ }
+
+ if (type_path_function.has_return_type()) {
+ auto& return_type = type_path_function.get_return_type();
+ return_type->accept_vis(*this);
+ if (return_type->is_marked_for_strip())
+ rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position");
+ }
}
void visit(AST::TypePath& path) override {
- // shouldn't require?
+ // this shouldn't strip any segments, but can strip inside them
+ for (auto& segment : path.get_segments())
+ segment->accept_vis(*this);
}
void visit(AST::QualifiedPathInExpression& path) override {
// initial strip test based on outer attrs
@@ -107,9 +296,20 @@ namespace Rust {
path.mark_for_strip();
return;
}
+
+ expand_qualified_path_type(path.get_qualified_path_type());
+
+ for (auto& segment : path.get_segments()) {
+ if (segment.has_generic_args())
+ expand_generic_args(segment.get_generic_args());
+ }
}
void visit(AST::QualifiedPathInType& path) override {
- // shouldn't require?
+ expand_qualified_path_type(path.get_qualified_path_type());
+
+ // this shouldn't strip any segments, but can strip inside them
+ for (auto& segment : path.get_segments())
+ segment->accept_vis(*this);
}
void visit(AST::LiteralExpr& expr) override {
@@ -258,14 +458,21 @@ namespace Rust {
/* outer attributes never allowed before these. while cannot strip
* direct descendant expression, can strip ones below that */
+ auto& casted_expr = expr.get_casted_expr();
/* should have no possibility for outer attrs as would be parsed
* with outer expr */
- expr.get_casted_expr()->accept_vis(*this);
+ casted_expr->accept_vis(*this);
// ensure that they are not marked for strip
- if (expr.get_casted_expr()->is_marked_for_strip())
- rust_error_at(expr.get_casted_expr()->get_locus_slow(),
+ if (casted_expr->is_marked_for_strip())
+ rust_error_at(casted_expr->get_locus_slow(),
"cannot strip expression in this position - outer attributes are never allowed before cast exprs");
+
+ // TODO: strip sub-types of type
+ auto& type = expr.get_type_to_cast_to();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
}
void visit(AST::AssignmentExpr& expr) override {
/* outer attributes never allowed before these. while cannot strip
@@ -478,6 +685,12 @@ namespace Rust {
expr.mark_for_strip();
return;
}
+
+ // strip sub-exprs of path
+ auto& struct_name = expr.get_struct_name();
+ visit(struct_name);
+ if (struct_name.is_marked_for_strip())
+ rust_error_at(struct_name.get_locus(), "cannot strip path in this position");
}
void visit(AST::StructExprFieldIdentifier& field) override {
// as no attrs (at moment, at least), no stripping possible
@@ -514,7 +727,13 @@ namespace Rust {
if (expander.fails_cfg(expr.get_inner_attrs())) {
expr.mark_for_strip();
return;
- }
+ }
+
+ // strip sub-exprs of path
+ auto& struct_name = expr.get_struct_name();
+ visit(struct_name);
+ if (struct_name.is_marked_for_strip())
+ rust_error_at(struct_name.get_locus(), "cannot strip path in this position");
/* spec does not specify whether expressions are allowed to be
* stripped at top level of struct fields, but I wouldn't think
@@ -551,6 +770,12 @@ namespace Rust {
return;
}
+ // strip sub-exprs of path
+ auto& struct_name = expr.get_struct_name();
+ visit(struct_name);
+ if (struct_name.is_marked_for_strip())
+ rust_error_at(struct_name.get_locus(), "cannot strip path in this position");
+
/* struct base presumably can't be stripped, as the '..' is before
* the expression. as such, can only strip sub-expressions. */
rust_assert(!expr.get_struct_base().is_invalid());
@@ -576,6 +801,12 @@ namespace Rust {
return;
}
+ // strip sub-exprs of path
+ auto& struct_name = expr.get_struct_name();
+ visit(struct_name);
+ if (struct_name.is_marked_for_strip())
+ rust_error_at(struct_name.get_locus(), "cannot strip path in this position");
+
/* spec says outer attributes are specifically allowed for elements
* of tuple-style struct expressions, so full stripping possible */
auto& values = expr.get_elems();
@@ -598,6 +829,12 @@ namespace Rust {
expr.mark_for_strip();
return;
}
+
+ // strip sub-exprs of path
+ auto& struct_name = expr.get_struct_name();
+ visit(struct_name);
+ if (struct_name.is_marked_for_strip())
+ rust_error_at(struct_name.get_locus(), "cannot strip path in this position");
}
void visit(AST::EnumExprFieldIdentifier& field) override {
// as no attrs (at moment, at least), no stripping possible
@@ -630,6 +867,12 @@ namespace Rust {
// supposedly spec doesn't allow inner attributes in enum exprs
+ // strip sub-exprs of path
+ auto& enum_path = expr.get_enum_variant_path();
+ visit(enum_path);
+ if (enum_path.is_marked_for_strip())
+ rust_error_at(enum_path.get_locus(), "cannot strip path in this position");
+
/* spec does not specify whether expressions are allowed to be
* stripped at top level of expression fields, but I wouldn't think
* that they would be, so operating under the assumption that only
@@ -649,6 +892,12 @@ namespace Rust {
// supposedly spec doesn't allow inner attributes in enum exprs
+ // strip sub-exprs of path
+ auto& enum_path = expr.get_enum_variant_path();
+ visit(enum_path);
+ if (enum_path.is_marked_for_strip())
+ rust_error_at(enum_path.get_locus(), "cannot strip path in this position");
+
/* spec says outer attributes are specifically allowed for elements
* of tuple-style enum expressions, so full stripping possible */
auto& values = expr.get_elems();
@@ -666,6 +915,12 @@ namespace Rust {
}
void visit(AST::EnumExprFieldless& expr) override {
// can't be stripped as no attrs
+
+ // strip sub-exprs of path
+ auto& enum_path = expr.get_enum_variant_path();
+ visit(enum_path);
+ if (enum_path.is_marked_for_strip())
+ rust_error_at(enum_path.get_locus(), "cannot strip path in this position");
}
void visit(AST::CallExpr& expr) override {
// initial strip test based on outer attrs
@@ -716,7 +971,9 @@ namespace Rust {
rust_error_at(receiver->get_locus_slow(),
"cannot strip expression in this position - outer attributes not allowed");
- // no outer attrs on paths possible
+ auto& method_name = expr.get_method_name();
+ if (method_name.has_generic_args())
+ expand_generic_args(method_name.get_generic_args());
/* spec says outer attributes are specifically allowed for elements
* of method call expressions, so full stripping possible */
@@ -760,15 +1017,7 @@ namespace Rust {
/* strip closure parameters if required - this is specifically
* allowed by spec */
- auto& params = expr.get_params();
- for (int i = 0; i < params.size();) {
- auto& param_attrs = params[i].get_outer_attrs();
- expander.expand_cfg_attrs(param_attrs);
- if (expander.fails_cfg(param_attrs))
- params.erase(params.begin() + i);
- else
- i++;
- }
+ expand_closure_params(expr.get_params());
// can't strip expression itself, but can strip sub-expressions
auto& definition_expr = expr.get_definition_expr();
@@ -827,15 +1076,13 @@ namespace Rust {
/* strip closure parameters if required - this is specifically
* allowed by spec */
- auto& params = expr.get_params();
- for (int i = 0; i < params.size();) {
- auto& param_attrs = params[i].get_outer_attrs();
- expander.expand_cfg_attrs(param_attrs);
- if (expander.fails_cfg(param_attrs))
- params.erase(params.begin() + i);
- else
- i++;
- }
+ expand_closure_params(expr.get_params());
+
+ // can't strip return type, but can strip sub-types
+ auto& type = expr.get_return_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
// can't strip expression itself, but can strip sub-expressions
auto& definition_block = expr.get_definition_block();
@@ -1042,6 +1289,12 @@ namespace Rust {
return;
}
+ for (auto& pattern : expr.get_patterns()) {
+ pattern->accept_vis(*this);
+ if (pattern->is_marked_for_strip())
+ rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position");
+ }
+
// can't strip scrutinee expr itself, but can strip sub-expressions
auto& scrutinee_expr = expr.get_scrutinee_expr();
scrutinee_expr->accept_vis(*this);
@@ -1064,6 +1317,12 @@ namespace Rust {
return;
}
+ // TODO: strip sub-patterns of pattern
+ auto& pattern = expr.get_pattern();
+ pattern->accept_vis(*this);
+ if (pattern->is_marked_for_strip())
+ rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position");
+
// can't strip scrutinee expr itself, but can strip sub-expressions
auto& iterator_expr = expr.get_iterator_expr();
iterator_expr->accept_vis(*this);
@@ -1195,6 +1454,12 @@ namespace Rust {
return;
}
+ for (auto& pattern : expr.get_patterns()) {
+ pattern->accept_vis(*this);
+ if (pattern->is_marked_for_strip())
+ rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position");
+ }
+
// can't strip value expr itself, but can strip sub-expressions
auto& value_expr = expr.get_value_expr();
value_expr->accept_vis(*this);
@@ -1217,6 +1482,12 @@ namespace Rust {
return;
}
+ for (auto& pattern : expr.get_patterns()) {
+ pattern->accept_vis(*this);
+ if (pattern->is_marked_for_strip())
+ rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position");
+ }
+
// can't strip value expr itself, but can strip sub-expressions
auto& value_expr = expr.get_value_expr();
value_expr->accept_vis(*this);
@@ -1246,6 +1517,12 @@ namespace Rust {
return;
}
+ for (auto& pattern : expr.get_patterns()) {
+ pattern->accept_vis(*this);
+ if (pattern->is_marked_for_strip())
+ rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position");
+ }
+
// can't strip value expr itself, but can strip sub-expressions
auto& value_expr = expr.get_value_expr();
value_expr->accept_vis(*this);
@@ -1275,6 +1552,12 @@ namespace Rust {
return;
}
+ for (auto& pattern : expr.get_patterns()) {
+ pattern->accept_vis(*this);
+ if (pattern->is_marked_for_strip())
+ rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position");
+ }
+
// can't strip value expr itself, but can strip sub-expressions
auto& value_expr = expr.get_value_expr();
value_expr->accept_vis(*this);
@@ -1332,6 +1615,12 @@ namespace Rust {
continue;
}
+ for (auto& pattern : match_arm.get_patterns()) {
+ pattern->accept_vis(*this);
+ if (pattern->is_marked_for_strip())
+ rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position");
+ }
+
/* assuming that guard expression cannot be stripped as
* strictly speaking you would have to strip the whole guard to
* make syntactical sense, which you can't do. as such, only
@@ -1388,13 +1677,35 @@ namespace Rust {
}
void visit(AST::TypeParam& param) override {
- // shouldn't require?
+ // outer attributes don't actually do anything, so ignore them
+
+ if (param.has_type_param_bounds()) {
+ // don't strip directly, only components of bounds
+ for (auto& bound : param.get_type_param_bounds())
+ bound->accept_vis(*this);
+ }
+
+ 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_slow(), "cannot strip type in this position");
+ }
}
void visit(AST::LifetimeWhereClauseItem& item) override {
- // shouldn't require?
+ // shouldn't require
}
void visit(AST::TypeBoundWhereClauseItem& item) override {
- // shouldn't require?
+ // for lifetimes shouldn't require
+
+ auto& type = item.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+
+ // don't strip directly, only components of bounds
+ for (auto& bound : item.get_type_param_bounds())
+ bound->accept_vis(*this);
}
void visit(AST::Method& method) override {
// initial test based on outer attrs
@@ -1404,14 +1715,29 @@ namespace Rust {
return;
}
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : method.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. */
+ expand_self_param(method.get_self_param());
/* strip method parameters if required - this is specifically
* allowed by spec */
expand_function_params(method.get_function_params());
+ if (method.has_return_type()) {
+ auto& return_type = method.get_return_type();
+ return_type->accept_vis(*this);
+ if (return_type->is_marked_for_strip())
+ rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position");
+ }
+
+ if (method.has_where_clause())
+ expand_where_clause(method.get_where_clause());
+
/* body should always exist - if error state, should have returned
* before now */
// can't strip block itself, but can strip sub-expressions
@@ -1491,10 +1817,24 @@ namespace Rust {
return;
}
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : function.get_generic_params())
+ param->accept_vis(*this);
+
/* strip function parameters if required - this is specifically
* allowed by spec */
expand_function_params(function.get_function_params());
+ if (function.has_return_type()) {
+ auto& return_type = function.get_return_type();
+ return_type->accept_vis(*this);
+ if (return_type->is_marked_for_strip())
+ rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position");
+ }
+
+ if (function.has_where_clause())
+ expand_where_clause(function.get_where_clause());
+
/* body should always exist - if error state, should have returned
* before now */
// can't strip block itself, but can strip sub-expressions
@@ -1511,6 +1851,18 @@ namespace Rust {
type_alias.mark_for_strip();
return;
}
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : type_alias.get_generic_params())
+ param->accept_vis(*this);
+
+ if (type_alias.has_where_clause())
+ expand_where_clause(type_alias.get_where_clause());
+
+ auto& type = type_alias.get_type_aliased();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
}
void visit(AST::StructStruct& struct_item) override {
// initial test based on outer attrs
@@ -1520,6 +1872,13 @@ namespace Rust {
return;
}
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : struct_item.get_generic_params())
+ param->accept_vis(*this);
+
+ if (struct_item.has_where_clause())
+ expand_where_clause(struct_item.get_where_clause());
+
/* strip struct fields if required - this is presumably
* allowed by spec */
expand_struct_fields(struct_item.get_fields());
@@ -1532,9 +1891,16 @@ namespace Rust {
return;
}
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : tuple_struct.get_generic_params())
+ param->accept_vis(*this);
+
/* strip struct fields if required - this is presumably
* allowed by spec */
expand_tuple_fields(tuple_struct.get_fields());
+
+ if (tuple_struct.has_where_clause())
+ expand_where_clause(tuple_struct.get_where_clause());
}
void visit(AST::EnumItem& item) override {
// initial test based on outer attrs
@@ -1593,6 +1959,13 @@ namespace Rust {
return;
}
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : enum_item.get_generic_params())
+ param->accept_vis(*this);
+
+ if (enum_item.has_where_clause())
+ expand_where_clause(enum_item.get_where_clause());
+
/* strip enum fields if required - this is presumably
* allowed by spec */
auto& variants = enum_item.get_variants();
@@ -1616,6 +1989,13 @@ namespace Rust {
return;
}
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : union_item.get_generic_params())
+ param->accept_vis(*this);
+
+ if (union_item.has_where_clause())
+ expand_where_clause(union_item.get_where_clause());
+
/* strip union fields if required - this is presumably
* allowed by spec */
expand_struct_fields(union_item.get_variants());
@@ -1628,6 +2008,12 @@ namespace Rust {
return;
}
+ // strip any sub-types
+ auto& type = const_item.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+
/* strip any internal sub-expressions - expression itself isn't
* allowed to have external attributes in this position so can't be
* stripped. */
@@ -1645,6 +2031,12 @@ namespace Rust {
return;
}
+ // strip any sub-types
+ auto& type = static_item.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+
/* strip any internal sub-expressions - expression itself isn't
* allowed to have external attributes in this position so can't be
* stripped. */
@@ -1662,9 +2054,7 @@ namespace Rust {
return;
}
- /* strip function parameters if required - this is specifically
- * allowed by spec */
- expand_function_params(item.get_function_params());
+ expand_trait_function_decl(item.get_trait_function_decl());
if (item.has_definition()) {
/* strip any internal sub-expressions - expression itself isn't
@@ -1685,13 +2075,7 @@ namespace Rust {
return;
}
- /* 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. */
-
- /* strip function parameters if required - this is specifically
- * allowed by spec */
- expand_function_params(item.get_function_params());
+ expand_trait_method_decl(item.get_trait_method_decl());
if (item.has_definition()) {
/* strip any internal sub-expressions - expression itself isn't
@@ -1712,6 +2096,12 @@ namespace Rust {
return;
}
+ // strip any sub-types
+ auto& type = item.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+
/* strip any internal sub-expressions - expression itself isn't
* allowed to have external attributes in this position so can't be
* stripped */
@@ -1730,6 +2120,12 @@ namespace Rust {
item.mark_for_strip();
return;
}
+
+ if (item.has_type_param_bounds()) {
+ // don't strip directly, only components of bounds
+ for (auto& bound : item.get_type_param_bounds())
+ bound->accept_vis(*this);
+ }
}
void visit(AST::Trait& trait) override {
// initial strip test based on outer attrs
@@ -1746,6 +2142,19 @@ namespace Rust {
return;
}
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : trait.get_generic_params())
+ param->accept_vis(*this);
+
+ if (trait.has_type_param_bounds()) {
+ // don't strip directly, only components of bounds
+ for (auto& bound : trait.get_type_param_bounds())
+ bound->accept_vis(*this);
+ }
+
+ if (trait.has_where_clause())
+ expand_where_clause(trait.get_where_clause());
+
// strip trait items if required
auto& trait_items = trait.get_trait_items();
for (int i = 0; i < trait_items.size();) {
@@ -1775,6 +2184,18 @@ namespace Rust {
return;
}
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : impl.get_generic_params())
+ param->accept_vis(*this);
+
+ auto& type = impl.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+
+ if (impl.has_where_clause())
+ expand_where_clause(impl.get_where_clause());
+
// strip inherent impl items if required
auto& impl_items = impl.get_impl_items();
for (int i = 0; i < impl_items.size();) {
@@ -1804,6 +2225,23 @@ namespace Rust {
return;
}
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : impl.get_generic_params())
+ param->accept_vis(*this);
+
+ auto& type = impl.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+
+ auto& trait_path = impl.get_trait_path();
+ visit(trait_path);
+ if (trait_path.is_marked_for_strip())
+ rust_error_at(trait_path.get_locus(), "cannot strip typepath in this position");
+
+ if (impl.has_where_clause())
+ expand_where_clause(impl.get_where_clause());
+
// strip trait impl items if required
auto& impl_items = impl.get_impl_items();
for (int i = 0; i < impl_items.size();) {
@@ -1825,6 +2263,11 @@ namespace Rust {
item.mark_for_strip();
return;
}
+
+ auto& type = item.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
}
void visit(AST::ExternalFunctionItem& item) override {
// strip test based on outer attrs
@@ -1834,16 +2277,30 @@ namespace Rust {
return;
}
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto& param : item.get_generic_params())
+ param->accept_vis(*this);
+
/* strip function parameters if required - this is specifically
* allowed by spec */
auto& params = item.get_function_params();
for (int i = 0; i < params.size();) {
- auto& param_attrs = params[i].get_outer_attrs();
+ auto& param = params[i];
+
+ auto& param_attrs = param.get_outer_attrs();
expander.expand_cfg_attrs(param_attrs);
- if (expander.fails_cfg(param_attrs))
+ if (expander.fails_cfg(param_attrs)) {
params.erase(params.begin() + i);
- else
- i++;
+ continue;
+ }
+
+ auto& type = param.get_type();
+ type->accept_vis(*this);
+ if (type->is_marked_for_strip())
+ rust_error_at(type->get_locus_slow(), "cannot strip type in this position");
+
+ // increment if nothing else happens
+ i++;
}
/* NOTE: these are extern function params, which may have different
* rules and restrictions to "normal" function params. So expansion
@@ -1851,6 +2308,16 @@ namespace Rust {
/* TODO: assuming that variadic nature cannot be stripped. If this
* is not true, then have code here to do so. */
+
+ if (item.has_return_type()) {
+ auto& return_type = item.get_return_type();
+ return_type->accept_vis(*this);
+ if (return_type->is_marked_for_strip())
+ rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position");
+ }
+
+ if (item.has_where_clause())
+ expand_where_clause(item.get_where_clause());
}
void visit(AST::ExternBlock& block) override {
// initial strip test based on outer attrs
@@ -1904,6 +2371,8 @@ namespace Rust {
}
// I don't think any macro token trees can be stripped in any way
+
+ // TODO: maybe have stripping behaviour for the cfg! macro here?
}
void visit(AST::MetaItemPath& meta_item) override {}
void visit(AST::MetaItemSeq& meta_item) override {}
@@ -1912,29 +2381,186 @@ namespace Rust {
void visit(AST::MetaListPaths& meta_item) override {}
void visit(AST::MetaListNameValueStr& meta_item) override {}
- // stripping shouldn't be required or possible for patterns
- void visit(AST::LiteralPattern& pattern) override {}
- void visit(AST::IdentifierPattern& pattern) override {}
- void visit(AST::WildcardPattern& pattern) override {}
- void visit(AST::RangePatternBoundLiteral& bound) override {}
- void visit(AST::RangePatternBoundPath& bound) override {}
- void visit(AST::RangePatternBoundQualPath& bound) override {}
- void visit(AST::RangePattern& pattern) override {}
- void visit(AST::ReferencePattern& pattern) override {}
- void visit(AST::StructPatternFieldTuplePat& field) override {}
- void visit(AST::StructPatternFieldIdentPat& field) override {}
- void visit(AST::StructPatternFieldIdent& field) override {}
+ void visit(AST::LiteralPattern& pattern) override {
+ // not possible
+ }
+ void visit(AST::IdentifierPattern& pattern) override {
+ // can only strip sub-patterns of the inner pattern to bind
+ if (!pattern.has_pattern_to_bind())
+ return;
+
+ auto& sub_pattern = pattern.get_pattern_to_bind();
+ sub_pattern->accept_vis(*this);
+ if (sub_pattern->is_marked_for_strip())
+ rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position");
+ }
+ void visit(AST::WildcardPattern& pattern) override {
+ // not possible
+ }
+ void visit(AST::RangePatternBoundLiteral& bound) override {
+ // not possible
+ }
+ void visit(AST::RangePatternBoundPath& bound) override {
+ // TODO: maybe possible if path is possible
+ }
+ void visit(AST::RangePatternBoundQualPath& bound) override {
+ // TODO: maybe possible if path is possible
+ }
+ void visit(AST::RangePattern& pattern) override {
+ // TODO: possible if any bounds are possible
+ }
+ void visit(AST::ReferencePattern& pattern) override {
+ auto& sub_pattern = pattern.get_referenced_pattern();
+ sub_pattern->accept_vis(*this);
+ if (sub_pattern->is_marked_for_strip())
+ rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position");
+ }
+ void visit(AST::StructPatternFieldTuplePat& field) override {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs(field.get_outer_attrs());
+ if (expander.fails_cfg(field.get_outer_attrs())) {
+ field.mark_for_strip();
+ return;
+ }
+
+ // strip sub-patterns (can't strip top-level pattern)
+ auto& sub_pattern = field.get_index_pattern();
+ sub_pattern->accept_vis(*this);
+ if (sub_pattern->is_marked_for_strip())
+ rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position");
+ }
+ void visit(AST::StructPatternFieldIdentPat& field) override {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs(field.get_outer_attrs());
+ if (expander.fails_cfg(field.get_outer_attrs())) {
+ field.mark_for_strip();
+ return;
+ }
+
+ // strip sub-patterns (can't strip top-level pattern)
+ auto& sub_pattern = field.get_ident_pattern();
+ sub_pattern->accept_vis(*this);
+ if (sub_pattern->is_marked_for_strip())
+ rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position");
+ }
+ void visit(AST::StructPatternFieldIdent& field) override {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs(field.get_outer_attrs());
+ if (expander.fails_cfg(field.get_outer_attrs())) {
+ field.mark_for_strip();
+ return;
+ }
+ }
void visit(AST::StructPattern& pattern) override {
// TODO: apparently struct pattern fields can have outer attrs. so can they be stripped?
+ if (!pattern.has_struct_pattern_elems())
+ return;
+
+ auto& elems = pattern.get_struct_pattern_elems();
+
+ // assuming you can strip struct pattern fields
+ auto& fields = elems.get_struct_pattern_fields();
+ for (int i = 0; i < fields.size();) {
+ auto& field = fields[i];
+
+ field->accept_vis(*this);
+
+ if (field->is_marked_for_strip())
+ fields.erase(fields.begin() + i);
+ else
+ i++;
+ }
+
+ // assuming you can strip the ".." part
+ if (elems.has_etc()) {
+ expander.expand_cfg_attrs(elems.get_etc_outer_attrs());
+ if (expander.fails_cfg(elems.get_etc_outer_attrs()))
+ elems.strip_etc();
+ }
+ }
+ void visit(AST::TupleStructItemsNoRange& tuple_items) override {
+ // can't strip individual patterns, only sub-patterns
+ for (auto& pattern : tuple_items.get_patterns()) {
+ pattern->accept_vis(*this);
+
+ if (pattern->is_marked_for_strip())
+ rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ }
+ void visit(AST::TupleStructItemsRange& tuple_items) override {
+ // can't strip individual patterns, only sub-patterns
+ for (auto& lower_pattern : tuple_items.get_lower_patterns()) {
+ lower_pattern->accept_vis(*this);
+
+ if (lower_pattern->is_marked_for_strip())
+ rust_error_at(lower_pattern->get_locus_slow(), "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ for (auto& upper_pattern : tuple_items.get_upper_patterns()) {
+ upper_pattern->accept_vis(*this);
+
+ if (upper_pattern->is_marked_for_strip())
+ rust_error_at(upper_pattern->get_locus_slow(), "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ }
+ void visit(AST::TupleStructPattern& pattern) override {
+ // TODO: stripping of path?
+
+ if (pattern.has_items())
+ pattern.get_items()->accept_vis(*this);
+ }
+ void visit(AST::TuplePatternItemsMultiple& tuple_items) override {
+ // can't strip individual patterns, only sub-patterns
+ for (auto& pattern : tuple_items.get_patterns()) {
+ pattern->accept_vis(*this);
+
+ if (pattern->is_marked_for_strip())
+ rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ }
+ void visit(AST::TuplePatternItemsRanged& tuple_items) override {
+ // can't strip individual patterns, only sub-patterns
+ for (auto& lower_pattern : tuple_items.get_lower_patterns()) {
+ lower_pattern->accept_vis(*this);
+
+ if (lower_pattern->is_marked_for_strip())
+ rust_error_at(lower_pattern->get_locus_slow(), "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ for (auto& upper_pattern : tuple_items.get_upper_patterns()) {
+ upper_pattern->accept_vis(*this);
+
+ if (upper_pattern->is_marked_for_strip())
+ rust_error_at(upper_pattern->get_locus_slow(), "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ }
+ void visit(AST::TuplePattern& pattern) override {
+ if (pattern.has_tuple_pattern_items())
+ pattern.get_items()->accept_vis(*this);
+ }
+ void visit(AST::GroupedPattern& pattern) override {
+ // can't strip inner pattern, only sub-patterns
+ auto& pattern_in_parens = pattern.get_pattern_in_parens();
+
+ pattern_in_parens->accept_vis(*this);
+
+ if (pattern_in_parens->is_marked_for_strip())
+ rust_error_at(pattern_in_parens->get_locus_slow(), "cannot strip pattern in this position");
+ }
+ void visit(AST::SlicePattern& pattern) override {
+ // can't strip individual patterns, only sub-patterns
+ for (auto& item : pattern.get_items()) {
+ item->accept_vis(*this);
+
+ if (item->is_marked_for_strip())
+ rust_error_at(item->get_locus_slow(), "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
}
- void visit(AST::TupleStructItemsNoRange& tuple_items) override {}
- void visit(AST::TupleStructItemsRange& tuple_items) override {}
- void visit(AST::TupleStructPattern& pattern) override {}
- void visit(AST::TuplePatternItemsMultiple& tuple_items) override {}
- void visit(AST::TuplePatternItemsRanged& tuple_items) override {}
- void visit(AST::TuplePattern& pattern) override {}
- void visit(AST::GroupedPattern& pattern) override {}
- void visit(AST::SlicePattern& pattern) override {}
void visit(AST::EmptyStmt& stmt) override {
// assuming no outer attributes, so nothing can happen
@@ -1947,6 +2573,12 @@ namespace Rust {
return;
}
+ // can't strip pattern, but call for sub-patterns
+ auto& pattern = stmt.get_pattern();
+ pattern->accept_vis(*this);
+ if (pattern->is_marked_for_strip())
+ rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position");
+
/* strip any internal sub-expressions - expression itself isn't
* allowed to have external attributes in this position so can't be
* stripped */
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 769cf41..88252ac 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -10150,6 +10150,14 @@ Parser<ManagedTokenSource>::parse_pattern ()
// tuple struct
lexer.skip_token ();
+ // check if empty tuple
+ if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
+ {
+ lexer.skip_token ();
+ return std::unique_ptr<AST::TupleStructPattern> (
+ new AST::TupleStructPattern (std::move (path), nullptr));
+ }
+
// parse items
std::unique_ptr<AST::TupleStructItems> items
= parse_tuple_struct_items ();
@@ -10574,6 +10582,14 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
// DEBUG
fprintf (stderr, "parsing tuple struct pattern\n");
+ // check if empty tuple
+ if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
+ {
+ lexer.skip_token ();
+ return std::unique_ptr<AST::TupleStructPattern> (
+ new AST::TupleStructPattern (std::move (path), nullptr));
+ }
+
// parse items
std::unique_ptr<AST::TupleStructItems> items
= parse_tuple_struct_items ();
@@ -10816,53 +10832,46 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems ()
{
std::vector<std::unique_ptr<AST::StructPatternField> > fields;
+ std::vector<AST::Attribute> etc_attrs;
+ bool has_etc = false;
+
// try parsing struct pattern fields
const_TokenPtr t = lexer.peek_token ();
- while (t->get_id () != RIGHT_CURLY && t->get_id () != DOT_DOT)
+ while (t->get_id () != RIGHT_CURLY)
{
+ std::vector<AST::Attribute> outer_attrs = parse_outer_attributes ();
+
+ // parse etc (must be last in struct pattern, so breaks)
+ if (lexer.peek_token ()->get_id () == DOT_DOT)
+ {
+ lexer.skip_token ();
+ etc_attrs = std::move (outer_attrs);
+ has_etc = true;
+ break;
+ }
+
std::unique_ptr<AST::StructPatternField> field
- = parse_struct_pattern_field ();
+ = parse_struct_pattern_field_partial (std::move (outer_attrs));
if (field == nullptr)
{
- // TODO: should this be an error?
- // assuming that this means that it is a struct pattern etc instead
-
- // DEBUG
- fprintf (
- stderr,
- "failed to parse struct pattern field - breaking from loop\n");
-
- break;
+ rust_error_at (lexer.peek_token ()->get_locus (), "failed to parse struct pattern field");
+ // skip after somewhere?
+ return AST::StructPatternElements::create_empty ();
}
-
fields.push_back (std::move (field));
- // DEBUG
- fprintf (stderr, "successfully pushed back a struct pattern field\n");
-
if (lexer.peek_token ()->get_id () != COMMA)
- {
break;
- }
- lexer.skip_token ();
-
- t = lexer.peek_token ();
- }
- /* FIXME: this method of parsing prevents parsing any outer attributes on the
- * .. - also there seems to be no distinction between having etc and not
- * having etc. */
- if (lexer.peek_token ()->get_id () == DOT_DOT)
- {
+ // skip comma
lexer.skip_token ();
-
- // as no outer attributes
- AST::StructPatternEtc etc = AST::StructPatternEtc::create_empty ();
-
- return AST::StructPatternElements (std::move (fields), std::move (etc));
+ t = lexer.peek_token ();
}
- return AST::StructPatternElements (std::move (fields));
+ if (has_etc)
+ return AST::StructPatternElements (std::move (fields), std::move (etc_attrs));
+ else
+ return AST::StructPatternElements (std::move (fields));
}
/* Parses a struct pattern field (tuple index/pattern, identifier/pattern, or
@@ -10874,6 +10883,15 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field ()
// parse outer attributes (if they exist)
std::vector<AST::Attribute> outer_attrs = parse_outer_attributes ();
+ return parse_struct_pattern_field_partial (std::move (outer_attrs));
+}
+
+/* Parses a struct pattern field (tuple index/pattern, identifier/pattern, or
+ * identifier), with outer attributes passed in. */
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::StructPatternField>
+Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (std::vector<AST::Attribute> outer_attrs)
+{
// branch based on next token
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 5202abf..a6de87b 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -575,6 +575,7 @@ private:
std::unique_ptr<AST::TupleStructItems> parse_tuple_struct_items ();
AST::StructPatternElements parse_struct_pattern_elems ();
std::unique_ptr<AST::StructPatternField> parse_struct_pattern_field ();
+ std::unique_ptr<AST::StructPatternField> parse_struct_pattern_field_partial (std::vector<AST::Attribute> outer_attrs);
int left_binding_power (const_TokenPtr token);