]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Fix StructPattern type checking rejecting tuple struct scrutinee
authorYap Zhi Heng <yapzhhg@gmail.com>
Sun, 28 Sep 2025 11:11:31 +0000 (19:11 +0800)
committerArthur Cohen <arthur.cohen@embecosm.com>
Thu, 30 Oct 2025 20:30:53 +0000 (21:30 +0100)
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 <yapzhhg@gmail.com>
gcc/rust/backend/rust-compile-pattern.cc
gcc/rust/hir/tree/rust-hir.cc
gcc/rust/typecheck/rust-hir-type-check-pattern.cc

index 149f6b0741135475dd0e72e4dce740da1b79cb83..9ebb4d1dd63e87e1243e68e472dff8b312e9a3f7 100644 (file)
@@ -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 ())
index 7aad4ef2730396cedb6bd45f6cb85aad4bcce8de..ce10b02303c314b29bd74f6ed600ff1cce004440 100644 (file)
@@ -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;
 }
 
index 7b405510bb393f3a5055088e0c5821fbea0a3030..e964318bf7c24c7c55a87e07a7333fd664ab32a5 100644 (file)
@@ -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;
                }
            }