Skip to content

Commit aa642e7

Browse files
Polygonalrphilberty
authored andcommitted
Fix StructPattern type checking rejecting tuple struct scrutinee
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]>
1 parent 8836ed1 commit aa642e7

File tree

3 files changed

+54
-9
lines changed

3 files changed

+54
-9
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -885,8 +885,9 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
885885
rust_assert (ok);
886886
}
887887

888-
rust_assert (variant->get_variant_type ()
889-
== TyTy::VariantDef::VariantType::STRUCT);
888+
rust_assert (
889+
variant->get_variant_type () == TyTy::VariantDef::VariantType::STRUCT
890+
|| variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE);
890891

891892
auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
892893
for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())

gcc/rust/hir/tree/rust-hir.cc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2519,10 +2519,29 @@ StructPatternField::as_string () const
25192519
* just the body */
25202520
for (const auto &attr : outer_attrs)
25212521
{
2522-
str += "\n " + attr.as_string ();
2522+
str += "\n " + attr.as_string ();
25232523
}
25242524
}
25252525

2526+
str += "\n item type: ";
2527+
switch (get_item_type ())
2528+
{
2529+
case ItemType::TUPLE_PAT:
2530+
str += "TUPLE_PAT";
2531+
break;
2532+
case ItemType::IDENT_PAT:
2533+
str += "IDENT_PAT";
2534+
break;
2535+
case ItemType::IDENT:
2536+
str += "IDENT";
2537+
break;
2538+
default:
2539+
str += "UNKNOWN";
2540+
break;
2541+
}
2542+
2543+
str += "\n mapping: " + mappings.as_string ();
2544+
25262545
return str;
25272546
}
25282547

gcc/rust/typecheck/rust-hir-type-check-pattern.cc

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,30 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
299299

300300
// error[E0532]: expected tuple struct or tuple variant, found struct
301301
// variant `Foo::D`
302-
if (variant->get_variant_type () != TyTy::VariantDef::VariantType::STRUCT)
302+
bool error_E0532 = false;
303+
if (variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE)
304+
{
305+
// Tuple structs can still be matched with struct patterns via index
306+
// numbers e.g. Foo {0: a, .., 3: b}, so check whether the fields are of
307+
// type TUPLE_PAT. Throw E0532 if not.
308+
auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
309+
for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
310+
{
311+
if (field->get_item_type ()
312+
!= HIR::StructPatternField::ItemType::TUPLE_PAT)
313+
{
314+
error_E0532 = true;
315+
break;
316+
}
317+
}
318+
}
319+
else if (variant->get_variant_type ()
320+
!= TyTy::VariantDef::VariantType::STRUCT)
321+
{
322+
error_E0532 = true;
323+
}
324+
325+
if (error_E0532)
303326
{
304327
std::string variant_type
305328
= TyTy::VariantDef::variant_type_string (variant->get_variant_type ());
@@ -508,7 +531,8 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern)
508531
{
509532
emit_pattern_size_error (pattern, par.get_fields ().size (),
510533
min_size_required);
511-
// TODO attempt to continue to do typechecking even after wrong size
534+
// TODO attempt to continue to do typechecking even after wrong
535+
// size
512536
break;
513537
}
514538

@@ -680,10 +704,11 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern)
680704

681705
if (cap_wi < pattern_min_cap)
682706
{
683-
rust_error_at (
684-
pattern.get_locus (), ErrorCode::E0528,
685-
"pattern requires at least %lu elements but array has %lu",
686-
(unsigned long) pattern_min_cap, (unsigned long) cap_wi);
707+
rust_error_at (pattern.get_locus (), ErrorCode::E0528,
708+
"pattern requires at least %lu elements but "
709+
"array has %lu",
710+
(unsigned long) pattern_min_cap,
711+
(unsigned long) cap_wi);
687712
break;
688713
}
689714
}

0 commit comments

Comments
 (0)