From: Yap Zhi Heng <[email protected]>
006t.original dump of rust/compile/match-structpattern-tuplefield.rs:
...
const struct match_structpattern_tuplefield::TupStruct t = {.0=1, .1=2};
struct () RUSTTMP.1;
const struct match_structpattern_tuplefield::TupStruct RUSTTMP.2;
RUSTTMP.2 = t;
if (RUSTTMP.2.0 == 1 && RUSTTMP.2.1 == 2)
{
{
struct () RUSTTMP.3;
{}
goto <D.100>;
}
}
if (1)
{
{
struct () RUSTTMP.4;
{}
goto <D.100>;
}
}
if (RUSTTMP.2.0 == 1)
{
{
struct () RUSTTMP.5;
{}
goto <D.100>;
}
}
if (1)
{
{
struct () RUSTTMP.6;
{}
goto <D.100>;
}
}
<D.100>:;
...
gcc/rust/ChangeLog:
* typecheck/rust-hir-type-check-pattern.cc (visit(StructPattern)):
Implement
type check case for HIR::StructPatternFieldTuplePat.
* checks/errors/rust-hir-pattern-analysis.cc (lower_struct_pattern):
Implement
case for HIR::StructPatternField::ItemType::TUPLE_PAT.
* backend/rust-compile-pattern.cc:
* CompilePatternCheckExpr::visit (HIR::StructPattern):
Implement code
gen for HIR::StructPatternField::ItemType::TUPLE_PAT case.
* CompilePatternBindings::handle_struct_pattern_tuple_pat:
Implement
bindings for HIR::StructPatternFieldTuplePat.
* backend/rust-compile-pattern.h: Update function definition for
handle_struct_pattern_tuple_pat.
Signed-off-by: Yap Zhi Heng <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/b940d2c51ba04f6c224642e777aacf4b2931be6b
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4400
gcc/rust/backend/rust-compile-pattern.cc | 51 +++++++++++++++++--
gcc/rust/backend/rust-compile-pattern.h | 5 +-
.../errors/rust-hir-pattern-analysis.cc | 8 ++-
.../typecheck/rust-hir-type-check-pattern.cc | 17 ++++++-
.../match-structpattern-tuplefield-err.rs | 17 +++++++
.../compile/match-structpattern-tuplefield.rs | 11 ++++
.../torture/match-structpattern-tuplefield.rs | 10 ++++
7 files changed, 109 insertions(+), 10 deletions(-)
create mode 100644
gcc/testsuite/rust/compile/match-structpattern-tuplefield-err.rs
create mode 100644 gcc/testsuite/rust/compile/match-structpattern-tuplefield.rs
create mode 100644
gcc/testsuite/rust/execute/torture/match-structpattern-tuplefield.rs
diff --git a/gcc/rust/backend/rust-compile-pattern.cc
b/gcc/rust/backend/rust-compile-pattern.cc
index 3836aa2af..d57616e6d 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -297,8 +297,18 @@ CompilePatternCheckExpr::visit (HIR::StructPattern
&pattern)
{
case HIR::StructPatternField::ItemType::TUPLE_PAT:
{
- // TODO
- rust_unreachable ();
+ HIR::StructPatternFieldTuplePat &tuple_pat
+ = static_cast<HIR::StructPatternFieldTuplePat &> (*field.get ());
+ size_t tuple_pat_index = tuple_pat.get_index ();
+ tree field_expr
+ = Backend::struct_field_expression (variant_accesser_expr,
+ tuple_pat_index,
+ tuple_pat.get_locus ());
+ tree check_expr_sub = CompilePatternCheckExpr::Compile (
+ tuple_pat.get_tuple_pattern (), field_expr, ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, tuple_pat.get_locus ());
}
break;
@@ -954,9 +964,40 @@ CompilePatternBindings::handle_struct_pattern_ident_pat (
void
CompilePatternBindings::handle_struct_pattern_tuple_pat (
- HIR::StructPatternField &pat)
+ HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant,
+ int variant_index)
{
- rust_unreachable ();
+ HIR::StructPatternFieldTuplePat &tuple_pat
+ = static_cast<HIR::StructPatternFieldTuplePat &> (pat);
+
+ size_t tuple_pat_index = tuple_pat.get_index ();
+ tree binding;
+
+ if (adt->is_enum ())
+ {
+ tree payload_accessor_union
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ pat.get_locus ());
+
+ tree variant_accessor
+ = Backend::struct_field_expression (payload_accessor_union,
+ variant_index, pat.get_locus ());
+
+ binding
+ = Backend::struct_field_expression (variant_accessor, tuple_pat_index,
+ pat.get_locus ());
+ }
+ else
+ {
+ tree variant_accessor = match_scrutinee_expr;
+
+ binding
+ = Backend::struct_field_expression (variant_accessor, tuple_pat_index,
+ pat.get_locus ());
+ }
+
+ CompilePatternBindings::Compile (tuple_pat.get_tuple_pattern (), binding,
+ ctx);
}
void
@@ -996,7 +1037,7 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
switch (field->get_item_type ())
{
case HIR::StructPatternField::ItemType::TUPLE_PAT:
- handle_struct_pattern_tuple_pat (*field);
+ handle_struct_pattern_tuple_pat (*field, adt, variant, variant_index);
break;
case HIR::StructPatternField::ItemType::IDENT_PAT:
handle_struct_pattern_ident_pat (*field, adt, variant, variant_index);
diff --git a/gcc/rust/backend/rust-compile-pattern.h
b/gcc/rust/backend/rust-compile-pattern.h
index 7c38eb571..35e152fe3 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -88,7 +88,10 @@ public:
TyTy::ADTType *adt,
TyTy::VariantDef *variant,
int variant_index);
- void handle_struct_pattern_tuple_pat (HIR::StructPatternField &pat);
+ void handle_struct_pattern_tuple_pat (HIR::StructPatternField &pat,
+ TyTy::ADTType *adt,
+ TyTy::VariantDef *variant,
+ int variant_index);
void visit (HIR::StructPattern &pattern) override;
void visit (HIR::TupleStructPattern &pattern) override;
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index 8c972a596..431cd9bb8 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -1315,8 +1315,12 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx,
break;
case HIR::StructPatternField::ItemType::TUPLE_PAT:
{
- // TODO: tuple: pat
- rust_unreachable ();
+ HIR::StructPatternFieldTuplePat *tuple_pat
+ = static_cast<HIR::StructPatternFieldTuplePat *> (elem.get ());
+ int field_idx = tuple_pat->get_index ();
+ fields.at (field_idx) = lower_pattern (
+ ctx, tuple_pat->get_tuple_pattern (),
+ variant->get_fields ().at (field_idx)->get_field_type ());
}
break;
default:
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 1e043d737..4f484ca0d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -474,8 +474,21 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
{
case HIR::StructPatternField::ItemType::TUPLE_PAT:
{
- // TODO
- rust_unreachable ();
+ HIR::StructPatternFieldTuplePat &tuple_pat
+ = static_cast<HIR::StructPatternFieldTuplePat &> (*field.get ());
+
+ if ((size_t) tuple_pat.get_index () >= variant->num_fields ())
+ {
+ emit_invalid_field_error (tuple_pat.get_locus (), variant,
+ std::to_string (
+ tuple_pat.get_index ()));
+ break;
+ }
+ named_fields.push_back (std::to_string (tuple_pat.get_index ()));
+ TyTy::StructFieldType *field
+ = variant->get_field_at_index (tuple_pat.get_index ());
+ TyTy::BaseType *fty = field->get_field_type ();
+ TypeCheckPattern::Resolve (tuple_pat.get_tuple_pattern (), fty);
}
break;
diff --git a/gcc/testsuite/rust/compile/match-structpattern-tuplefield-err.rs
b/gcc/testsuite/rust/compile/match-structpattern-tuplefield-err.rs
new file mode 100644
index 000000000..ca4fb1ab1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-structpattern-tuplefield-err.rs
@@ -0,0 +1,17 @@
+pub struct TupStruct (i32, i32);
+
+pub fn main() {
+ let t = TupStruct (1, 2);
+ match t {
+ TupStruct { 0: 1, 1: 2, 2: 3 } => {}
+ // { dg-error "variant TupStruct does not have a field named 2
.E0026." "" { target *-*-* } .-1 }
+ TupStruct { 3: 3 } => {}
+ // { dg-error "pattern does not mention fields 0, 1 .E0027." "" {
target *-*-* } .-1 }
+ // { dg-error "variant TupStruct does not have a field named 3
.E0026." "" { target *-*-* } .-2 }
+ TupStruct { a: 3 } => {}
+ // { dg-error "tuple variant .TupStruct. written as struct variant
.E0769." "" { target *-*-* } .-1 }
+ TupStruct { 0: 0.1f32, .. } => {}
+ // { dg-error "mismatched types, expected .i32. but got .f32. .E0308."
"" { target *-*-* } .-1 }
+ _ => {}
+ }
+}
diff --git a/gcc/testsuite/rust/compile/match-structpattern-tuplefield.rs
b/gcc/testsuite/rust/compile/match-structpattern-tuplefield.rs
new file mode 100644
index 000000000..8807e98ac
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-structpattern-tuplefield.rs
@@ -0,0 +1,11 @@
+pub struct TupStruct (i32, i32);
+
+pub fn main() {
+ let t = TupStruct (1, 2);
+ match t {
+ TupStruct { 0: 1, 1: 2 } => {}
+ TupStruct { 1: b, .. } => {}
+ TupStruct { 0: 1, .. } => {}
+ _ => {}
+ }
+}
diff --git
a/gcc/testsuite/rust/execute/torture/match-structpattern-tuplefield.rs
b/gcc/testsuite/rust/execute/torture/match-structpattern-tuplefield.rs
new file mode 100644
index 000000000..3c6657547
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-structpattern-tuplefield.rs
@@ -0,0 +1,10 @@
+pub struct TupStruct (i32, i32);
+
+pub fn main() -> i32 {
+ let mut t = TupStruct (1, 1);
+ match t {
+ TupStruct { 0: 1, 1: b } => { b -= 1 }
+ _ => {}
+ }
+ b
+}
base-commit: d2f8f6493738e752660b3deeb34529613f4adf1b
--
2.52.0