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([.., ..]: ()) {}

Reply via email to