From: Yap Zhi Heng <[email protected]>
Previously, type checking of StructPattern will throw an error if it is used
to match against a tuple struct, even though it is possible to do so in rustc.
gcc/rust/ChangeLog:
* typecheck/rust-hir-type-check-pattern.cc (visit(StructPattern)): Add
type check
support for StructPatterns matching against a TUPLE type ADT.
*
backend/rust-compile-pattern.cc(CompilePatternBindings::visit(StructPattern)):
Update assert to allow TUPLE type ADTs.
* hir/tree/rust-hir.cc (StructPatternField::as_string()): Improve info
dumped.
Signed-off-by: Yap Zhi Heng <[email protected]>
---
gcc/rust/backend/rust-compile-pattern.cc | 5 ++-
gcc/rust/hir/tree/rust-hir.cc | 21 ++++++++++-
.../typecheck/rust-hir-type-check-pattern.cc | 37 ++++++++++++++++---
3 files changed, 54 insertions(+), 9 deletions(-)
diff --git a/gcc/rust/backend/rust-compile-pattern.cc
b/gcc/rust/backend/rust-compile-pattern.cc
index 149f6b07411..9ebb4d1dd63 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -885,8 +885,9 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
rust_assert (ok);
}
- rust_assert (variant->get_variant_type ()
- == TyTy::VariantDef::VariantType::STRUCT);
+ rust_assert (
+ variant->get_variant_type () == TyTy::VariantDef::VariantType::STRUCT
+ || variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE);
auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 7aad4ef2730..ce10b02303c 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -2519,10 +2519,29 @@ StructPatternField::as_string () const
* just the body */
for (const auto &attr : outer_attrs)
{
- str += "\n " + attr.as_string ();
+ str += "\n " + attr.as_string ();
}
}
+ str += "\n item type: ";
+ switch (get_item_type ())
+ {
+ case ItemType::TUPLE_PAT:
+ str += "TUPLE_PAT";
+ break;
+ case ItemType::IDENT_PAT:
+ str += "IDENT_PAT";
+ break;
+ case ItemType::IDENT:
+ str += "IDENT";
+ break;
+ default:
+ str += "UNKNOWN";
+ break;
+ }
+
+ str += "\n mapping: " + mappings.as_string ();
+
return str;
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 7b405510bb3..e964318bf7c 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -299,7 +299,30 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
// error[E0532]: expected tuple struct or tuple variant, found struct
// variant `Foo::D`
- if (variant->get_variant_type () != TyTy::VariantDef::VariantType::STRUCT)
+ bool error_E0532 = false;
+ if (variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE)
+ {
+ // Tuple structs can still be matched with struct patterns via index
+ // numbers e.g. Foo {0: a, .., 3: b}, so check whether the fields are of
+ // type TUPLE_PAT. Throw E0532 if not.
+ auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
+ for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
+ {
+ if (field->get_item_type ()
+ != HIR::StructPatternField::ItemType::TUPLE_PAT)
+ {
+ error_E0532 = true;
+ break;
+ }
+ }
+ }
+ else if (variant->get_variant_type ()
+ != TyTy::VariantDef::VariantType::STRUCT)
+ {
+ error_E0532 = true;
+ }
+
+ if (error_E0532)
{
std::string variant_type
= TyTy::VariantDef::variant_type_string (variant->get_variant_type ());
@@ -508,7 +531,8 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern)
{
emit_pattern_size_error (pattern, par.get_fields ().size (),
min_size_required);
- // TODO attempt to continue to do typechecking even after wrong size
+ // TODO attempt to continue to do typechecking even after wrong
+ // size
break;
}
@@ -680,10 +704,11 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern)
if (cap_wi < pattern_min_cap)
{
- rust_error_at (
- pattern.get_locus (), ErrorCode::E0528,
- "pattern requires at least %lu elements but array has %lu",
- (unsigned long) pattern_min_cap, (unsigned long) cap_wi);
+ rust_error_at (pattern.get_locus (), ErrorCode::E0528,
+ "pattern requires at least %lu elements but "
+ "array has %lu",
+ (unsigned long) pattern_min_cap,
+ (unsigned long) cap_wi);
break;
}
}
--
2.50.1