Skip to content

Commit 16d7b8b

Browse files
committed
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]>
1 parent 51cfac1 commit 16d7b8b

File tree

4 files changed

+134
-12
lines changed

4 files changed

+134
-12
lines changed

gcc/rust/backend/rust-compile-pattern.cc

Lines changed: 73 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,42 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern)
358358
{
359359
case HIR::TupleStructItems::HAS_REST:
360360
{
361-
// TODO
362-
rust_unreachable ();
361+
HIR::TupleStructItemsHasRest &items_has_rest
362+
= static_cast<HIR::TupleStructItemsHasRest &> (items);
363+
size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
364+
+ items_has_rest.get_upper_patterns ().size ();
365+
366+
// enums cases shouldn't reach here
367+
rust_assert (num_patterns <= variant->num_fields ()
368+
&& (!adt->is_enum ()));
369+
370+
size_t tuple_field_index = 0;
371+
for (auto &pattern : items_has_rest.get_lower_patterns ())
372+
{
373+
tree field_expr
374+
= Backend::struct_field_expression (match_scrutinee_expr,
375+
tuple_field_index++,
376+
pattern->get_locus ());
377+
tree check_expr_sub
378+
= CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx);
379+
check_expr = Backend::arithmetic_or_logical_expression (
380+
ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
381+
check_expr_sub, pattern->get_locus ());
382+
}
383+
tuple_field_index = variant->num_fields ()
384+
- items_has_rest.get_upper_patterns ().size ();
385+
for (auto &pattern : items_has_rest.get_upper_patterns ())
386+
{
387+
tree field_expr
388+
= Backend::struct_field_expression (match_scrutinee_expr,
389+
tuple_field_index++,
390+
pattern->get_locus ());
391+
tree check_expr_sub
392+
= CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx);
393+
check_expr = Backend::arithmetic_or_logical_expression (
394+
ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
395+
check_expr_sub, pattern->get_locus ());
396+
}
363397
}
364398
break;
365399

@@ -738,23 +772,52 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
738772
{
739773
case HIR::TupleStructItems::HAS_REST:
740774
{
741-
// TODO
742-
rust_unreachable ();
775+
HIR::TupleStructItemsHasRest &items_has_rest
776+
= static_cast<HIR::TupleStructItemsHasRest &> (items);
777+
size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
778+
+ items_has_rest.get_upper_patterns ().size ();
779+
780+
// enums cases shouldn't reach here
781+
rust_assert (num_patterns <= variant->num_fields ()
782+
&& (!adt->is_enum ()));
783+
784+
size_t tuple_field_index = 0;
785+
for (auto &pattern : items_has_rest.get_lower_patterns ())
786+
{
787+
tree binding
788+
= Backend::struct_field_expression (match_scrutinee_expr,
789+
tuple_field_index++,
790+
pattern->get_locus ());
791+
792+
CompilePatternBindings::Compile (*pattern, binding, ctx);
793+
}
794+
795+
tuple_field_index = variant->num_fields ()
796+
- items_has_rest.get_upper_patterns ().size ();
797+
798+
for (auto &pattern : items_has_rest.get_upper_patterns ())
799+
{
800+
tree binding
801+
= Backend::struct_field_expression (match_scrutinee_expr,
802+
tuple_field_index++,
803+
pattern->get_locus ());
804+
805+
CompilePatternBindings::Compile (*pattern, binding, ctx);
806+
}
743807
}
744808
break;
745809

746810
case HIR::TupleStructItems::NO_REST:
747811
{
748-
HIR::TupleStructItemsNoRest &items_no_range
812+
HIR::TupleStructItemsNoRest &items_no_rest
749813
= static_cast<HIR::TupleStructItemsNoRest &> (items);
750-
751-
rust_assert (items_no_range.get_patterns ().size ()
814+
rust_assert (items_no_rest.get_patterns ().size ()
752815
== variant->num_fields ());
753816

754817
if (adt->is_enum ())
755818
{
756819
size_t tuple_field_index = 0;
757-
for (auto &pattern : items_no_range.get_patterns ())
820+
for (auto &pattern : items_no_rest.get_patterns ())
758821
{
759822
tree payload_accessor_union
760823
= Backend::struct_field_expression (match_scrutinee_expr, 1,
@@ -776,12 +839,10 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
776839
else
777840
{
778841
size_t tuple_field_index = 0;
779-
for (auto &pattern : items_no_range.get_patterns ())
842+
for (auto &pattern : items_no_rest.get_patterns ())
780843
{
781-
tree variant_accessor = match_scrutinee_expr;
782-
783844
tree binding
784-
= Backend::struct_field_expression (variant_accessor,
845+
= Backend::struct_field_expression (match_scrutinee_expr,
785846
tuple_field_index++,
786847
pattern->get_locus ());
787848

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fn main() {
2+
struct A (i32, i32);
3+
let a = A (0, 1);
4+
5+
match a {
6+
A (0, ..) => {},
7+
_ => {}
8+
}
9+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// { dg-output "correct\r*" }
2+
extern "C" {
3+
fn puts(s: *const i8);
4+
}
5+
6+
fn main() -> i32 {
7+
struct A (i32, i32, i32);
8+
let a = A (0, 1, 2);
9+
let mut ret = 1;
10+
11+
match a {
12+
A (1, ..) => {
13+
/* should not take this path */
14+
unsafe { puts("wrong\0" as *const str as *const i8) }
15+
}
16+
A (0, b, ..) => {
17+
ret -= b;
18+
unsafe { puts("correct\0" as *const str as *const i8) }
19+
},
20+
_ => {}
21+
}
22+
23+
ret
24+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// { dg-output "correct\r*" }
2+
extern "C" {
3+
fn puts(s: *const i8);
4+
}
5+
6+
fn main() -> i32 {
7+
struct A (i32, i32, i32);
8+
let a = A (0, 3, 1);
9+
let mut ret = 1;
10+
11+
match a {
12+
A (1, ..) => {
13+
/* should not take this path */
14+
unsafe { puts("wrong\0" as *const str as *const i8) }
15+
}
16+
A (.., 3) => {
17+
/* should not take this path */
18+
unsafe { puts("wrong\0" as *const str as *const i8) }
19+
}
20+
A (.., b) => {
21+
ret -= b;
22+
unsafe { puts("correct\0" as *const str as *const i8) }
23+
},
24+
_ => {}
25+
}
26+
27+
ret
28+
}

0 commit comments

Comments
 (0)