]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Fix ICE on enum in tuple struct pattern
authorRyo Yoshida <low.ryoshida@gmail.com>
Sun, 19 Oct 2025 13:45:17 +0000 (22:45 +0900)
committerArthur Cohen <arthur.cohen@embecosm.com>
Thu, 30 Oct 2025 20:30:59 +0000 (21:30 +0100)
When we typecheck a tuple struct pattern and the type of its path is
an enum, it may refer to the enum itself and not a variant. Emit an
E0532 error on such cases.

Fixes Rust-GCC/gccrs#3917
Fixes Rust-GCC/gccrs#3918
Fixes Rust-GCC/gccrs#3926

gcc/rust/ChangeLog:

* typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Emit
an error when the path refers to an enum itself rather than its variant.

gcc/testsuite/ChangeLog:

* rust/compile/match-tuplestructpattern-non-variant.rs: New test.

Signed-off-by: Ryo Yoshida <low.ryoshida@gmail.com>
gcc/rust/typecheck/rust-hir-type-check-pattern.cc
gcc/testsuite/rust/compile/match-tuplestructpattern-non-variant.rs [new file with mode: 0644]

index e8467f0c7b8a770c01baed9e8c1c5d8d4fe1a911..dd9a49f49dc52689e564fbe33b9a2d5c5e7989af 100644 (file)
@@ -162,19 +162,32 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
 
   infered = pattern_ty;
   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
-  rust_assert (adt->number_of_variants () > 0);
 
-  TyTy::VariantDef *variant = adt->get_variants ().at (0);
+  TyTy::VariantDef *variant = nullptr;
   if (adt->is_enum ())
     {
       HirId variant_id = UNKNOWN_HIRID;
       bool ok = context->lookup_variant_definition (
        pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
-      rust_assert (ok);
+      if (!ok)
+       {
+         rust_error_at (
+           pattern.get_locus (), ErrorCode::E0532,
+           "expected tuple struct or tuple variant, found enum %qs",
+           pattern_ty->get_name ().c_str ());
+         return;
+       }
 
       ok = adt->lookup_variant_by_id (variant_id, &variant);
       rust_assert (ok);
     }
+  else
+    {
+      rust_assert (adt->number_of_variants () > 0);
+      variant = adt->get_variants ().at (0);
+    }
+
+  rust_assert (variant != nullptr);
 
   // error[E0532]: expected tuple struct or tuple variant, found struct
   // variant `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0
diff --git a/gcc/testsuite/rust/compile/match-tuplestructpattern-non-variant.rs b/gcc/testsuite/rust/compile/match-tuplestructpattern-non-variant.rs
new file mode 100644 (file)
index 0000000..cf751cb
--- /dev/null
@@ -0,0 +1,20 @@
+enum Empty {}
+enum NonEmpty {
+    Foo(i32),
+}
+
+fn f(e: Empty) {
+    match e { 
+        Empty(0) => {} // { dg-error "expected tuple struct or tuple variant, found enum 'Empty'" }
+    }
+
+    match e {
+        Empty(Empty(..)) => {} // { dg-error "expected tuple struct or tuple variant, found enum 'Empty'" }
+    }
+}
+
+fn g(e: NonEmpty) {
+    match e {
+        NonEmpty(0) => {} // { dg-error "expected tuple struct or tuple variant, found enum 'NonEmpty'" }
+    }
+}