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