From: Yap Zhi Heng <[email protected]>
gcc/rust/ChangeLog:
* backend/rust-compile-pattern.cc: Add compilation support for
TupleStructItemsHasRest
in CompilePatternCheckExpr(TupleStructPattern) &
CompilePatternBindings(TupleStructPattern)
Signed-off-by: Yap Zhi Heng <[email protected]>
---
gcc/rust/backend/rust-compile-pattern.cc | 85 ++++++++++++++++---
.../compile/match-tuplestructpattern-rest.rs | 9 ++
.../match-tuplestructpattern-rest-1.rs | 24 ++++++
.../match-tuplestructpattern-rest-2.rs | 28 ++++++
4 files changed, 134 insertions(+), 12 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/match-tuplestructpattern-rest.rs
create mode 100644
gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-1.rs
create mode 100644
gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-2.rs
diff --git a/gcc/rust/backend/rust-compile-pattern.cc
b/gcc/rust/backend/rust-compile-pattern.cc
index 9ebb4d1dd63..9459fd618f3 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -358,8 +358,42 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern
&pattern)
{
case HIR::TupleStructItems::HAS_REST:
{
- // TODO
- rust_unreachable ();
+ HIR::TupleStructItemsHasRest &items_has_rest
+ = static_cast<HIR::TupleStructItemsHasRest &> (items);
+ size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
+ + items_has_rest.get_upper_patterns ().size ();
+
+ // enums cases shouldn't reach here
+ rust_assert (num_patterns <= variant->num_fields ()
+ && (!adt->is_enum ()));
+
+ size_t tuple_field_index = 0;
+ for (auto &pattern : items_has_rest.get_lower_patterns ())
+ {
+ tree field_expr
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pattern->get_locus ());
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pattern->get_locus ());
+ }
+ tuple_field_index = variant->num_fields ()
+ - items_has_rest.get_upper_patterns ().size ();
+ for (auto &pattern : items_has_rest.get_upper_patterns ())
+ {
+ tree field_expr
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pattern->get_locus ());
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pattern->get_locus ());
+ }
}
break;
@@ -738,23 +772,52 @@ CompilePatternBindings::visit (HIR::TupleStructPattern
&pattern)
{
case HIR::TupleStructItems::HAS_REST:
{
- // TODO
- rust_unreachable ();
+ HIR::TupleStructItemsHasRest &items_has_rest
+ = static_cast<HIR::TupleStructItemsHasRest &> (items);
+ size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
+ + items_has_rest.get_upper_patterns ().size ();
+
+ // enums cases shouldn't reach here
+ rust_assert (num_patterns <= variant->num_fields ()
+ && (!adt->is_enum ()));
+
+ size_t tuple_field_index = 0;
+ for (auto &pattern : items_has_rest.get_lower_patterns ())
+ {
+ tree binding
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pattern->get_locus ());
+
+ CompilePatternBindings::Compile (*pattern, binding, ctx);
+ }
+
+ tuple_field_index = variant->num_fields ()
+ - items_has_rest.get_upper_patterns ().size ();
+
+ for (auto &pattern : items_has_rest.get_upper_patterns ())
+ {
+ tree binding
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pattern->get_locus ());
+
+ CompilePatternBindings::Compile (*pattern, binding, ctx);
+ }
}
break;
case HIR::TupleStructItems::NO_REST:
{
- HIR::TupleStructItemsNoRest &items_no_range
+ HIR::TupleStructItemsNoRest &items_no_rest
= static_cast<HIR::TupleStructItemsNoRest &> (items);
-
- rust_assert (items_no_range.get_patterns ().size ()
+ rust_assert (items_no_rest.get_patterns ().size ()
== variant->num_fields ());
if (adt->is_enum ())
{
size_t tuple_field_index = 0;
- for (auto &pattern : items_no_range.get_patterns ())
+ for (auto &pattern : items_no_rest.get_patterns ())
{
tree payload_accessor_union
= Backend::struct_field_expression (match_scrutinee_expr, 1,
@@ -776,12 +839,10 @@ CompilePatternBindings::visit (HIR::TupleStructPattern
&pattern)
else
{
size_t tuple_field_index = 0;
- for (auto &pattern : items_no_range.get_patterns ())
+ for (auto &pattern : items_no_rest.get_patterns ())
{
- tree variant_accessor = match_scrutinee_expr;
-
tree binding
- = Backend::struct_field_expression (variant_accessor,
+ = Backend::struct_field_expression (match_scrutinee_expr,
tuple_field_index++,
pattern->get_locus ());
diff --git a/gcc/testsuite/rust/compile/match-tuplestructpattern-rest.rs
b/gcc/testsuite/rust/compile/match-tuplestructpattern-rest.rs
new file mode 100644
index 00000000000..4681acbfcb1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-tuplestructpattern-rest.rs
@@ -0,0 +1,9 @@
+fn main() {
+ struct A (i32, i32);
+ let a = A (0, 1);
+
+ match a {
+ A (0, ..) => {},
+ _ => {}
+ }
+}
diff --git
a/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-1.rs
b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-1.rs
new file mode 100644
index 00000000000..8d7446d8e5f
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-1.rs
@@ -0,0 +1,24 @@
+// { dg-output "correct\r*" }
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+ struct A (i32, i32, i32);
+ let a = A (0, 1, 2);
+ let mut ret = 1;
+
+ match a {
+ A (1, ..) => {
+ /* should not take this path */
+ unsafe { puts("wrong\0" as *const str as *const i8) }
+ }
+ A (0, b, ..) => {
+ ret -= b;
+ unsafe { puts("correct\0" as *const str as *const i8) }
+ },
+ _ => {}
+ }
+
+ ret
+}
diff --git
a/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-2.rs
b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-2.rs
new file mode 100644
index 00000000000..f433be91b4a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-2.rs
@@ -0,0 +1,28 @@
+// { dg-output "correct\r*" }
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+ struct A (i32, i32, i32);
+ let a = A (0, 3, 1);
+ let mut ret = 1;
+
+ match a {
+ A (1, ..) => {
+ /* should not take this path */
+ unsafe { puts("wrong\0" as *const str as *const i8) }
+ }
+ A (.., 3) => {
+ /* should not take this path */
+ unsafe { puts("wrong\0" as *const str as *const i8) }
+ }
+ A (.., b) => {
+ ret -= b;
+ unsafe { puts("correct\0" as *const str as *const i8) }
+ },
+ _ => {}
+ }
+
+ ret
+}
--
2.50.1