diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2020-11-29 22:47:31 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2020-12-08 21:10:34 +0800 |
commit | db39766514144dbbad34d9db3977c3a72d1216c3 (patch) | |
tree | c7c470e4bf94ccb0105f8ad80ff85c7582ee9358 /gcc | |
parent | 9b252167a77316750f34c455222e5f30724e51e4 (diff) | |
download | gcc-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.cc | 22 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-full-test.cc | 86 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 16 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 50 | ||||
-rw-r--r-- | gcc/rust/ast/rust-item.h | 272 | ||||
-rw-r--r-- | gcc/rust/ast/rust-path.h | 86 | ||||
-rw-r--r-- | gcc/rust/ast/rust-pattern.h | 194 | ||||
-rw-r--r-- | gcc/rust/ast/rust-stmt.h | 7 | ||||
-rw-r--r-- | gcc/rust/ast/rust-type.h | 21 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 24 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 786 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 82 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse.h | 1 |
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 ¶m : 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 ¶m : 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 ¶m : 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 ¶m : 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 ¶m : 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); |