[gccrs COMMIT 1/2] gccrs: Move SlicePattern RestPattern handling
[email protected] Mon, 3 Aug 2026 10:31:06 +0000
| Newsgroups | gmane.comp.gcc.rust,gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
From: Owen Avery <[email protected]> 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]> --- This change was merged into the gccrs repository and is posted here for upstream visibility and potential drive-by review, as requested by GCC release managers. Each commit email contains a link to its details on github from where you can find the Pull-Request and associated discussions. Commit on github: https://github.com/Rust-GCC/gccrs/commit/ad91fefcade73ffbe8c019685e791997245ac963 The commit has NOT been mentioned in any issue. The commit has been mentioned in the following pull-request(s): - https://github.com/Rust-GCC/gccrs/pull/4749 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 +++----------- .../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 b478a8d48..b6dd650e6 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 6f03f5758..e3cd70373 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 21bb686d4..cf8b06037 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 40df7a08f..cea7ae647 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 a12343e45..498f99c4a 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 f7d33ffc4..c800f2c30 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 c3ec4362b..4ca56d139 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 e8bf1c991..750c586a0 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 78780f3cc..a175ff670 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 52831e26e..e3262b947 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 2e4fcee9c..c8eb302e7 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 514ddbac4..a5c4c7c13 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 e372744f6..2619ed58a 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 3309c919a..670619126 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 7cbe52af6..70a98866d 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 ff1e51eb2..cfc09becf 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 2a2751ada..b19a6411d 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 ab972d61e..2c1fe7596 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 08608b847..8cf7c2a88 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([.., ..]: ()) {} base-commit: 9d6f07245f228c8e24d92dbb117c476ec2870a6f -- 2.54.0