aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2025-04-16 16:32:35 +0200
committerCohenArthur <arthur.cohen@embecosm.com>2025-04-30 10:35:43 +0000
commit515e1692ffe87852ae68fab2715a64e6bf0477a2 (patch)
tree471a34c04bdf345b5b2fdec17431edeb32091fe0 /gcc
parent0a316f44a0811b54b72aa68997ee62a66ff54ebe (diff)
downloadgcc-515e1692ffe87852ae68fab2715a64e6bf0477a2.zip
gcc-515e1692ffe87852ae68fab2715a64e6bf0477a2.tar.gz
gcc-515e1692ffe87852ae68fab2715a64e6bf0477a2.tar.bz2
backend: Compile struct rebinding patterns
Allow matching on a struct instance and rebinding its fields to new names: match X { Foo { field0: new_name0, field1: new_name1, } => { do_something(new_name0, new_name1); }, } This will enable us to finish derives for PartialEq and PartialOrd but isn't a complete implementation of these patterns yet. gcc/rust/ChangeLog: * backend/rust-compile-pattern.cc (CompilePatternBindings::make_struct_access): New function. (CompilePatternBindings::visit): Properly implement patterns mentioned above and call make_struct_accesss. * backend/rust-compile-pattern.h: New declaration. gcc/testsuite/ChangeLog: * rust/execute/torture/struct_pattern1.rs: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-pattern.cc68
-rw-r--r--gcc/rust/backend/rust-compile-pattern.h8
-rw-r--r--gcc/testsuite/rust/execute/torture/struct_pattern1.rs19
3 files changed, 77 insertions, 18 deletions
diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index a836072..94844fe 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -22,8 +22,11 @@
#include "rust-constexpr.h"
#include "rust-compile-type.h"
#include "print-tree.h"
+#include "rust-diagnostics.h"
+#include "rust-hir-pattern-abstract.h"
#include "rust-hir-pattern.h"
#include "rust-system.h"
+#include "rust-tyty.h"
namespace Rust {
namespace Compile {
@@ -506,20 +509,16 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
}
}
-void
-CompilePatternBindings::handle_struct_pattern_ident (
- HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant,
- int variant_index)
+tree
+CompilePatternBindings::make_struct_access (TyTy::ADTType *adt,
+ TyTy::VariantDef *variant,
+ Identifier &ident,
+ int variant_index)
{
- HIR::StructPatternFieldIdent &ident
- = static_cast<HIR::StructPatternFieldIdent &> (pat);
-
size_t offs = 0;
- auto ok = variant->lookup_field (ident.get_identifier ().as_string (),
- nullptr, &offs);
+ auto ok = variant->lookup_field (ident.as_string (), nullptr, &offs);
rust_assert (ok);
- tree binding = error_mark_node;
if (adt->is_enum ())
{
tree payload_accessor_union
@@ -530,24 +529,59 @@ CompilePatternBindings::handle_struct_pattern_ident (
= Backend::struct_field_expression (payload_accessor_union,
variant_index, ident.get_locus ());
- binding = Backend::struct_field_expression (variant_accessor, offs,
- ident.get_locus ());
+ return Backend::struct_field_expression (variant_accessor, offs,
+ ident.get_locus ());
}
else
{
tree variant_accessor = match_scrutinee_expr;
- binding = Backend::struct_field_expression (variant_accessor, offs,
- ident.get_locus ());
+
+ return Backend::struct_field_expression (variant_accessor, offs,
+ ident.get_locus ());
}
+}
+
+void
+CompilePatternBindings::handle_struct_pattern_ident (
+ HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant,
+ int variant_index)
+{
+ HIR::StructPatternFieldIdent &ident
+ = static_cast<HIR::StructPatternFieldIdent &> (pat);
+
+ auto identifier = ident.get_identifier ();
+ tree binding = make_struct_access (adt, variant, identifier, variant_index);
ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), binding);
}
void
CompilePatternBindings::handle_struct_pattern_ident_pat (
- HIR::StructPatternField &pat)
+ HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant,
+ int variant_index)
{
- rust_unreachable ();
+ auto &pattern = static_cast<HIR::StructPatternFieldIdentPat &> (pat);
+
+ switch (pattern.get_pattern ().get_pattern_type ())
+ {
+ case HIR::Pattern::IDENTIFIER: {
+ auto &id
+ = static_cast<HIR::IdentifierPattern &> (pattern.get_pattern ());
+
+ CompilePatternBindings::Compile (id, match_scrutinee_expr, ctx);
+ }
+ break;
+ default:
+ rust_sorry_at (pat.get_locus (),
+ "cannot handle non-identifier struct patterns");
+ return;
+ }
+
+ auto ident = pattern.get_identifier ();
+ tree binding = make_struct_access (adt, variant, ident, variant_index);
+
+ ctx->insert_pattern_binding (
+ pattern.get_pattern ().get_mappings ().get_hirid (), binding);
}
void
@@ -596,7 +630,7 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
handle_struct_pattern_tuple_pat (*field);
break;
case HIR::StructPatternField::ItemType::IDENT_PAT:
- handle_struct_pattern_ident_pat (*field);
+ handle_struct_pattern_ident_pat (*field, adt, variant, variant_index);
break;
case HIR::StructPatternField::ItemType::IDENT:
handle_struct_pattern_ident (*field, adt, variant, variant_index);
diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h
index dea63e3..8ebc275 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -80,11 +80,17 @@ public:
pattern.accept_vis (compiler);
}
+ tree make_struct_access (TyTy::ADTType *adt, TyTy::VariantDef *variant,
+ Identifier &ident, int variant_index);
+
void handle_struct_pattern_ident (HIR::StructPatternField &pat,
TyTy::ADTType *adt,
TyTy::VariantDef *variant,
int variant_index);
- void handle_struct_pattern_ident_pat (HIR::StructPatternField &pat);
+ void handle_struct_pattern_ident_pat (HIR::StructPatternField &pat,
+ TyTy::ADTType *adt,
+ TyTy::VariantDef *variant,
+ int variant_index);
void handle_struct_pattern_tuple_pat (HIR::StructPatternField &pat);
void visit (HIR::StructPattern &pattern) override;
diff --git a/gcc/testsuite/rust/execute/torture/struct_pattern1.rs b/gcc/testsuite/rust/execute/torture/struct_pattern1.rs
new file mode 100644
index 0000000..7a74092
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/struct_pattern1.rs
@@ -0,0 +1,19 @@
+struct A {
+ // the two warnings are invalid but this should be fixed by our lint rework
+ // with this year's GSoC so ok for now
+ a: i32, // { dg-warning "never read" }
+ b: i32, // { dg-warning "never read" }
+}
+
+fn main() -> i32 {
+ let a = A { a: 15, b: 14 };
+
+ let result = match a {
+ A {
+ a: self_a,
+ b: self_b,
+ } => self_a + self_b,
+ };
+
+ result - 29
+}