]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Use rich_location for TupleStructPattern type check num field error
authorYap Zhi Heng <yapzhhg@gmail.com>
Tue, 2 Sep 2025 13:44:19 +0000 (21:44 +0800)
committerArthur Cohen <arthur.cohen@embecosm.com>
Thu, 30 Oct 2025 20:30:54 +0000 (21:30 +0100)
gcc/rust/ChangeLog:

* typecheck/rust-hir-type-check-pattern.cc (visit(TupleStructPattern)):
Update error for mismatched number of fields to use rich_location.

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

index 751456ccc7731a5d1776afb22119b82cf13bcbd1..4d9d60ca5bdc7f51763ed84b97d6579ca4dae224 100644 (file)
@@ -204,22 +204,66 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
       {
        HIR::TupleStructItemsHasRest &items_has_rest
          = static_cast<HIR::TupleStructItemsHasRest &> (items);
-       size_t pattern_min_cap = items_has_rest.get_lower_patterns ().size ()
-                                + items_has_rest.get_upper_patterns ().size ();
+       auto &lower_patterns = items_has_rest.get_lower_patterns ();
+       auto &upper_patterns = items_has_rest.get_upper_patterns ();
+       size_t pattern_min_cap
+         = lower_patterns.size () + upper_patterns.size ();
        if (variant->num_fields () < pattern_min_cap)
          {
-           rust_error_at (pattern.get_locus (), ErrorCode::E0023,
-                          "this pattern has %lu fields but the corresponding "
-                          "tuple variant has %lu field",
-                          (unsigned long) (pattern_min_cap),
-                          (unsigned long) variant->num_fields ());
+           if (!lower_patterns.empty ())
+             {
+               // TODO initialize rich_locus with loc of ADT definition instead
+               rich_location rich_locus (line_table,
+                                         lower_patterns[0]->get_locus ());
+               for (auto &pattern : lower_patterns)
+                 {
+                   if (pattern == lower_patterns[0])
+                     continue;
+                   rich_locus.add_range (pattern->get_locus (),
+                                         SHOW_RANGE_WITH_CARET);
+                 }
+               for (auto &pattern : upper_patterns)
+                 {
+                   rich_locus.add_range (pattern->get_locus (),
+                                         SHOW_RANGE_WITH_CARET);
+                 }
+               rust_error_at (rich_locus, ErrorCode::E0023,
+                              "this pattern has %lu %s but the corresponding "
+                              "tuple variant has %lu %s",
+                              (unsigned long) (pattern_min_cap),
+                              pattern_min_cap == 1 ? "field" : "fields",
+                              (unsigned long) variant->num_fields (),
+                              variant->num_fields () == 1 ? "field"
+                                                          : "fields");
+             }
+           else
+             {
+               // TODO initialize rich_locus with loc of ADT definition instead
+               rich_location rich_locus (line_table,
+                                         upper_patterns[0]->get_locus ());
+               for (auto &pattern : upper_patterns)
+                 {
+                   if (pattern == upper_patterns[0])
+                     continue;
+                   rich_locus.add_range (pattern->get_locus (),
+                                         SHOW_RANGE_WITH_CARET);
+                 }
+               rust_error_at (rich_locus, ErrorCode::E0023,
+                              "this pattern has %lu %s but the corresponding "
+                              "tuple variant has %lu %s",
+                              (unsigned long) (pattern_min_cap),
+                              pattern_min_cap == 1 ? "field" : "fields",
+                              (unsigned long) variant->num_fields (),
+                              variant->num_fields () == 1 ? "field"
+                                                          : "fields");
+             }
            // we continue on to try and setup the types as best we can for
            // type checking
          }
 
        // iterate the fields manually to set them up
        size_t i = 0;
-       for (auto &pattern : items_has_rest.get_lower_patterns ())
+       for (auto &pattern : lower_patterns)
          {
            if (i >= variant->num_fields ())
              break;
@@ -232,9 +276,8 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
            TypeCheckPattern::Resolve (*pattern, fty);
          }
 
-       i = variant->num_fields ()
-           - items_has_rest.get_upper_patterns ().size ();
-       for (auto &pattern : items_has_rest.get_upper_patterns ())
+       i = variant->num_fields () - upper_patterns.size ();
+       for (auto &pattern : upper_patterns)
          {
            if (i >= variant->num_fields ())
              break;
@@ -253,15 +296,41 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
       {
        HIR::TupleStructItemsNoRest &items_no_rest
          = static_cast<HIR::TupleStructItemsNoRest &> (items);
+       auto &patterns = items_no_rest.get_patterns ();
 
-       if (items_no_rest.get_patterns ().size () != variant->num_fields ())
+       if (patterns.size () != variant->num_fields ())
          {
-           rust_error_at (
-             pattern.get_locus (), ErrorCode::E0023,
-             "this pattern has %lu fields but the corresponding "
-             "tuple variant has %lu field",
-             (unsigned long) items_no_rest.get_patterns ().size (),
-             (unsigned long) variant->num_fields ());
+           if (patterns.empty ())
+             {
+               rust_error_at (pattern.get_locus (), ErrorCode::E0023,
+                              "this pattern has %lu %s but the corresponding "
+                              "tuple variant has %lu %s",
+                              (unsigned long) patterns.size (),
+                              patterns.size () == 1 ? "field" : "fields",
+                              (unsigned long) variant->num_fields (),
+                              variant->num_fields () == 1 ? "field"
+                                                          : "fields");
+             }
+           else
+             {
+               rich_location rich_locus (line_table,
+                                         patterns[0]->get_locus ());
+               for (auto &pattern : items_no_rest.get_patterns ())
+                 {
+                   if (pattern == patterns[0])
+                     continue;
+                   rich_locus.add_range (pattern->get_locus (),
+                                         SHOW_RANGE_WITH_CARET);
+                 }
+               rust_error_at (rich_locus, ErrorCode::E0023,
+                              "this pattern has %lu %s but the corresponding "
+                              "tuple variant has %lu %s",
+                              (unsigned long) patterns.size (),
+                              patterns.size () == 1 ? "field" : "fields",
+                              (unsigned long) variant->num_fields (),
+                              variant->num_fields () == 1 ? "field"
+                                                          : "fields");
+             }
            // we continue on to try and setup the types as best we can for
            // type checking
          }
diff --git a/gcc/testsuite/rust/compile/match-tuplestructpattern-err.rs b/gcc/testsuite/rust/compile/match-tuplestructpattern-err.rs
new file mode 100644 (file)
index 0000000..efd1a89
--- /dev/null
@@ -0,0 +1,14 @@
+fn main() {
+    struct A (i32, i32);
+    let a = A (0, 1);
+
+    match a {
+        A (1, 2, 3, 4) => {},
+        // { dg-error "this pattern has 4 fields but the corresponding tuple variant has 2 fields .E0023." "" { target *-*-* } .-1 }
+        A (1, 2, .., 3, 4) => {},
+        // { dg-error "this pattern has 4 fields but the corresponding tuple variant has 2 fields .E0023." "" { target *-*-* } .-1 }
+        A (.., 3, 4, 5) => {},
+        // { dg-error "this pattern has 3 fields but the corresponding tuple variant has 2 fields .E0023." "" { target *-*-* } .-1 }
+        _ => {}
+    }
+}
\ No newline at end of file