]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Attempt to resolve pattern items in tuple pattern with a rest pattern
authorYap Zhi Heng <yapzhhg@gmail.com>
Sat, 18 Oct 2025 05:22:05 +0000 (13:22 +0800)
committerArthur Cohen <arthur.cohen@embecosm.com>
Thu, 30 Oct 2025 20:31:01 +0000 (21:31 +0100)
gcc/rust/ChangeLog:

* typecheck/rust-hir-type-check-pattern.cc (visit(TuplePattern)): Update HAS_REST
case to continue to attempt to resolve pattern items after emitting size error.

Signed-off-by: Yap Zhi Heng <yapzhhg@gmail.com>
gcc/rust/typecheck/rust-hir-type-check-pattern.cc
gcc/testsuite/rust/compile/tuplepattern-restpattern-typecheck-err.rs [new file with mode: 0644]

index dd9a49f49dc52689e564fbe33b9a2d5c5e7989af..7dae303cd25a9a56810bec2d1ea64787eaa7b988 100644 (file)
@@ -657,14 +657,14 @@ 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
-           break;
+           // continue and attempt to resolve individual items in the pattern
          }
 
        // Resolve lower patterns
        std::vector<TyTy::TyVar> pattern_elems;
-       for (size_t i = 0; i < lower.size (); i++)
+       size_t nlower_items_to_resolve
+         = std::min (lower.size (), par.get_fields ().size ());
+       for (size_t i = 0; i < nlower_items_to_resolve; i++)
          {
            auto &p = lower[i];
            TyTy::BaseType *par_type = par.get_field (i);
@@ -673,16 +673,23 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern)
            pattern_elems.emplace_back (elem->get_ref ());
          }
 
+       if (lower.size () > par.get_fields ().size ())
+         break;
+
        // Pad pattern_elems until needing to resolve upper patterns
-       size_t rest_end = par.get_fields ().size () - upper.size ();
+       size_t rest_end
+         = std::max (par.get_fields ().size () - upper.size (), lower.size ());
        for (size_t i = lower.size (); i < rest_end; i++)
          {
            TyTy::BaseType *par_type = par.get_field (i);
            pattern_elems.emplace_back (par_type->get_ref ());
          }
 
+       size_t nupper_items_to_resolve
+         = std::min (upper.size (),
+                     par.get_fields ().size () - pattern_elems.size ());
        // Resolve upper patterns
-       for (size_t i = 0; i < upper.size (); i++)
+       for (size_t i = 0; i < nupper_items_to_resolve; i++)
          {
            auto &p = upper[i];
            TyTy::BaseType *par_type = par.get_field (rest_end + i);
diff --git a/gcc/testsuite/rust/compile/tuplepattern-restpattern-typecheck-err.rs b/gcc/testsuite/rust/compile/tuplepattern-restpattern-typecheck-err.rs
new file mode 100644 (file)
index 0000000..d9f7c18
--- /dev/null
@@ -0,0 +1,8 @@
+fn main() {
+    match (1, 2.2, "not 3") {
+        // { dg-error "expected a tuple with 3 elements, found one with 5 elements" "" { target *-*-* } .+1 }
+        (a, b, .., c, d, e) => {
+            let _ = b + c; // { dg-error "cannot apply operator .+. to types <float> and & str" }
+        }
+    }
+}
\ No newline at end of file