From: Yap Zhi Heng <[email protected]>

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 <[email protected]>
---
 .../typecheck/rust-hir-type-check-pattern.cc  | 105 +++++++++++++++---
 .../compile/match-tuplestructpattern-err.rs   |  14 +++
 2 files changed, 101 insertions(+), 18 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/match-tuplestructpattern-err.rs

diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc 
b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 751456ccc77..4d9d60ca5bd 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -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
index 00000000000..efd1a896941
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-tuplestructpattern-err.rs
@@ -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
-- 
2.50.1

Reply via email to