From: Yap Zhi Heng <[email protected]>

This patch adds support for compiling rest patterns present in slice patterns
(e.g. `[1, .., 2]`). 006t.original output from compiling 
match-slicepattern-slice-2.rs
for first 2 match arms:

...
  if (RUSTTMP.3.len > 1 && *NON_LVALUE_EXPR <RUSTTMP.3.data> == 1)
    {
      {
                struct () RUSTTMP.4;
        {
                    struct () RUSTTMP.5;
          {
           ..
          }
        }
        goto <D.139>;
      }
    }
  if ((RUSTTMP.3.len > 1 && *NON_LVALUE_EXPR <RUSTTMP.3.data> == 0) && 
*(RUSTTMP.3.data + (sizetype) (RUSTTMP.3.len + 18446744073709551615) * 4) == 0)
    {
      {
                struct () RUSTTMP.6;
        {
                    struct () RUSTTMP.7;
          {
          }
        }
        goto <D.139>;
      }
    }
...

gcc/rust/ChangeLog:

        * hir/tree/rust-hir-pattern.h: Add SlicePatternItems base class and
        SlicePatternItemsNoRest/SlicePatternItemsHasRest derived classes.
        Update SlicePattern to hold patterns using the new classes.
        * hir/tree/rust-hir-full-decls.h: Declare new classes.
        * hir/tree/rust-hir.cc: Add visits for new classes.
        * hir/tree/rust-hir-visitor.h: Add visits for new classes.
        * hir/tree/rust-hir-visitor.cc: Implement visits for new classes.
        * hir/rust-hir-dump.h: Add visits for new classes.
        * hir/rust-hir-dump.cc: Implement Dump::visit for new classes.
        * hir/rust-ast-lower-base.h: Declare new 
lower_slice_pattern_no_rest/has_rest
        methods.
        * hir/rust-ast-lower-base.cc: Implement 
lower_slice_pattern_no_rest/has_rest
        to lower AST slice pattern items to HIR.
        * hir/rust-ast-lower-pattern.cc: Update ASTLoweringPattern::visit for
        SlicePattern to use new lowering methods.
        * backend/rust-compile-pattern.cc: Update CompilePatternCheckExpr::visit
        and CompilePatternBindings::visit for SlicePattern to handle
        SlicePatternItemsNoRest/HasRest.
        * checks/errors/borrowck/rust-bir-builder-pattern.cc: Update
        PatternBindingBuilder::visit for SlicePattern to iterate members 
correctly.
        * checks/errors/borrowck/rust-bir-builder-struct.h: Add visits for new
        classes.
        * checks/errors/borrowck/rust-function-collector.h: Add visits for new
        classes.
        * checks/errors/rust-const-checker.h: Add visits for new classes.
        * checks/errors/rust-const-checker.cc: Implement empty visits for new 
classes.
        * checks/errors/rust-hir-pattern-analysis.h: Add visits for new classes.
        * checks/errors/rust-hir-pattern-analysis.cc: Implement empty visits 
for new
        classes.
        * checks/errors/rust-unsafe-checker.h: Add visits for new classes.
        * checks/errors/rust-unsafe-checker.cc: Implement empty visits for new
        classes.
        * typecheck/rust-hir-type-check-pattern.cc: Update 
TypeCheckPattern::visit
        for SlicePattern to handle SlicePatternItemsNoRest/HasRest.

gcc/testsuite/ChangeLog:

        * rust/compile/slice_rest_pattern.rs: Removed -fsyntax-only.

Signed-off-by: Yap Zhi Heng <[email protected]>
---
 gcc/rust/backend/rust-compile-pattern.cc      | 290 ++++++++++++++----
 .../borrowck/rust-bir-builder-pattern.cc      |  29 +-
 .../errors/borrowck/rust-bir-builder-struct.h |   8 +
 .../errors/borrowck/rust-function-collector.h |   2 +
 gcc/rust/checks/errors/rust-const-checker.cc  |   8 +
 gcc/rust/checks/errors/rust-const-checker.h   |   2 +
 .../errors/rust-hir-pattern-analysis.cc       |   8 +
 .../checks/errors/rust-hir-pattern-analysis.h |   2 +
 gcc/rust/checks/errors/rust-unsafe-checker.cc |   8 +
 gcc/rust/checks/errors/rust-unsafe-checker.h  |   2 +
 gcc/rust/hir/rust-ast-lower-base.cc           |  35 +++
 gcc/rust/hir/rust-ast-lower-base.h            |   6 +
 gcc/rust/hir/rust-ast-lower-pattern.cc        |  13 +-
 gcc/rust/hir/rust-hir-dump.cc                 |  19 +-
 gcc/rust/hir/rust-hir-dump.h                  |   4 +
 gcc/rust/hir/tree/rust-hir-full-decls.h       |   2 +
 gcc/rust/hir/tree/rust-hir-pattern.h          | 179 +++++++++--
 gcc/rust/hir/tree/rust-hir-visitor.cc         |  19 +-
 gcc/rust/hir/tree/rust-hir-visitor.h          |   9 +
 gcc/rust/hir/tree/rust-hir.cc                 |  58 +++-
 .../typecheck/rust-hir-type-check-pattern.cc  |  68 +++-
 .../rust/compile/slice_rest_pattern.rs        |   3 +-
 .../torture/match-slicepattern-array-2.rs     |  27 ++
 .../torture/match-slicepattern-slice-2.rs     |  28 ++
 24 files changed, 731 insertions(+), 98 deletions(-)
 create mode 100644 
gcc/testsuite/rust/execute/torture/match-slicepattern-array-2.rs
 create mode 100644 
gcc/testsuite/rust/execute/torture/match-slicepattern-slice-2.rs

diff --git a/gcc/rust/backend/rust-compile-pattern.cc 
b/gcc/rust/backend/rust-compile-pattern.cc
index 577f8de9c93..e29dc92ea49 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -534,25 +534,14 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern 
&pattern)
               || lookup->get_kind () == TyTy::TypeKind::SLICE
               || lookup->get_kind () == TyTy::REF);
 
-  size_t array_element_index = 0;
+  // function ptr that points to either array_index_expression or
+  // slice_index_expression depending on the scrutinee's type
+  tree (*scrutinee_index_expr_func) (tree, tree, location_t) = nullptr;
+
   switch (lookup->get_kind ())
     {
     case TyTy::TypeKind::ARRAY:
-      for (auto &pattern_member : pattern.get_items ())
-       {
-         tree array_index_tree
-           = Backend::size_constant_expression (array_element_index++);
-         tree element_expr
-           = Backend::array_index_expression (match_scrutinee_expr,
-                                              array_index_tree,
-                                              pattern.get_locus ());
-         tree check_expr_sub
-           = CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
-                                               ctx);
-         check_expr = Backend::arithmetic_or_logical_expression (
-           ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
-           check_expr_sub, pattern.get_locus ());
-       }
+      scrutinee_index_expr_func = Backend::array_index_expression;
       break;
     case TyTy::TypeKind::SLICE:
       rust_sorry_at (
@@ -562,25 +551,81 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern 
&pattern)
     case TyTy::TypeKind::REF:
       {
        rust_assert (RS_DST_FLAG_P (TREE_TYPE (match_scrutinee_expr)));
+       scrutinee_index_expr_func = Backend::slice_index_expression;
        tree size_field
          = Backend::struct_field_expression (match_scrutinee_expr, 1,
                                              pattern.get_locus ());
 
-       // First compare the size
-       check_expr = Backend::comparison_expression (
-         ComparisonOperator::EQUAL, size_field,
-         build_int_cst (size_type_node, pattern.get_items ().size ()),
-         pattern.get_locus ());
+       // for slices, generate a dynamic size comparison expression tree
+       // because size checking is done at runtime.
+       switch (pattern.get_items ().get_item_type ())
+         {
+         case HIR::SlicePatternItems::ItemType::NO_REST:
+           {
+             auto &items = static_cast<HIR::SlicePatternItemsNoRest &> (
+               pattern.get_items ());
+             check_expr = Backend::comparison_expression (
+               ComparisonOperator::EQUAL, size_field,
+               build_int_cst (size_type_node, items.get_patterns ().size ()),
+               pattern.get_locus ());
+           }
+           break;
+         case HIR::SlicePatternItems::ItemType::HAS_REST:
+           {
+             auto &items = static_cast<HIR::SlicePatternItemsHasRest &> (
+               pattern.get_items ());
+             auto pattern_min_cap = items.get_lower_patterns ().size ()
+                                    + items.get_upper_patterns ().size ();
+             check_expr = Backend::comparison_expression (
+               ComparisonOperator::GREATER_OR_EQUAL, size_field,
+               build_int_cst (size_type_node, pattern_min_cap),
+               pattern.get_locus ());
+           }
+           break;
+         }
+      }
+      break;
+    default:
+      rust_unreachable ();
+    }
+
+  rust_assert (scrutinee_index_expr_func != nullptr);
 
-       // Then compare each element in the slice pattern
-       for (auto &pattern_member : pattern.get_items ())
+  // Generate tree to compare every element within array/slice
+  size_t element_index = 0;
+  switch (pattern.get_items ().get_item_type ())
+    {
+    case HIR::SlicePatternItems::ItemType::NO_REST:
+      {
+       auto &items
+         = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
+       for (auto &pattern_member : items.get_patterns ())
          {
-           tree slice_index_tree
-             = Backend::size_constant_expression (array_element_index++);
+           tree index_tree
+             = Backend::size_constant_expression (element_index++);
            tree element_expr
-             = Backend::slice_index_expression (match_scrutinee_expr,
-                                                slice_index_tree,
-                                                pattern.get_locus ());
+             = scrutinee_index_expr_func (match_scrutinee_expr, index_tree,
+                                          pattern.get_locus ());
+           tree check_expr_sub
+             = CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
+                                                 ctx);
+           check_expr = Backend::arithmetic_or_logical_expression (
+             ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+             check_expr_sub, pattern.get_locus ());
+         }
+       break;
+      }
+    case HIR::SlicePatternItems::ItemType::HAS_REST:
+      {
+       auto &items
+         = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
+       for (auto &pattern_member : items.get_lower_patterns ())
+         {
+           tree index_tree
+             = Backend::size_constant_expression (element_index++);
+           tree element_expr
+             = scrutinee_index_expr_func (match_scrutinee_expr, index_tree,
+                                          pattern.get_locus ());
            tree check_expr_sub
              = CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
                                                  ctx);
@@ -588,10 +633,71 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern 
&pattern)
              ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
              check_expr_sub, pattern.get_locus ());
          }
+
+       // handle codegen for upper patterns differently for both types
+       switch (lookup->get_kind ())
+         {
+         case TyTy::TypeKind::ARRAY:
+           {
+             // for array type scrutinee, we can simply get the capacity as a
+             // const and calculate how many elements to skip
+             auto array_ty = static_cast<TyTy::ArrayType *> (lookup);
+             auto cap_tree = array_ty->get_capacity ()->get_value ();
+             size_t cap_wi = (size_t) wi::to_wide (cap_tree).to_uhwi ();
+             element_index = cap_wi - items.get_upper_patterns ().size ();
+             for (auto &pattern_member : items.get_upper_patterns ())
+               {
+                 tree index_tree
+                   = Backend::size_constant_expression (element_index++);
+                 tree element_expr
+                   = scrutinee_index_expr_func (match_scrutinee_expr,
+                                                index_tree,
+                                                pattern.get_locus ());
+                 tree check_expr_sub
+                   = CompilePatternCheckExpr::Compile (*pattern_member,
+                                                       element_expr, ctx);
+                 check_expr = Backend::arithmetic_or_logical_expression (
+                   ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+                   check_expr_sub, pattern.get_locus ());
+               }
+           }
+           break;
+         case TyTy::TypeKind::REF:
+           {
+             // for slice type scrutinee, size is dyanamic, so number of
+             // elements to skip is calculated during runtime
+             tree slice_size
+               = Backend::struct_field_expression (match_scrutinee_expr, 1,
+                                                   pattern.get_locus ());
+             tree upper_patterns_size = Backend::size_constant_expression (
+               items.get_upper_patterns ().size ());
+             tree index_tree = Backend::arithmetic_or_logical_expression (
+               ArithmeticOrLogicalOperator::SUBTRACT, slice_size,
+               upper_patterns_size, pattern.get_locus ());
+             for (auto &pattern_member : items.get_upper_patterns ())
+               {
+                 tree element_expr
+                   = scrutinee_index_expr_func (match_scrutinee_expr,
+                                                index_tree,
+                                                pattern.get_locus ());
+                 tree check_expr_sub
+                   = CompilePatternCheckExpr::Compile (*pattern_member,
+                                                       element_expr, ctx);
+                 check_expr = Backend::arithmetic_or_logical_expression (
+                   ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+                   check_expr_sub, pattern.get_locus ());
+                 index_tree = Backend::arithmetic_or_logical_expression (
+                   ArithmeticOrLogicalOperator::ADD, index_tree,
+                   Backend::size_constant_expression (1),
+                   pattern.get_locus ());
+               }
+           }
+           break;
+         default:
+           rust_unreachable ();
+         }
       }
       break;
-    default:
-      rust_unreachable ();
     }
 }
 
@@ -932,43 +1038,121 @@ CompilePatternBindings::visit (HIR::SlicePattern 
&pattern)
               || lookup->get_kind () == TyTy::TypeKind::SLICE
               || lookup->get_kind () == TyTy::REF);
 
-  size_t array_element_index = 0;
+  // function ptr that points to either array_index_expression or
+  // slice_index_expression depending on the scrutinee's type
+  tree (*scrutinee_index_expr_func) (tree, tree, location_t) = nullptr;
+
   switch (lookup->get_kind ())
     {
     case TyTy::TypeKind::ARRAY:
-      for (auto &pattern_member : pattern.get_items ())
-       {
-         tree array_index_tree
-           = Backend::size_constant_expression (array_element_index++);
-         tree element_expr
-           = Backend::array_index_expression (match_scrutinee_expr,
-                                              array_index_tree,
-                                              pattern.get_locus ());
-         CompilePatternBindings::Compile (*pattern_member, element_expr, ctx);
-       }
+      scrutinee_index_expr_func = Backend::array_index_expression;
       break;
     case TyTy::TypeKind::SLICE:
-      rust_sorry_at (
-       pattern.get_locus (),
-       "SlicePattern matching against non-ref slices are not yet supported");
+      rust_sorry_at (pattern.get_locus (),
+                    "SlicePattern matching against non-ref slices are "
+                    "not yet supported");
       break;
     case TyTy::TypeKind::REF:
+      scrutinee_index_expr_func = Backend::slice_index_expression;
+      break;
+    default:
+      rust_unreachable ();
+    }
+
+  rust_assert (scrutinee_index_expr_func != nullptr);
+
+  size_t element_index = 0;
+
+  switch (pattern.get_items ().get_item_type ())
+    {
+    case HIR::SlicePatternItems::ItemType::NO_REST:
       {
-       for (auto &pattern_member : pattern.get_items ())
+       auto &items
+         = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
+       for (auto &pattern_member : items.get_patterns ())
          {
-           tree slice_index_tree
-             = Backend::size_constant_expression (array_element_index++);
+           tree index_tree
+             = Backend::size_constant_expression (element_index++);
            tree element_expr
-             = Backend::slice_index_expression (match_scrutinee_expr,
-                                                slice_index_tree,
-                                                pattern.get_locus ());
+             = scrutinee_index_expr_func (match_scrutinee_expr, index_tree,
+                                          pattern.get_locus ());
            CompilePatternBindings::Compile (*pattern_member, element_expr,
                                             ctx);
          }
-       break;
       }
-    default:
-      rust_unreachable ();
+      break;
+    case HIR::SlicePatternItems::ItemType::HAS_REST:
+      {
+       auto &items
+         = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
+       for (auto &pattern_member : items.get_lower_patterns ())
+         {
+           tree index_tree
+             = Backend::size_constant_expression (element_index++);
+           tree element_expr
+             = scrutinee_index_expr_func (match_scrutinee_expr, index_tree,
+                                          pattern.get_locus ());
+           CompilePatternBindings::Compile (*pattern_member, element_expr,
+                                            ctx);
+         }
+
+       // handle codegen for upper patterns differently for both types
+       switch (lookup->get_kind ())
+         {
+         case TyTy::TypeKind::ARRAY:
+           {
+             auto array_ty = static_cast<TyTy::ArrayType *> (lookup);
+             auto cap_tree = array_ty->get_capacity ()->get_value ();
+             size_t cap_wi = (size_t) wi::to_wide (cap_tree).to_uhwi ();
+             element_index = cap_wi - items.get_upper_patterns ().size ();
+             for (auto &pattern_member : items.get_upper_patterns ())
+               {
+                 tree index_tree
+                   = Backend::size_constant_expression (element_index++);
+                 tree element_expr
+                   = scrutinee_index_expr_func (match_scrutinee_expr,
+                                                index_tree,
+                                                pattern.get_locus ());
+                 CompilePatternBindings::Compile (*pattern_member,
+                                                  element_expr, ctx);
+               }
+           }
+           break;
+         case TyTy::TypeKind::SLICE:
+           rust_sorry_at (pattern.get_locus (),
+                          "SlicePattern matching against non-ref slices are "
+                          "not yet supported");
+           break;
+         case TyTy::TypeKind::REF:
+           {
+             tree slice_size
+               = Backend::struct_field_expression (match_scrutinee_expr, 1,
+                                                   pattern.get_locus ());
+             tree upper_patterns_size = Backend::size_constant_expression (
+               items.get_upper_patterns ().size ());
+             tree index_tree = Backend::arithmetic_or_logical_expression (
+               ArithmeticOrLogicalOperator::SUBTRACT, slice_size,
+               upper_patterns_size, pattern.get_locus ());
+             for (auto &pattern_member : items.get_upper_patterns ())
+               {
+                 tree element_expr
+                   = scrutinee_index_expr_func (match_scrutinee_expr,
+                                                index_tree,
+                                                pattern.get_locus ());
+                 CompilePatternBindings::Compile (*pattern_member,
+                                                  element_expr, ctx);
+                 index_tree = Backend::arithmetic_or_logical_expression (
+                   ArithmeticOrLogicalOperator::ADD, index_tree,
+                   Backend::size_constant_expression (1),
+                   pattern.get_locus ());
+               }
+           }
+           break;
+         default:
+           rust_unreachable ();
+         }
+      }
+      break;
     }
 }
 
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
index 18f9584a4f0..e78d7505094 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
@@ -70,11 +70,34 @@ PatternBindingBuilder::visit (HIR::SlicePattern &pattern)
     return ty->as<TyTy::SliceType> ()->get_element_type ();
   });
 
-  // Regions are unchnaged.
+  // Regions are unchanged.
 
-  for (auto &item : pattern.get_items ())
+  switch (pattern.get_items ().get_item_type ())
     {
-      item->accept_vis (*this);
+    case HIR::SlicePatternItems::NO_REST:
+      {
+       auto &items
+         = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
+       for (auto &member : items.get_patterns ())
+         {
+           member->accept_vis (*this);
+         }
+       break;
+      }
+    case HIR::SlicePatternItems::HAS_REST:
+      {
+       auto &items
+         = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
+       for (auto &member : items.get_lower_patterns ())
+         {
+           member->accept_vis (*this);
+         }
+       for (auto &member : items.get_upper_patterns ())
+         {
+           member->accept_vis (*this);
+         }
+       break;
+      }
     }
 }
 
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
index f05dd6ceb1b..6cb87c7568a 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
@@ -246,6 +246,14 @@ protected:
     rust_unreachable ();
   }
   void visit (HIR::TuplePattern &pattern) override { rust_unreachable (); }
+  void visit (HIR::SlicePatternItemsNoRest &tuple_items) override
+  {
+    rust_unreachable ();
+  }
+  void visit (HIR::SlicePatternItemsHasRest &tuple_items) override
+  {
+    rust_unreachable ();
+  }
   void visit (HIR::SlicePattern &pattern) override { rust_unreachable (); }
   void visit (HIR::AltPattern &pattern) override { rust_unreachable (); }
   void visit (HIR::EmptyStmt &stmt) override { rust_unreachable (); }
diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h 
b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
index f4a11702a85..63f2a95f4bf 100644
--- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
@@ -176,6 +176,8 @@ public:
   void visit (HIR::TuplePatternItemsNoRest &tuple_items) override {}
   void visit (HIR::TuplePatternItemsHasRest &tuple_items) override {}
   void visit (HIR::TuplePattern &pattern) override {}
+  void visit (HIR::SlicePatternItemsNoRest &tuple_items) override {}
+  void visit (HIR::SlicePatternItemsHasRest &tuple_items) override {}
   void visit (HIR::SlicePattern &pattern) override {}
   void visit (HIR::AltPattern &pattern) override {}
   void visit (HIR::EmptyStmt &stmt) override {}
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc 
b/gcc/rust/checks/errors/rust-const-checker.cc
index 845e5b68187..782d6940bbe 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -836,6 +836,14 @@ void
 ConstChecker::visit (TuplePattern &)
 {}
 
+void
+ConstChecker::visit (SlicePatternItemsNoRest &)
+{}
+
+void
+ConstChecker::visit (SlicePatternItemsHasRest &)
+{}
+
 void
 ConstChecker::visit (SlicePattern &)
 {}
diff --git a/gcc/rust/checks/errors/rust-const-checker.h 
b/gcc/rust/checks/errors/rust-const-checker.h
index 66138bdc851..d464b7b9fce 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -186,6 +186,8 @@ private:
   virtual void visit (TuplePatternItemsNoRest &tuple_items) override;
   virtual void visit (TuplePatternItemsHasRest &tuple_items) override;
   virtual void visit (TuplePattern &pattern) override;
+  virtual void visit (SlicePatternItemsNoRest &items) override;
+  virtual void visit (SlicePatternItemsHasRest &items) override;
   virtual void visit (SlicePattern &pattern) override;
   virtual void visit (AltPattern &pattern) override;
   virtual void visit (EmptyStmt &stmt) override;
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc 
b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index 7fe7f029f2a..290087c573f 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -663,6 +663,14 @@ void
 PatternChecker::visit (TuplePattern &)
 {}
 
+void
+PatternChecker::visit (SlicePatternItemsNoRest &)
+{}
+
+void
+PatternChecker::visit (SlicePatternItemsHasRest &)
+{}
+
 void
 PatternChecker::visit (SlicePattern &)
 {}
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h 
b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
index 6aefaeca63f..d75e900f2be 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
@@ -159,6 +159,8 @@ private:
   virtual void visit (TuplePatternItemsNoRest &tuple_items) override;
   virtual void visit (TuplePatternItemsHasRest &tuple_items) override;
   virtual void visit (TuplePattern &pattern) override;
+  virtual void visit (SlicePatternItemsNoRest &items) override;
+  virtual void visit (SlicePatternItemsHasRest &items) override;
   virtual void visit (SlicePattern &pattern) override;
   virtual void visit (AltPattern &pattern) override;
   virtual void visit (EmptyStmt &stmt) override;
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc 
b/gcc/rust/checks/errors/rust-unsafe-checker.cc
index 41ed698db77..607d20fa11f 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -949,6 +949,14 @@ void
 UnsafeChecker::visit (TuplePattern &)
 {}
 
+void
+UnsafeChecker::visit (SlicePatternItemsNoRest &)
+{}
+
+void
+UnsafeChecker::visit (SlicePatternItemsHasRest &)
+{}
+
 void
 UnsafeChecker::visit (SlicePattern &)
 {}
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h 
b/gcc/rust/checks/errors/rust-unsafe-checker.h
index 4c884ad6b04..420668f46ed 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -167,6 +167,8 @@ private:
   virtual void visit (TuplePatternItemsNoRest &tuple_items) override;
   virtual void visit (TuplePatternItemsHasRest &tuple_items) override;
   virtual void visit (TuplePattern &pattern) override;
+  virtual void visit (SlicePatternItemsNoRest &items) override;
+  virtual void visit (SlicePatternItemsHasRest &items) override;
   virtual void visit (SlicePattern &pattern) override;
   virtual void visit (AltPattern &pattern) override;
   virtual void visit (EmptyStmt &stmt) override;
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc 
b/gcc/rust/hir/rust-ast-lower-base.cc
index f3ae3ce71a3..e32918e8e85 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -906,6 +906,41 @@ 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 e86aacb216a..a188e178526 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -322,6 +322,12 @@ protected:
   std::unique_ptr<TuplePatternItems>
   lower_tuple_pattern_ranged (AST::TuplePatternItemsRanged &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 f1b3ba8cfad..6933c2dca83 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -322,23 +322,22 @@ ASTLoweringPattern::visit (AST::ReferencePattern &pattern)
 void
 ASTLoweringPattern::visit (AST::SlicePattern &pattern)
 {
-  std::vector<std::unique_ptr<HIR::Pattern>> items;
+  std::unique_ptr<HIR::SlicePatternItems> items;
 
   switch (pattern.get_items ().get_pattern_type ())
     {
     case AST::SlicePatternItems::SlicePatternItemType::NO_REST:
       {
-       AST::SlicePatternItemsNoRest &ref
+       auto &ref
          = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ());
-       for (auto &p : ref.get_patterns ())
-         items.emplace_back (ASTLoweringPattern::translate (*p));
+       items = ASTLoweringBase::lower_slice_pattern_no_rest (ref);
       }
       break;
     case AST::SlicePatternItems::SlicePatternItemType::HAS_REST:
       {
-       rust_error_at (pattern.get_locus (),
-                      "lowering of slice patterns with rest elements are not "
-                      "supported yet");
+       auto &ref
+         = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ());
+       items = ASTLoweringBase::lower_slice_pattern_has_rest (ref);
       }
       break;
     }
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index b5c2bcf24fe..49ce1437899 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -2362,12 +2362,29 @@ Dump::visit (TuplePattern &e)
   end ("TuplePattern");
 }
 
+void
+Dump::visit (SlicePatternItemsNoRest &e)
+{
+  begin ("SlicePatternItemsNoRest");
+  visit_collection ("patterns", e.get_patterns ());
+  end ("SlicePatternItemsNoRest");
+}
+
+void
+Dump::visit (SlicePatternItemsHasRest &e)
+{
+  begin ("SlicePatternItemsHasRest");
+  visit_collection ("lower_patterns", e.get_lower_patterns ());
+  visit_collection ("upper_patterns", e.get_upper_patterns ());
+  end ("SlicePatternItemsHasRest");
+}
+
 void
 Dump::visit (SlicePattern &e)
 {
   begin ("SlicePattern");
   do_mappings (e.get_mappings ());
-  visit_collection ("items", e.get_items ());
+  visit_field ("items", e.get_items ());
   end ("SlicePattern");
 }
 
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
index 0202210db87..4dfc8859393 100644
--- a/gcc/rust/hir/rust-hir-dump.h
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -230,7 +230,11 @@ private:
   virtual void visit (TuplePatternItemsNoRest &) override;
   virtual void visit (TuplePatternItemsHasRest &) override;
   virtual void visit (TuplePattern &) override;
+
+  virtual void visit (SlicePatternItemsNoRest &) override;
+  virtual void visit (SlicePatternItemsHasRest &) override;
   virtual void visit (SlicePattern &) override;
+
   virtual void visit (AltPattern &) override;
 
   virtual void visit (EmptyStmt &) override;
diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h 
b/gcc/rust/hir/tree/rust-hir-full-decls.h
index b52ccb40286..aec2f362e44 100644
--- a/gcc/rust/hir/tree/rust-hir-full-decls.h
+++ b/gcc/rust/hir/tree/rust-hir-full-decls.h
@@ -206,6 +206,8 @@ class TuplePatternItems;
 class TuplePatternItemsNoRest;
 class TuplePatternItemsHasRest;
 class TuplePattern;
+class SlicePatternItemsNoRest;
+class SlicePatternItemsHasRest;
 class SlicePattern;
 class AltPattern;
 
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h 
b/gcc/rust/hir/tree/rust-hir-pattern.h
index 2a2965875f8..e3581dc5c8c 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -1241,10 +1241,161 @@ protected:
   }
 };
 
+// Base abstract class representing SlicePattern patterns
+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 override = 0;
+};
+
+// Class representing patterns within a SlicePattern, without a rest pattern
+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 (HIRFullVisitor &vis) override;
+
+  ItemType get_item_type () const override { return ItemType::NO_REST; }
+
+  std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+  const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
+  {
+    return patterns;
+  }
+
+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 patterns within a SlicePattern, with a rest pattern
+// included
+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 ());
+
+    lower_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 (HIRFullVisitor &vis) override;
+
+  ItemType get_item_type () const override { return ItemType::HAS_REST; }
+
+  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;
+  }
+
+  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;
+  }
+
+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);
+  }
+};
+
 // HIR 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;
   Analysis::NodeMapping mappings;
 
@@ -1252,30 +1403,23 @@ public:
   std::string as_string () const override;
 
   SlicePattern (Analysis::NodeMapping mappings,
-               std::vector<std::unique_ptr<Pattern>> items, location_t locus)
+               std::unique_ptr<SlicePatternItems> items, location_t locus)
     : items (std::move (items)), locus (locus), mappings (mappings)
   {}
 
-  // Copy constructor with vector clone
+  // Copy constructor requires clone
   SlicePattern (SlicePattern const &other)
-    : locus (other.locus), mappings (other.mappings)
-  {
-    items.reserve (other.items.size ());
-    for (const auto &e : other.items)
-      items.push_back (e->clone_pattern ());
-  }
+    : items (other.items->clone_slice_pattern_items ()), locus (other.locus),
+      mappings (other.mappings)
+  {}
 
   // Overloaded assignment operator to vector clone
   SlicePattern &operator= (SlicePattern const &other)
   {
+    items = other.items->clone_slice_pattern_items ();
     locus = other.locus;
     mappings = other.mappings;
 
-    items.clear ();
-    items.reserve (other.items.size ());
-    for (const auto &e : other.items)
-      items.push_back (e->clone_pattern ());
-
     return *this;
   }
 
@@ -1283,11 +1427,8 @@ public:
   SlicePattern (SlicePattern &&other) = default;
   SlicePattern &operator= (SlicePattern &&other) = default;
 
-  std::vector<std::unique_ptr<Pattern>> &get_items () { return items; }
-  const std::vector<std::unique_ptr<Pattern>> &get_items () const
-  {
-    return items;
-  }
+  SlicePatternItems &get_items () { return *items; }
+  const SlicePatternItems &get_items () const { return *items; }
 
   location_t get_locus () const override { return locus; }
 
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.cc 
b/gcc/rust/hir/tree/rust-hir-visitor.cc
index 15db3f0d6df..1e201a5541e 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.cc
+++ b/gcc/rust/hir/tree/rust-hir-visitor.cc
@@ -1067,11 +1067,26 @@ DefaultHIRVisitor::walk (TuplePattern &pattern)
   pattern.get_items ().accept_vis (*this);
 }
 
+void
+DefaultHIRVisitor::walk (SlicePatternItemsNoRest &items)
+{
+  for (auto &pattern : items.get_patterns ())
+    pattern->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (SlicePatternItemsHasRest &items)
+{
+  for (auto &lower : items.get_lower_patterns ())
+    lower->accept_vis (*this);
+  for (auto &upper : items.get_upper_patterns ())
+    upper->accept_vis (*this);
+}
+
 void
 DefaultHIRVisitor::walk (SlicePattern &pattern)
 {
-  for (auto &item : pattern.get_items ())
-    item->accept_vis (*this);
+  pattern.get_items ().accept_vis (*this);
 }
 
 void
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h 
b/gcc/rust/hir/tree/rust-hir-visitor.h
index d0bb484b41e..77760b0141d 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.h
+++ b/gcc/rust/hir/tree/rust-hir-visitor.h
@@ -138,6 +138,8 @@ public:
   virtual void visit (TuplePatternItemsNoRest &tuple_items) = 0;
   virtual void visit (TuplePatternItemsHasRest &tuple_items) = 0;
   virtual void visit (TuplePattern &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;
   virtual void visit (EmptyStmt &stmt) = 0;
@@ -311,6 +313,8 @@ public:
   virtual void visit (TuplePatternItemsNoRest &node) override { walk (node); }
   virtual void visit (TuplePatternItemsHasRest &node) override { walk (node); }
   virtual void visit (TuplePattern &node) override { walk (node); }
+  virtual void visit (SlicePatternItemsNoRest &node) override { walk (node); }
+  virtual void visit (SlicePatternItemsHasRest &node) override { walk (node); }
   virtual void visit (SlicePattern &node) override { walk (node); }
   virtual void visit (AltPattern &node) override { walk (node); }
   virtual void visit (EmptyStmt &node) override { walk (node); }
@@ -444,6 +448,8 @@ protected:
   virtual void walk (TuplePatternItemsNoRest &) final;
   virtual void walk (TuplePatternItemsHasRest &) final;
   virtual void walk (TuplePattern &) final;
+  virtual void walk (SlicePatternItemsNoRest &) final;
+  virtual void walk (SlicePatternItemsHasRest &) final;
   virtual void walk (SlicePattern &) final;
   virtual void walk (AltPattern &) final;
   virtual void walk (EmptyStmt &) final;
@@ -593,6 +599,9 @@ public:
   virtual void visit (TuplePatternItemsNoRest &) override {}
   virtual void visit (TuplePatternItemsHasRest &) override {}
   virtual void visit (TuplePattern &) override {}
+
+  virtual void visit (SlicePatternItemsNoRest &) override {}
+  virtual void visit (SlicePatternItemsHasRest &) override {}
   virtual void visit (SlicePattern &) override {}
   virtual void visit (AltPattern &) override {}
 
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 39c0e2e1c29..7aad4ef2730 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -2386,11 +2386,11 @@ RangePatternBoundLiteral::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 ();
     }
@@ -2398,6 +2398,46 @@ SlicePattern::as_string () const
   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
 {
@@ -4505,6 +4545,18 @@ TuplePattern::accept_vis (HIRFullVisitor &vis)
   vis.visit (*this);
 }
 
+void
+SlicePatternItemsNoRest::accept_vis (HIRFullVisitor &vis)
+{
+  vis.visit (*this);
+}
+
+void
+SlicePatternItemsHasRest::accept_vis (HIRFullVisitor &vis)
+{
+  vis.visit (*this);
+}
+
 void
 SlicePattern::accept_vis (HIRFullVisitor &vis)
 {
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc 
b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index b34679eb6b4..5a2dde85e18 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -651,14 +651,44 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern)
            break;
          }
        auto cap_wi = wi::to_wide (cap).to_uhwi ();
-       if (cap_wi != pattern.get_items ().size ())
+
+       // size check during compile time
+       switch (pattern.get_items ().get_item_type ())
          {
-           rust_error_at (pattern.get_locus (), ErrorCode::E0527,
-                          "pattern requires %lu elements but array has %lu",
-                          (unsigned long) pattern.get_items ().size (),
-                          (unsigned long) cap_wi);
+         case HIR::SlicePatternItems::ItemType::NO_REST:
+           {
+             auto &ref = static_cast<HIR::SlicePatternItemsNoRest &> (
+               pattern.get_items ());
+             if (cap_wi != ref.get_patterns ().size ())
+               {
+                 rust_error_at (
+                   pattern.get_locus (), ErrorCode::E0527,
+                   "pattern requires %lu elements but array has %lu",
+                   (unsigned long) ref.get_patterns ().size (),
+                   (unsigned long) cap_wi);
+                 break;
+               }
+           }
+           break;
+         case HIR::SlicePatternItems::ItemType::HAS_REST:
+           {
+             auto &ref = static_cast<HIR::SlicePatternItemsHasRest &> (
+               pattern.get_items ());
+             auto pattern_min_cap = ref.get_lower_patterns ().size ()
+                                    + ref.get_upper_patterns ().size ();
+
+             if (cap_wi < pattern_min_cap)
+               {
+                 rust_error_at (
+                   pattern.get_locus (), ErrorCode::E0528,
+                   "pattern requires at least %lu elements but array has %lu",
+                   (unsigned long) pattern_min_cap, (unsigned long) cap_wi);
+                 break;
+               }
+           }
            break;
          }
+
        break;
       }
     case TyTy::SLICE:
@@ -694,10 +724,32 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern)
   infered->set_ref (pattern.get_mappings ().get_hirid ());
 
   // Type check every item in the SlicePattern against parent's element ty
-  // TODO update this after adding support for RestPattern in SlicePattern
-  for (const auto &item : pattern.get_items ())
+  switch (pattern.get_items ().get_item_type ())
     {
-      TypeCheckPattern::Resolve (*item, parent_element_ty);
+    case HIR::SlicePatternItems::ItemType::NO_REST:
+      {
+       auto &ref
+         = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
+       for (const auto &pattern_member : ref.get_patterns ())
+         {
+           TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
+         }
+       break;
+      }
+    case HIR::SlicePatternItems::ItemType::HAS_REST:
+      {
+       auto &ref
+         = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
+       for (const auto &pattern_member : ref.get_lower_patterns ())
+         {
+           TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
+         }
+       for (const auto &pattern_member : ref.get_upper_patterns ())
+         {
+           TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
+         }
+       break;
+      }
     }
 }
 
diff --git a/gcc/testsuite/rust/compile/slice_rest_pattern.rs 
b/gcc/testsuite/rust/compile/slice_rest_pattern.rs
index c27a8dd777e..bb3c414173a 100644
--- a/gcc/testsuite/rust/compile/slice_rest_pattern.rs
+++ b/gcc/testsuite/rust/compile/slice_rest_pattern.rs
@@ -1,5 +1,4 @@
-// { dg-options "-fsyntax-only" }
-fn foo(a: &[u32]) {
+pub fn foo(a: &[u32]) {
     match a {
         [first, ..] => {}
         [.., last] => {}
diff --git a/gcc/testsuite/rust/execute/torture/match-slicepattern-array-2.rs 
b/gcc/testsuite/rust/execute/torture/match-slicepattern-array-2.rs
new file mode 100644
index 00000000000..c6e77627b4d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-slicepattern-array-2.rs
@@ -0,0 +1,27 @@
+// { dg-output "correct\r*" }
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+    let a = [0, 4, 5, 6, 1];
+    let mut ret = 1;
+
+    match a {
+        [1, .., b] => {
+            /* should not take this path */
+            unsafe { puts("wrong\0" as *const str as *const i8) }
+        }
+        [0, .., 0] => {
+            /* should not take this path */
+            unsafe { puts("wrong\0" as *const str as *const i8) }
+        },
+        [0, .., b] => {
+            ret -= b;
+            unsafe { puts("correct\0" as *const str as *const i8) }
+        },
+        _ => {}
+    }
+
+    ret
+}
diff --git a/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-2.rs 
b/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-2.rs
new file mode 100644
index 00000000000..2fdffbb29f9
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-2.rs
@@ -0,0 +1,28 @@
+// { dg-output "correct\r*" }
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+    let arr = [0, 4, 5, 6, 1];
+    let a: &[i32] = &arr;
+    let mut ret = 1;
+
+    match a {
+        [1, .., b] => {
+            /* should not take this path */
+            unsafe { puts("wrong\0" as *const str as *const i8) }
+        }
+        [0, .., 0] => {
+            /* should not take this path */
+            unsafe { puts("wrong\0" as *const str as *const i8) }
+        },
+        [0, .., b] => {
+            ret -= b;
+            unsafe { puts("correct\0" as *const str as *const i8) }
+        },
+        _ => {}
+    }
+
+    ret
+}
-- 
2.50.1

Reply via email to