https://gcc.gnu.org/g:3ce3af99a166fff35636a4f58d3d7d90b2223ecb
commit r17-3131-g3ce3af99a166fff35636a4f58d3d7d90b2223ecb Author: Owen Avery <[email protected]> Date: Sun Aug 2 12:46:43 2026 -0400 gccrs: Move SlicePattern RestPattern handling This allows the AST to represent SlicePattern instances with more than one RestPattern child, which allows us to handle invalid SlicePattern instances which would be cfg'd out and mostly avoid dealing with the implications of a RestPattern until HIR lowering. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit (SlicePatternItemsNoRest)): Remove function definition. (TokenCollector::visit (SlicePatternItemsHasRest)): Likewise. (TokenCollector::visit (SlicePattern)): Handle sub-patterns. * ast/rust-ast-collector.h (TokenCollector::visit (SlicePatternItemsNoRest)): Remove function declaration. (TokenCollector::visit (SlicePatternItemsHasRest)): Likewise. * ast/rust-ast-full-decls.h (class SlicePatternItemsNoRest): Remove forward declaration. (class SlicePatternItemsHasRest): Likewise. * ast/rust-ast-pointer-visitor.cc (PointerVisitor::visit (SlicePatternItemsNoRest)): Remove function definition. (PointerVisitor::visit (SlicePatternItemsHasRest)): Likewise. (PointerVisitor::visit (SlicePattern)): New function definition. * ast/rust-ast-pointer-visitor.h (PointerVisitor::visit (SlicePatternItemsNoRest)): Remove function declaration. (PointerVisitor::visit (SlicePatternItemsHasRest)): Likewise. (PointerVisitor::visit (SlicePattern)): New function declaration. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit (SlicePatternItemsNoRest)): Remove function definition. (DefaultASTVisitor::visit (SlicePatternItemsHasRest)): Likewise. (DefaultASTVisitor::visit (SlicePattern)): Handle sub-patterns. * ast/rust-ast-visitor.h (ASTVisitor::visit (SlicePatternItemsNoRest)): Remove function declaration. (ASTVisitor::visit (SlicePatternItemsHasRest)): Likewise. (DefaultASTVisitor::visit (SlicePatternItemsNoRest)): Likewise. (DefaultASTVisitor::visit (SlicePatternItemsHasRest)): Likewise. * ast/rust-pattern.cc (SlicePatternItemsNoRest::as_string): Remove function definition. (SlicePatternItemsHasRest::as_string): Likewise. (SlicePattern::as_string): Use as_string on sub patterns directly. (SlicePatternItemsNoRest::accept_vis): Remove function definition. (SlicePatternItemsHasRest::accept_vis): Likewise. * ast/rust-pattern.h (class SlicePatternItems): Remove. (class SlicePatternItemsNoRest): Remove. (class SlicePatternItemsHasRest): Remove. (SlicePattern::items): Remove member variable. (SlicePattern::patterns): New member variable. (SlicePattern::SlicePattern): Adjust to match member variable adjustments. (SlicePattern::get_items): Remove function. (SlicePattern::get_patterns): New function. (class CloneableDelegate<std::unique_ptr<SlicePatternItems>>): Remove specialization. * checks/errors/rust-ast-validation.cc (ASTValidation::visit (SlicePattern)): New function to check for too many RestPattern sub-patterns. * checks/errors/rust-ast-validation.h (ASTValidation::visit (SlicePattern)): New function declaration. * expand/rust-cfg-strip.cc (CfgStrip::visit (SlicePatternItemsNoRest)): Remove function definition. (CfgStrip::visit (SlicePatternItemsHasRest)): Likewise. (CfgStrip::visit (SlicePattern)): Directly visit sub-patterns. * expand/rust-cfg-strip.h (CfgStrip::visit (SlicePatternItemsNoRest)): Remove function declaration. (CfgStrip::visit (SlicePatternItemsHasRest)): Likewise. * expand/rust-derive.h (DeriveVisitor::visit (SlicePatternItemsNoRest)): Remove function. (DeriveVisitor::visit (SlicePatternItemsHasRest)): Likewise. * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit (SlicePatternItemsNoRest)): Remove function definition. (ASTLoweringBase::visit (SlicePatternItemsHasRest)): Likewise. (ASTLoweringBase::lower_slice_pattern_no_rest): Likewise. (ASTLoweringBase::lower_slice_pattern_has_rest): Likewise. * hir/rust-ast-lower-base.h (ASTLoweringBase::visit (SlicePatternItemsNoRest)): Remove function declaration. (ASTLoweringBase::visit (SlicePatternItemsHasRest)): Likewise. (ASTLoweringBase::lower_slice_pattern_no_rest): Likewise. (ASTLoweringBase::lower_slice_pattern_has_rest): Likewise. * hir/rust-ast-lower-pattern.cc (lower_pattern_seq): New function. (ASTLoweringPattern::visit (SlicePattern)): Handle changes to AST SlicePattern. * parse/rust-parse-impl-pattern.hxx (Parser::parse_slice_pattern): Likewise. gcc/testsuite/ChangeLog: * rust/compile/slice_rest_pattern.rs: Verify that too many rest patterns in a slice pattern does not produce an error, if that slice pattern is cfg'd out. Signed-off-by: Owen Avery <[email protected]> Diff: --- gcc/rust/ast/rust-ast-collector.cc | 26 +---- gcc/rust/ast/rust-ast-collector.h | 2 - gcc/rust/ast/rust-ast-full-decls.h | 2 - gcc/rust/ast/rust-ast-pointer-visitor.cc | 15 +-- gcc/rust/ast/rust-ast-pointer-visitor.h | 3 +- gcc/rust/ast/rust-ast-visitor.cc | 19 +--- gcc/rust/ast/rust-ast-visitor.h | 4 - gcc/rust/ast/rust-pattern.cc | 51 +--------- gcc/rust/ast/rust-pattern.h | 123 ++--------------------- gcc/rust/checks/errors/rust-ast-validation.cc | 19 ++++ gcc/rust/checks/errors/rust-ast-validation.h | 1 + gcc/rust/expand/rust-cfg-strip.cc | 35 +------ gcc/rust/expand/rust-cfg-strip.h | 2 - gcc/rust/expand/rust-derive.h | 2 - gcc/rust/hir/rust-ast-lower-base.cc | 41 -------- gcc/rust/hir/rust-ast-lower-base.h | 8 -- gcc/rust/hir/rust-ast-lower-pattern.cc | 52 +++++++--- gcc/rust/parse/rust-parse-impl-pattern.hxx | 96 +++--------------- gcc/testsuite/rust/compile/slice_rest_pattern.rs | 3 + 19 files changed, 96 insertions(+), 408 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index b478a8d4804e..b6dd650e6295 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -3055,36 +3055,12 @@ TokenCollector::visit (GroupedPattern &pattern) }); } -void -TokenCollector::visit (SlicePatternItemsNoRest &items) -{ - visit_items_joined_by_separator (items.get_patterns (), COMMA); -} - -void -TokenCollector::visit (SlicePatternItemsHasRest &items) -{ - if (!items.get_lower_patterns ().empty ()) - { - visit_items_joined_by_separator (items.get_lower_patterns (), COMMA); - push (Rust::Token::make (COMMA, UNDEF_LOCATION)); - } - - push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION)); - - if (!items.get_upper_patterns ().empty ()) - { - push (Rust::Token::make (COMMA, UNDEF_LOCATION)); - visit_items_joined_by_separator (items.get_upper_patterns (), COMMA); - } -} - void TokenCollector::visit (SlicePattern &pattern) { describe_node (std::string ("SlicePattern"), [this, &pattern] () { push (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ())); - visit (pattern.get_items ()); + visit_items_joined_by_separator (pattern.get_patterns (), COMMA); push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION)); }); } diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index 6f03f5758629..e3cd703735ca 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -424,8 +424,6 @@ public: void visit (TuplePatternItemsHasRest &tuple_items); void visit (TuplePattern &pattern); void visit (GroupedPattern &pattern); - void visit (SlicePatternItemsNoRest &items); - void visit (SlicePatternItemsHasRest &items); void visit (SlicePattern &pattern); void visit (AltPattern &pattern); diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 21bb686d4e72..cf8b060376b5 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -247,8 +247,6 @@ class TuplePatternItemsNoRest; class TuplePatternItemsHasRest; class TuplePattern; class GroupedPattern; -class SlicePatternItemsNoRest; -class SlicePatternItemsHasRest; class SlicePattern; class AltPattern; diff --git a/gcc/rust/ast/rust-ast-pointer-visitor.cc b/gcc/rust/ast/rust-ast-pointer-visitor.cc index 40df7a08f4b6..cea7ae647546 100644 --- a/gcc/rust/ast/rust-ast-pointer-visitor.cc +++ b/gcc/rust/ast/rust-ast-pointer-visitor.cc @@ -919,19 +919,10 @@ PointerVisitor::visit (AST::GroupedPattern &pattern) } void -PointerVisitor::visit (AST::SlicePatternItemsNoRest &items) +PointerVisitor::visit (AST::SlicePattern &pattern) { - for (auto &item : items.get_patterns ()) - reseat (item); -} - -void -PointerVisitor::visit (AST::SlicePatternItemsHasRest &items) -{ - for (auto &item : items.get_lower_patterns ()) - reseat (item); - for (auto &item : items.get_upper_patterns ()) - reseat (item); + for (auto &pat : pattern.get_patterns ()) + reseat (pat); } void diff --git a/gcc/rust/ast/rust-ast-pointer-visitor.h b/gcc/rust/ast/rust-ast-pointer-visitor.h index a12343e45322..498f99c4ae38 100644 --- a/gcc/rust/ast/rust-ast-pointer-visitor.h +++ b/gcc/rust/ast/rust-ast-pointer-visitor.h @@ -150,8 +150,7 @@ public: void visit (AST::TuplePatternItemsNoRest &tuple_items) override; void visit (AST::TuplePatternItemsHasRest &tuple_items) override; void visit (AST::GroupedPattern &pattern) override; - void visit (AST::SlicePatternItemsNoRest &items) override; - void visit (AST::SlicePatternItemsHasRest &items) override; + void visit (AST::SlicePattern &pattern) override; void visit (AST::AltPattern &pattern) override; void visit (AST::LetStmt &stmt) override; void visit (AST::ExprStmt &stmt) override; diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index f7d33ffc44e5..c800f2c30dcb 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -1345,26 +1345,11 @@ DefaultASTVisitor::visit (AST::GroupedPattern &pattern) visit (pattern.get_pattern_in_parens ()); } -void -DefaultASTVisitor::visit (AST::SlicePatternItemsNoRest &items) -{ - for (auto &item : items.get_patterns ()) - visit (item); -} - -void -DefaultASTVisitor::visit (AST::SlicePatternItemsHasRest &items) -{ - for (auto &item : items.get_lower_patterns ()) - visit (item); - for (auto &item : items.get_upper_patterns ()) - visit (item); -} - void DefaultASTVisitor::visit (AST::SlicePattern &pattern) { - visit (pattern.get_items ()); + for (auto &pat : pattern.get_patterns ()) + visit (pat); } void diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index c3ec4362b50e..4ca56d139e95 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -212,8 +212,6 @@ public: virtual void visit (TuplePatternItemsHasRest &tuple_items) = 0; virtual void visit (TuplePattern &pattern) = 0; virtual void visit (GroupedPattern &pattern) = 0; - virtual void visit (SlicePatternItemsNoRest &items) = 0; - virtual void visit (SlicePatternItemsHasRest &items) = 0; virtual void visit (SlicePattern &pattern) = 0; virtual void visit (AltPattern &pattern) = 0; @@ -387,8 +385,6 @@ public: virtual void visit (AST::TuplePatternItemsHasRest &tuple_items) override; virtual void visit (AST::TuplePattern &pattern) override; virtual void visit (AST::GroupedPattern &pattern) override; - virtual void visit (AST::SlicePatternItemsNoRest &items) override; - virtual void visit (AST::SlicePatternItemsHasRest &items) override; virtual void visit (AST::SlicePattern &pattern) override; virtual void visit (AST::AltPattern &pattern) override; virtual void visit (AST::EmptyStmt &stmt) override; diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc index e8bf1c9911e9..750c586a0979 100644 --- a/gcc/rust/ast/rust-pattern.cc +++ b/gcc/rust/ast/rust-pattern.cc @@ -327,52 +327,17 @@ GroupedExpr::as_string () const } std::string -SlicePatternItemsNoRest::as_string () const +SlicePattern::as_string () const { std::string str; + str = "SlicePattern: "; for (const auto &pattern : patterns.get ()) str += "\n " + pattern->as_string (); return str; } -std::string -SlicePatternItemsHasRest::as_string () const -{ - std::string str; - - str += "\n Lower patterns: "; - if (lower_patterns.get ().empty ()) - { - str += "none"; - } - else - { - for (const auto &lower : lower_patterns.get ()) - str += "\n " + lower->as_string (); - } - - str += "\n Upper patterns: "; - if (upper_patterns.get ().empty ()) - { - str += "none"; - } - else - { - for (const auto &upper : upper_patterns.get ()) - str += "\n " + upper->as_string (); - } - - return str; -} - -std::string -SlicePattern::as_string () const -{ - return "SlicePattern: " + items.get ()->as_string (); -} - std::string AltPattern::as_string () const { @@ -402,18 +367,6 @@ GroupedExpr::accept_vis (ASTVisitor &vis) vis.visit (*this); } -void -SlicePatternItemsNoRest::accept_vis (ASTVisitor &vis) -{ - vis.visit (*this); -} - -void -SlicePatternItemsHasRest::accept_vis (ASTVisitor &vis) -{ - vis.visit (*this); -} - void SlicePattern::accept_vis (ASTVisitor &vis) { diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 78780f3cc22a..a175ff670fe4 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -1211,117 +1211,19 @@ protected: } }; -// Base abstract class representing patterns in a SlicePattern -class SlicePatternItems : public PatternItems -{ -public: - // Unique pointer custom clone function - std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const - { - return std::unique_ptr<SlicePatternItems> (clone_pattern_items_impl ()); - } - -protected: - // pure virtual clone implementation - virtual SlicePatternItems *clone_pattern_items_impl () const = 0; -}; - -// Class representing the patterns in a SlicePattern without `..` -class SlicePatternItemsNoRest : public SlicePatternItems -{ - Cloneable<std::vector<std::unique_ptr<Pattern>>> patterns; - -public: - SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) - : patterns (std::move (patterns)) - {} - - std::string as_string () const override; - - void accept_vis (ASTVisitor &vis) override; - - // TODO: seems kinda dodgy. Think of better way. - std::vector<std::unique_ptr<Pattern>> &get_patterns () - { - return patterns.get (); - } - const std::vector<std::unique_ptr<Pattern>> &get_patterns () const - { - return patterns.get (); - } - - ItemType get_item_type () const override { return ItemType::NO_REST; } - -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - SlicePatternItemsNoRest *clone_pattern_items_impl () const override - { - return new SlicePatternItemsNoRest (*this); - } -}; - -// Class representing the patterns in a SlicePattern that contains a `..` -class SlicePatternItemsHasRest : public SlicePatternItems -{ - Cloneable<std::vector<std::unique_ptr<Pattern>>> lower_patterns; - Cloneable<std::vector<std::unique_ptr<Pattern>>> upper_patterns; - -public: - SlicePatternItemsHasRest ( - std::vector<std::unique_ptr<Pattern>> lower_patterns, - std::vector<std::unique_ptr<Pattern>> upper_patterns) - : lower_patterns (std::move (lower_patterns)), - upper_patterns (std::move (upper_patterns)) - {} - - std::string as_string () const override; - - 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.get (); - } - const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const - { - return lower_patterns.get (); - } - - // TODO: seems kinda dodgy. Think of better way. - std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () - { - return upper_patterns.get (); - } - const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const - { - return upper_patterns.get (); - } - - ItemType get_item_type () const override { return ItemType::HAS_REST; } - -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - SlicePatternItemsHasRest *clone_pattern_items_impl () const override - { - return new SlicePatternItemsHasRest (*this); - } -}; - // AST node representing patterns that can match slices and arrays class SlicePattern : public Pattern { - Cloneable<std::unique_ptr<SlicePatternItems>> items; + Cloneable<std::vector<std::unique_ptr<Pattern>>> patterns; location_t locus; NodeId node_id; public: std::string as_string () const override; - SlicePattern (std::unique_ptr<SlicePatternItems> items, location_t locus) - : items (std::move (items)), locus (locus), + SlicePattern (std::vector<std::unique_ptr<Pattern>> patterns, + location_t locus) + : patterns (std::move (patterns)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} @@ -1330,10 +1232,9 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - SlicePatternItems &get_items () + std::vector<std::unique_ptr<Pattern>> &get_patterns () { - rust_assert (items != nullptr); - return *items.get (); + return patterns.get (); } NodeId get_node_id () const override { return node_id; } @@ -1436,18 +1337,6 @@ template <> struct CloneableDelegate<std::unique_ptr<AST::TuplePatternItems>> } }; -template <> struct CloneableDelegate<std::unique_ptr<AST::SlicePatternItems>> -{ - static std::unique_ptr<AST::SlicePatternItems> - clone (const std::unique_ptr<AST::SlicePatternItems> &other) - { - if (other == nullptr) - return nullptr; - else - return other->clone_slice_pattern_items (); - } -}; - template <> struct CloneableDelegate<std::unique_ptr<AST::StructPatternField>> { static std::unique_ptr<AST::StructPatternField> diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index 52831e26eb14..e3262b947cb4 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -198,4 +198,23 @@ ASTValidation::visit (AST::Module &module) AST::ContextualASTVisitor::visit (module); } +void +ASTValidation::visit (AST::SlicePattern &pattern) +{ + // TODO: store/use first rest pattern location? + // for nicer errors + bool had_rest = false; + + for (auto &pat : pattern.get_patterns ()) + { + if (pat->get_pattern_kind () == AST::Pattern::Kind::Rest) + { + if (had_rest) + rust_error_at (pat->get_locus (), + "%<..%> can only be used once per slice pattern"); + had_rest = true; + } + } +} + } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h index 2e4fcee9c276..c8eb302e7205 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.h +++ b/gcc/rust/checks/errors/rust-ast-validation.h @@ -41,6 +41,7 @@ public: virtual void visit (AST::Union &item); virtual void visit (AST::Function &function); virtual void visit (AST::Trait &trait); + virtual void visit (AST::SlicePattern &pattern); }; } // namespace Rust diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index 514ddbac4674..a5c4c7c1358d 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -2440,43 +2440,18 @@ CfgStrip::visit (AST::GroupedPattern &pattern) } void -CfgStrip::visit (AST::SlicePatternItemsNoRest &items) +CfgStrip::visit (AST::SlicePattern &pattern) { - AST::DefaultASTVisitor::visit (items); + AST::DefaultASTVisitor::visit (pattern); // can't strip individual patterns, only sub-patterns - for (auto &pattern : items.get_patterns ()) + for (auto &sub_pat : pattern.get_patterns ()) { - if (pattern->is_marked_for_strip ()) - rust_error_at (pattern->get_locus (), + if (sub_pat->is_marked_for_strip ()) + rust_error_at (sub_pat->get_locus (), "cannot strip pattern in this position"); } } -void -CfgStrip::visit (AST::SlicePatternItemsHasRest &items) -{ - AST::DefaultASTVisitor::visit (items); - // can't strip individual patterns, only sub-patterns - for (auto &pattern : items.get_lower_patterns ()) - { - if (pattern->is_marked_for_strip ()) - rust_error_at (pattern->get_locus (), - "cannot strip pattern in this position"); - } - for (auto &pattern : items.get_upper_patterns ()) - { - if (pattern->is_marked_for_strip ()) - rust_error_at (pattern->get_locus (), - "cannot strip pattern in this position"); - } -} - -void -CfgStrip::visit (AST::SlicePattern &pattern) -{ - AST::DefaultASTVisitor::visit (pattern); -} - void CfgStrip::visit (AST::AltPattern &pattern) { diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h index e372744f62d9..2619ed58a4ca 100644 --- a/gcc/rust/expand/rust-cfg-strip.h +++ b/gcc/rust/expand/rust-cfg-strip.h @@ -180,8 +180,6 @@ public: void visit (AST::TuplePatternItemsNoRest &tuple_items) override; void visit (AST::TuplePatternItemsHasRest &tuple_items) override; void visit (AST::GroupedPattern &pattern) override; - void visit (AST::SlicePatternItemsNoRest &items) override; - void visit (AST::SlicePatternItemsHasRest &items) override; void visit (AST::SlicePattern &pattern) override; void visit (AST::AltPattern &pattern) override; diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index 3309c919aa3c..6706191262fa 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -232,8 +232,6 @@ private: virtual void visit (TuplePatternItemsHasRest &tuple_items) override final{}; virtual void visit (TuplePattern &pattern) override final{}; virtual void visit (GroupedPattern &pattern) override final{}; - virtual void visit (SlicePatternItemsNoRest &items) override final{}; - virtual void visit (SlicePatternItemsHasRest &items) override final{}; virtual void visit (SlicePattern &pattern) override final{}; virtual void visit (AltPattern &pattern) override final{}; virtual void visit (EmptyStmt &stmt) override final{}; diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index 7cbe52af6298..70a98866dcef 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -504,12 +504,6 @@ void ASTLoweringBase::visit (AST::GroupedPattern &) {} void -ASTLoweringBase::visit (AST::SlicePatternItemsNoRest &) -{} -void -ASTLoweringBase::visit (AST::SlicePatternItemsHasRest &) -{} -void ASTLoweringBase::visit (AST::SlicePattern &) {} void @@ -942,41 +936,6 @@ ASTLoweringBase::lower_tuple_pattern_ranged ( std::move (upper_patterns))); } -std::unique_ptr<HIR::SlicePatternItems> -ASTLoweringBase::lower_slice_pattern_no_rest ( - AST::SlicePatternItemsNoRest &pattern) -{ - std::vector<std::unique_ptr<HIR::Pattern>> patterns; - patterns.reserve (pattern.get_patterns ().size ()); - for (auto &p : pattern.get_patterns ()) - patterns.emplace_back (ASTLoweringPattern::translate (*p)); - - return std::unique_ptr<HIR::SlicePatternItems> ( - new HIR::SlicePatternItemsNoRest (std::move (patterns))); -} - -std::unique_ptr<HIR::SlicePatternItems> -ASTLoweringBase::lower_slice_pattern_has_rest ( - AST::SlicePatternItemsHasRest &pattern) -{ - std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns; - lower_patterns.reserve (pattern.get_lower_patterns ().size ()); - std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns; - upper_patterns.reserve (pattern.get_upper_patterns ().size ()); - - for (auto &p : pattern.get_lower_patterns ()) - lower_patterns.emplace_back ( - std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*p))); - - for (auto &p : pattern.get_upper_patterns ()) - upper_patterns.emplace_back ( - std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*p))); - - return std::unique_ptr<HIR::SlicePatternItems> ( - new HIR::SlicePatternItemsHasRest (std::move (lower_patterns), - std::move (upper_patterns))); -} - std::unique_ptr<HIR::RangePatternBound> ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound) { diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index ff1e51eb21b8..cfc09becf374 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -236,8 +236,6 @@ public: virtual void visit (AST::TuplePatternItemsHasRest &tuple_items) override; virtual void visit (AST::TuplePattern &pattern) override; virtual void visit (AST::GroupedPattern &pattern) override; - virtual void visit (AST::SlicePatternItemsNoRest &items) override; - virtual void visit (AST::SlicePatternItemsHasRest &items) override; virtual void visit (AST::SlicePattern &pattern) override; virtual void visit (AST::AltPattern &pattern) override; @@ -322,12 +320,6 @@ protected: std::unique_ptr<TuplePatternItems> lower_tuple_pattern_ranged (AST::TuplePatternItemsHasRest &pattern); - std::unique_ptr<SlicePatternItems> - lower_slice_pattern_no_rest (AST::SlicePatternItemsNoRest &pattern); - - std::unique_ptr<SlicePatternItems> - lower_slice_pattern_has_rest (AST::SlicePatternItemsHasRest &pattern); - std::unique_ptr<HIR::RangePatternBound> lower_range_pattern_bound (AST::RangePatternBound &bound); diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index 2a2751adaa97..b19a6411d2e9 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -338,27 +338,49 @@ ASTLoweringPattern::visit (AST::ReferencePattern &pattern) } } +template <typename It> +static std::vector<std::unique_ptr<HIR::Pattern>> +lower_pattern_seq (It begin, It end) +{ + std::vector<std::unique_ptr<HIR::Pattern>> ret; + ret.reserve (end - begin); + for (auto it = begin; it != end; it++) + ret.emplace_back (ASTLoweringPattern::translate (**it)); + return ret; +} + void ASTLoweringPattern::visit (AST::SlicePattern &pattern) { + tl::optional<size_t> rest_index; + + std::vector<std::unique_ptr<AST::Pattern>> &sub_patterns + = pattern.get_patterns (); + + for (size_t i = 0; i < sub_patterns.size (); i++) + { + auto &pat = sub_patterns[i]; + if (pat->get_pattern_kind () == AST::Pattern::Kind::Rest) + { + rest_index = i; + // ASTValidation verified there's only one Rest pattern + break; + } + } + std::unique_ptr<HIR::SlicePatternItems> items; - switch (pattern.get_items ().get_item_type ()) + if (rest_index) { - case AST::SlicePatternItems::ItemType::NO_REST: - { - auto &ref - = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ()); - items = ASTLoweringBase::lower_slice_pattern_no_rest (ref); - } - break; - case AST::SlicePatternItems::ItemType::HAS_REST: - { - auto &ref - = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ()); - items = ASTLoweringBase::lower_slice_pattern_has_rest (ref); - } - break; + auto rest_it = sub_patterns.begin () + *rest_index; + items = std::make_unique<HIR::SlicePatternItemsHasRest> ( + lower_pattern_seq (sub_patterns.begin (), rest_it), + lower_pattern_seq (rest_it + 1, sub_patterns.end ())); + } + else + { + items = std::make_unique<HIR::SlicePatternItemsNoRest> ( + lower_pattern_seq (sub_patterns.begin (), sub_patterns.end ())); } auto crate_num = mappings.get_current_crate (); diff --git a/gcc/rust/parse/rust-parse-impl-pattern.hxx b/gcc/rust/parse/rust-parse-impl-pattern.hxx index ab972d61ed25..2c1fe7596d83 100644 --- a/gcc/rust/parse/rust-parse-impl-pattern.hxx +++ b/gcc/rust/parse/rust-parse-impl-pattern.hxx @@ -525,73 +525,26 @@ std::unique_ptr<AST::SlicePattern> Parser<ManagedTokenSource>::parse_slice_pattern () { location_t square_locus = lexer.peek_token ()->get_locus (); - std::vector<std::unique_ptr<AST::Pattern>> patterns; - tl::optional<std::vector<std::unique_ptr<AST::Pattern>>> upper_patterns - = tl::nullopt; - - // lambda function to determine which vector to push new patterns into - auto get_pattern_ref - = [&] () -> std::vector<std::unique_ptr<AST::Pattern>> & { - return upper_patterns.has_value () ? upper_patterns.value () : patterns; - }; + std::vector<std::unique_ptr<AST::Pattern>> sub_patterns; skip_token (LEFT_SQUARE); - if (lexer.peek_token ()->get_id () == RIGHT_SQUARE) - { - skip_token (RIGHT_SQUARE); - std::unique_ptr<AST::SlicePatternItemsNoRest> items ( - new AST::SlicePatternItemsNoRest (std::move (patterns))); - return std::unique_ptr<AST::SlicePattern> ( - new AST::SlicePattern (std::move (items), square_locus)); - } + bool is_first = true; - // parse initial pattern (required) - if (lexer.peek_token ()->get_id () == DOT_DOT) + while (true) { - lexer.skip_token (); - upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> (); - } - else - { - // Not a rest pattern `..`, parse normally - std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern (); - if (initial_pattern == nullptr) - { - Error error (lexer.peek_token ()->get_locus (), - "failed to parse initial pattern in slice pattern"); - add_error (std::move (error)); + const_TokenPtr t = lexer.peek_token (); - return nullptr; + if (!is_first && t->get_id () == COMMA) + { + skip_token (COMMA); + t = lexer.peek_token (); } - patterns.push_back (std::move (initial_pattern)); - } - - const_TokenPtr t = lexer.peek_token (); - while (t->get_id () == COMMA) - { - lexer.skip_token (); - - // break if end bracket - if (lexer.peek_token ()->get_id () == RIGHT_SQUARE) - break; - - if (lexer.peek_token ()->get_id () == DOT_DOT) + if (t->get_id () == RIGHT_SQUARE) { - if (upper_patterns.has_value ()) - { - // DOT_DOT has been parsed before - Error error (lexer.peek_token ()->get_locus (), "%s", - "`..` can only be used once per slice pattern"); - add_error (std::move (error)); - - return nullptr; - } - upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> (); - lexer.skip_token (); - t = lexer.peek_token (); - continue; + skip_token (RIGHT_SQUARE); + break; } // parse pattern (required) @@ -601,34 +554,17 @@ Parser<ManagedTokenSource>::parse_slice_pattern () Error error (lexer.peek_token ()->get_locus (), "failed to parse pattern in slice pattern"); add_error (std::move (error)); + // TODO: skip until closing square bracket return nullptr; } - get_pattern_ref ().push_back (std::move (pattern)); - - t = lexer.peek_token (); - } - if (!skip_token (RIGHT_SQUARE)) - { - return nullptr; - } - - if (upper_patterns.has_value ()) - { - // Slice pattern with rest - std::unique_ptr<AST::SlicePatternItemsHasRest> items ( - new AST::SlicePatternItemsHasRest ( - std::move (patterns), std::move (upper_patterns.value ()))); - return std::unique_ptr<AST::SlicePattern> ( - new AST::SlicePattern (std::move (items), square_locus)); + sub_patterns.push_back (std::move (pattern)); + is_first = false; } - // Rest-less slice pattern - std::unique_ptr<AST::SlicePatternItemsNoRest> items ( - new AST::SlicePatternItemsNoRest (std::move (patterns))); - return std::unique_ptr<AST::SlicePattern> ( - new AST::SlicePattern (std::move (items), square_locus)); + return std::make_unique<AST::SlicePattern> (std::move (sub_patterns), + square_locus); } /* Parses an identifier pattern (pattern that binds a value matched to a diff --git a/gcc/testsuite/rust/compile/slice_rest_pattern.rs b/gcc/testsuite/rust/compile/slice_rest_pattern.rs index 08608b8479a1..8cf7c2a8821e 100644 --- a/gcc/testsuite/rust/compile/slice_rest_pattern.rs +++ b/gcc/testsuite/rust/compile/slice_rest_pattern.rs @@ -8,3 +8,6 @@ pub fn foo(a: &[u32]) { _ => {} } } + +#[cfg(any())] +pub fn foo([.., ..]: ()) {}
