From: Yap Zhi Heng <yapz...@gmail.com>

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 <yapz...@gmail.com>
---
 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-visitor.cc             |  19 +-
 gcc/rust/ast/rust-ast-visitor.h              |   4 +
 gcc/rust/ast/rust-pattern.cc                 |  54 ++++-
 gcc/rust/ast/rust-pattern.h                  | 204 +++++++++++++++++--
 gcc/rust/expand/rust-cfg-strip.cc            |  36 +++-
 gcc/rust/expand/rust-cfg-strip.h             |   2 +
 gcc/rust/expand/rust-derive.h                |   2 +
 gcc/rust/hir/rust-ast-lower-base.cc          |   6 +
 gcc/rust/hir/rust-ast-lower-base.h           |   2 +
 gcc/rust/hir/rust-ast-lower-pattern.cc       |  23 ++-
 gcc/rust/parse/rust-parse-impl.h             |  72 ++++++-
 gcc/rust/resolve/rust-ast-resolve-base.cc    |   8 +
 gcc/rust/resolve/rust-ast-resolve-base.h     |   2 +
 gcc/rust/resolve/rust-ast-resolve-pattern.cc |  25 ++-
 17 files changed, 447 insertions(+), 42 deletions(-)

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<SlicePatternItems> clone_slice_pattern_items () const
+  {
+    return std::unique_ptr<SlicePatternItems> (
+      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<std::unique_ptr<Pattern>> patterns;
+
+public:
+  SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> 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<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+  const std::vector<std::unique_ptr<Pattern>> &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<std::unique_ptr<Pattern>> lower_patterns;
+  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))
+  {}
+
+  // 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<std::unique_ptr<Pattern>> &get_lower_patterns ()
+  {
+    return lower_patterns;
+  }
+  const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
+  {
+    return lower_patterns;
+  }
+
+  // TODO: seems kinda dodgy. Think of better way.
+  std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
+  {
+    return upper_patterns;
+  }
+  const std::vector<std::unique_ptr<Pattern>> &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<std::unique_ptr<Pattern>> items;
+  std::unique_ptr<SlicePatternItems> items;
   location_t locus;
   NodeId node_id;
 
 public:
   std::string as_string () const override;
 
-  SlicePattern (std::vector<std::unique_ptr<Pattern>> items, location_t locus)
+  SlicePattern (std::unique_ptr<SlicePatternItems> 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<std::unique_ptr<Pattern>> &get_items () { return items; }
-  const std::vector<std::unique_ptr<Pattern>> &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<std::unique_ptr<HIR::Pattern>> 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<HIR::Pattern> (item));
+    case AST::SlicePatternItems::SlicePatternItemType::NO_REST:
+      {
+       AST::SlicePatternItemsNoRest &ref
+         = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ());
+       for (auto &p : ref.get_patterns ())
+         {
+           HIR::Pattern *item = ASTLoweringPattern::translate (*p);
+           items.push_back (std::unique_ptr<HIR::Pattern> (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<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;
+  };
+
   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 (patterns), square_locus));
+       new AST::SlicePattern (std::move (items), square_locus));
     }
 
   // parse initial pattern (required)
-  std::unique_ptr<AST::Pattern> 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<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));
 
-  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<ManagedTokenSource>::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<std::unique_ptr<AST::Pattern>> ();
+         lexer.skip_token ();
+         t = lexer.peek_token ();
+         continue;
+       }
+
       // parse pattern (required)
       std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
       if (pattern == nullptr)
@@ -11003,7 +11040,7 @@ Parser<ManagedTokenSource>::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<ManagedTokenSource>::parse_slice_pattern ()
       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));
+    }
+
+  // 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 (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<AST::SlicePatternItemsNoRest &> (pattern.get_items ());
+
+       for (auto &p : ref.get_patterns ())
+         p->accept_vis (*this);
+      }
+      break;
+
+    case AST::SlicePatternItems::SlicePatternItemType::HAS_REST:
+      {
+       auto &ref
+         = static_cast<AST::SlicePatternItemsHasRest &> (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;
     }
 }
 
-- 
2.49.0

Reply via email to