https://gcc.gnu.org/g:495ec48ac88128053567721745a3a740016fe6a4
commit r16-4881-g495ec48ac88128053567721745a3a740016fe6a4 Author: Yap Zhi Heng <[email protected]> Date: Mon Aug 25 20:33:43 2025 +0800 gccrs: Implement compilation support for HIR::TupleStructItemsHasRest 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]> Diff: --- gcc/rust/backend/rust-compile-pattern.cc | 85 +++++++++++++++++++--- .../rust/compile/match-tuplestructpattern-rest.rs | 9 +++ .../torture/match-tuplestructpattern-rest-1.rs | 24 ++++++ .../torture/match-tuplestructpattern-rest-2.rs | 28 +++++++ 4 files changed, 134 insertions(+), 12 deletions(-) diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 9ebb4d1dd63e..9459fd618f35 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 000000000000..4681acbfcb1b --- /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 000000000000..8d7446d8e5f4 --- /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 000000000000..f433be91b4a9 --- /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 +}
