From: Yap Zhi Heng Date: Wed, 30 Jul 2025 15:37:43 +0000 (+0800) Subject: gccrs: Add rest pattern support for AST::SlicePattern X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=a22c11304c40ed8895d00555fe91a33291ba7c67;p=thirdparty%2Fgcc.git gccrs: Add rest pattern support for AST::SlicePattern The main change can be found in ast/rust-pattern.h, which introduces 2 item types for AST::SlicePattern - one without rest pattern (SlicePatternItemsNoRest) & the other with it (SlicePatternItemsHasRest). This led to a number of cascading changes as seen in the changelog. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc: Add support for the 2 new classes. * ast/rust-ast-collector.h: Header file update for above. * ast/rust-ast-full-decls.h: Add forward decls for the 2 new classes. * ast/rust-ast-visitor.cc: Add visit support for the 2 new classes. * ast/rust-ast-visitor.h: Header file update for above. * ast/rust-pattern.cc: Implementation of certain methods for the 2 new classes. * ast/rust-pattern.h: Define the 2 new classes. Update SlicePattern to be able to hold 2 kinds of items - SlicePatternItemsNoRest or SlicePatternItemsRest. * expand/rust-cfg-strip.cc: Add support for the 2 new classes. * expand/rust-cfg-strip.h: Header file update for above. * expand/rust-derive.h: Add visits for the 2 new classes. * hir/rust-ast-lower-base.cc: Add visits for the 2 new classes. * hir/rust-ast-lower-base.h: Header file update for above. * hir/rust-ast-lower-pattern.cc: Update lowering of SlicePattern to support SlicePatternItemsNoRest. * parse/rust-parse-impl.h (parse_slice_pattern()): Add support for parsing DOT_DOT into respective SlicePatternItems. * resolve/rust-ast-resolve-base.cc: Add visits for the 2 new classes. * resolve/rust-ast-resolve-base.h: Header file update for above. * resolve/rust-ast-resolve-pattern.cc: Update SlicePattern resolution to support new classes. Signed-off-by: Yap Zhi Heng --- diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index b27a3af11e8..677c2472e6f 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -2717,11 +2717,35 @@ TokenCollector::visit (GroupedPattern &pattern) push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); } +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) { push (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ())); - visit_items_joined_by_separator (pattern.get_items (), COMMA); + visit (pattern.get_items ()); 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 767d211ddf3..9ffbfced47d 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -378,6 +378,8 @@ public: void visit (TuplePatternItemsRanged &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 eb1f3ea890c..1dfb25c4363 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -248,6 +248,8 @@ class TuplePatternItemsMultiple; class TuplePatternItemsRanged; class TuplePattern; class GroupedPattern; +class SlicePatternItemsNoRest; +class SlicePatternItemsHasRest; class SlicePattern; class AltPattern; diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index f752b3a8f15..88dc24b570c 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -1347,12 +1347,27 @@ DefaultASTVisitor::visit (AST::GroupedPattern &pattern) } void -DefaultASTVisitor::visit (AST::SlicePattern &pattern) +DefaultASTVisitor::visit (AST::SlicePatternItemsNoRest &items) { - for (auto &item : pattern.get_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 ()); +} + void DefaultASTVisitor::visit (AST::AltPattern &pattern) { diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index 020400dde3f..a5469cccb42 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -212,6 +212,8 @@ public: virtual void visit (TuplePatternItemsRanged &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; @@ -386,6 +388,8 @@ public: virtual void visit (AST::TuplePatternItemsRanged &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 62bf6f2c5e8..15ab0b75741 100644 --- a/gcc/rust/ast/rust-pattern.cc +++ b/gcc/rust/ast/rust-pattern.cc @@ -327,16 +327,52 @@ GroupedExpr::as_string () const } std::string -SlicePattern::as_string () const +SlicePatternItemsNoRest::as_string () const { - std::string str ("SlicePattern: "); + std::string str; - for (const auto &pattern : items) + for (const auto &pattern : patterns) str += "\n " + pattern->as_string (); return str; } +std::string +SlicePatternItemsHasRest::as_string () const +{ + std::string str; + + str += "\n Lower patterns: "; + if (lower_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &lower : lower_patterns) + str += "\n " + lower->as_string (); + } + + str += "\n Upper patterns: "; + if (upper_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &upper : upper_patterns) + str += "\n " + upper->as_string (); + } + + return str; +} + +std::string +SlicePattern::as_string () const +{ + return "SlicePattern: " + items->as_string (); +} + std::string AltPattern::as_string () const { @@ -366,6 +402,18 @@ 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 57c065ff695..4945ec4480d 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -1521,41 +1521,217 @@ protected: } }; +// Base abstract class representing patterns in a SlicePattern +class SlicePatternItems +{ +public: + enum SlicePatternItemType + { + NO_REST, + HAS_REST, + }; + + virtual ~SlicePatternItems () {} + + // TODO: should this store location data? + + // Unique pointer custom clone function + std::unique_ptr clone_slice_pattern_items () const + { + return std::unique_ptr ( + clone_slice_pattern_items_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual SlicePatternItemType get_pattern_type () const = 0; + +protected: + // pure virtual clone implementation + virtual SlicePatternItems *clone_slice_pattern_items_impl () const = 0; +}; + +// Class representing the patterns in a SlicePattern without `..` +class SlicePatternItemsNoRest : public SlicePatternItems +{ + std::vector> patterns; + +public: + SlicePatternItemsNoRest (std::vector> patterns) + : patterns (std::move (patterns)) + {} + + // Copy constructor with vector clone + SlicePatternItemsNoRest (SlicePatternItemsNoRest const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to vector clone + SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other) + { + patterns.clear (); + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default; + SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other) + = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::vector> &get_patterns () { return patterns; } + const std::vector> &get_patterns () const + { + return patterns; + } + + SlicePatternItemType get_pattern_type () const override + { + return SlicePatternItemType::NO_REST; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePatternItemsNoRest *clone_slice_pattern_items_impl () const override + { + return new SlicePatternItemsNoRest (*this); + } +}; + +// Class representing the patterns in a SlicePattern that contains a `..` +class SlicePatternItemsHasRest : public SlicePatternItems +{ + std::vector> lower_patterns; + std::vector> upper_patterns; + +public: + SlicePatternItemsHasRest ( + std::vector> lower_patterns, + std::vector> upper_patterns) + : lower_patterns (std::move (lower_patterns)), + upper_patterns (std::move (upper_patterns)) + {} + + // Copy constructor with vector clone + SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to clone + SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other) + { + lower_patterns.clear (); + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.clear (); + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default; + SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other) + = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::vector> &get_lower_patterns () + { + return lower_patterns; + } + const std::vector> &get_lower_patterns () const + { + return lower_patterns; + } + + // TODO: seems kinda dodgy. Think of better way. + std::vector> &get_upper_patterns () + { + return upper_patterns; + } + const std::vector> &get_upper_patterns () const + { + return upper_patterns; + } + + SlicePatternItemType get_pattern_type () const override + { + return SlicePatternItemType::HAS_REST; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePatternItemsHasRest *clone_slice_pattern_items_impl () const override + { + return new SlicePatternItemsHasRest (*this); + } +}; + // AST node representing patterns that can match slices and arrays class SlicePattern : public Pattern { - std::vector> items; + std::unique_ptr items; location_t locus; NodeId node_id; public: std::string as_string () const override; - SlicePattern (std::vector> items, location_t locus) + SlicePattern (std::unique_ptr items, location_t locus) : items (std::move (items)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} - // Copy constructor with vector clone + // Copy constructor requires clone SlicePattern (SlicePattern const &other) : locus (other.locus) { + // guard to prevent null dereference + rust_assert (other.items != nullptr); + node_id = other.node_id; - items.reserve (other.items.size ()); - for (const auto &e : other.items) - items.push_back (e->clone_pattern ()); + items = other.items->clone_slice_pattern_items (); } - // Overloaded assignment operator to vector clone + // Overloaded assignment operator to clone SlicePattern &operator= (SlicePattern const &other) { locus = other.locus; node_id = other.node_id; - items.clear (); - items.reserve (other.items.size ()); - for (const auto &e : other.items) - items.push_back (e->clone_pattern ()); + // guard to prevent null dereference + rust_assert (other.items != nullptr); + items = other.items->clone_slice_pattern_items (); return *this; } @@ -1568,10 +1744,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - std::vector> &get_items () { return items; } - const std::vector> &get_items () const + SlicePatternItems &get_items () { - return items; + rust_assert (items != nullptr); + return *items; } NodeId get_node_id () const override { return node_id; } diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index ac795f7259d..58d80716009 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -2478,19 +2478,43 @@ CfgStrip::visit (AST::GroupedPattern &pattern) } void -CfgStrip::visit (AST::SlicePattern &pattern) +CfgStrip::visit (AST::SlicePatternItemsNoRest &items) { - AST::DefaultASTVisitor::visit (pattern); + AST::DefaultASTVisitor::visit (items); // can't strip individual patterns, only sub-patterns - for (auto &item : pattern.get_items ()) + for (auto &pattern : items.get_patterns ()) { - if (item->is_marked_for_strip ()) - rust_error_at (item->get_locus (), + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus (), "cannot strip pattern in this position"); - // TODO: quit stripping now? or keep going? } } +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 4900ae893ed..767cf28a712 100644 --- a/gcc/rust/expand/rust-cfg-strip.h +++ b/gcc/rust/expand/rust-cfg-strip.h @@ -172,6 +172,8 @@ public: void visit (AST::TuplePatternItemsMultiple &tuple_items) override; void visit (AST::TuplePatternItemsRanged &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 297d0799122..283b4434dd3 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -231,6 +231,8 @@ private: virtual void visit (TuplePatternItemsRanged &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 9098a9fc6cf..09f4b930963 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -495,6 +495,12 @@ void ASTLoweringBase::visit (AST::GroupedPattern &) {} void +ASTLoweringBase::visit (AST::SlicePatternItemsNoRest &) +{} +void +ASTLoweringBase::visit (AST::SlicePatternItemsHasRest &) +{} +void ASTLoweringBase::visit (AST::SlicePattern &) {} void diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index 6437b2e9dbb..af21c40d5c5 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -236,6 +236,8 @@ public: virtual void visit (AST::TuplePatternItemsRanged &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; diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index bb5b93b2c49..b9d7b620aa2 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -321,10 +321,27 @@ void ASTLoweringPattern::visit (AST::SlicePattern &pattern) { std::vector> items; - for (auto &p : pattern.get_items ()) + + switch (pattern.get_items ().get_pattern_type ()) { - HIR::Pattern *item = ASTLoweringPattern::translate (*p); - items.push_back (std::unique_ptr (item)); + case AST::SlicePatternItems::SlicePatternItemType::NO_REST: + { + AST::SlicePatternItemsNoRest &ref + = static_cast (pattern.get_items ()); + for (auto &p : ref.get_patterns ()) + { + HIR::Pattern *item = ASTLoweringPattern::translate (*p); + items.push_back (std::unique_ptr (item)); + } + } + break; + case AST::SlicePatternItems::SlicePatternItemType::HAS_REST: + { + rust_error_at (pattern.get_locus (), + "lowering of slice patterns with rest elements are not " + "supported yet"); + } + break; } auto crate_num = mappings.get_current_crate (); diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 6d996ca6026..80b529c05e4 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -10962,27 +10962,47 @@ Parser::parse_slice_pattern () { location_t square_locus = lexer.peek_token ()->get_locus (); std::vector> patterns; + tl::optional>> upper_patterns + = tl::nullopt; + + // lambda function to determine which vector to push new patterns into + auto get_pattern_ref + = [&] () -> std::vector> & { + return upper_patterns.has_value () ? upper_patterns.value () : patterns; + }; + skip_token (LEFT_SQUARE); if (lexer.peek_token ()->get_id () == RIGHT_SQUARE) { skip_token (RIGHT_SQUARE); + std::unique_ptr items ( + new AST::SlicePatternItemsNoRest (std::move (patterns))); return std::unique_ptr ( - new AST::SlicePattern (std::move (patterns), square_locus)); + new AST::SlicePattern (std::move (items), square_locus)); } // parse initial pattern (required) - std::unique_ptr initial_pattern = parse_pattern (); - if (initial_pattern == nullptr) + if (lexer.peek_token ()->get_id () == DOT_DOT) { - Error error (lexer.peek_token ()->get_locus (), - "failed to parse initial pattern in slice pattern"); - add_error (std::move (error)); - - return nullptr; + lexer.skip_token (); + upper_patterns = std::vector> (); } + else + { + // Not a rest pattern `..`, parse normally + std::unique_ptr 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)); - patterns.push_back (std::move (initial_pattern)); + return nullptr; + } + + patterns.push_back (std::move (initial_pattern)); + } const_TokenPtr t = lexer.peek_token (); while (t->get_id () == COMMA) @@ -10993,6 +11013,23 @@ Parser::parse_slice_pattern () if (lexer.peek_token ()->get_id () == RIGHT_SQUARE) break; + if (lexer.peek_token ()->get_id () == DOT_DOT) + { + 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> (); + lexer.skip_token (); + t = lexer.peek_token (); + continue; + } + // parse pattern (required) std::unique_ptr pattern = parse_pattern (); if (pattern == nullptr) @@ -11003,7 +11040,7 @@ Parser::parse_slice_pattern () return nullptr; } - patterns.push_back (std::move (pattern)); + get_pattern_ref ().push_back (std::move (pattern)); t = lexer.peek_token (); } @@ -11013,8 +11050,21 @@ Parser::parse_slice_pattern () return nullptr; } + if (upper_patterns.has_value ()) + { + // Slice pattern with rest + std::unique_ptr items ( + new AST::SlicePatternItemsHasRest ( + std::move (patterns), std::move (upper_patterns.value ()))); + return std::unique_ptr ( + new AST::SlicePattern (std::move (items), square_locus)); + } + + // Rest-less slice pattern + std::unique_ptr items ( + new AST::SlicePatternItemsNoRest (std::move (patterns))); return std::unique_ptr ( - new AST::SlicePattern (std::move (patterns), square_locus)); + new AST::SlicePattern (std::move (items), square_locus)); } /* Parses an identifier pattern (pattern that binds a value matched to a diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc index 4890d8e519c..6b57c6d62a8 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc @@ -583,6 +583,14 @@ void ResolverBase::visit (AST::GroupedPattern &) {} +void +ResolverBase::visit (AST::SlicePatternItemsNoRest &) +{} + +void +ResolverBase::visit (AST::SlicePatternItemsHasRest &) +{} + void ResolverBase::visit (AST::SlicePattern &) {} diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index dce8e7bfc75..febfc6126d5 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -186,6 +186,8 @@ public: void visit (AST::TuplePatternItemsRanged &); void visit (AST::TuplePattern &); void visit (AST::GroupedPattern &); + void visit (AST::SlicePatternItemsNoRest &); + void visit (AST::SlicePatternItemsHasRest &); void visit (AST::SlicePattern &); void visit (AST::AltPattern &); diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc index fce45bcf1e6..3b80f9f0508 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc @@ -388,9 +388,30 @@ PatternDeclaration::visit (AST::RangePattern &pattern) void PatternDeclaration::visit (AST::SlicePattern &pattern) { - for (auto &p : pattern.get_items ()) + auto &items = pattern.get_items (); + switch (items.get_pattern_type ()) { - p->accept_vis (*this); + case AST::SlicePatternItems::SlicePatternItemType::NO_REST: + { + auto &ref + = static_cast (pattern.get_items ()); + + for (auto &p : ref.get_patterns ()) + p->accept_vis (*this); + } + break; + + case AST::SlicePatternItems::SlicePatternItemType::HAS_REST: + { + auto &ref + = static_cast (pattern.get_items ()); + + for (auto &p : ref.get_lower_patterns ()) + p->accept_vis (*this); + for (auto &p : ref.get_upper_patterns ()) + p->accept_vis (*this); + } + break; } }