[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