From: Kushal Pal <kushalpal...@gmail.com>

gcc/rust/ChangeLog:

        * checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
        (BorrowCheckerDiagnostics::report_subset_errors): Highlight
        lifetime locations while reporting subset errors.
        (BorrowCheckerDiagnostics::get_lifetime_param): Helper function
        to fetch HIR::Lifetime node from Polonius::Origin.
        * checks/errors/borrowck/rust-borrow-checker-diagnostics.h:
        Definition of helper function.

gcc/testsuite/ChangeLog:

        * rust/borrowck/subset.rs: Better subset errors.

Signed-off-by: Kushal Pal <kushalpal...@gmail.com>
---
 .../rust-borrow-checker-diagnostics.cc        | 43 ++++++++++++++++---
 .../rust-borrow-checker-diagnostics.h         |  1 +
 gcc/testsuite/rust/borrowck/subset.rs         | 29 +++++++++++--
 3 files changed, 64 insertions(+), 9 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc 
b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
index 0365dc3bd6f..dc010291073 100644
--- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
@@ -61,12 +61,38 @@ BorrowCheckerDiagnostics::report_loan_errors ()
 void
 BorrowCheckerDiagnostics::report_subset_errors ()
 {
-  if (!subset_errors.empty ())
+  // remove duplicates in subset_errors
+  //
+  // Polonius may output subset errors for same 2 origins at multiple points
+  // so to avoid duplicating the errors, we can remove the elements in subset
+  // errors with same origin pair
+  std::vector<std::pair<size_t, std::pair<size_t, size_t>>>
+    deduplicated_subset_errors;
+
+  for (auto pair : subset_errors)
     {
-      rust_error_at (hir_function->get_locus (),
-                    "Found subset errors in function %s. Some lifetime "
-                    "constraints need to be added.",
-                    hir_function->get_function_name ().as_string ().c_str ());
+      auto it = std::find_if (
+       deduplicated_subset_errors.begin (), deduplicated_subset_errors.end (),
+       [&pair] (std::pair<size_t, std::pair<size_t, size_t>> element) {
+         return element.second == pair.second;
+       });
+      if (it == deduplicated_subset_errors.end ())
+       {
+         deduplicated_subset_errors.push_back (pair);
+       }
+    }
+  for (const auto &error : deduplicated_subset_errors)
+    {
+      auto first_lifetime_location
+       = get_lifetime_param (error.second.first)->get_locus ();
+      auto second_lifetime_location
+       = get_lifetime_param (error.second.second)->get_locus ();
+      multi_label_error (
+       "subset error, some lifetime constraints need to be added",
+       bir_function.location,
+       {{"lifetime defined here", first_lifetime_location},
+        {"lifetime defined here", second_lifetime_location},
+        {"subset error occurs in this function", bir_function.location}});
     }
 }
 
@@ -88,6 +114,13 @@ BorrowCheckerDiagnostics::get_loan (Polonius::Loan loan)
   return bir_function.place_db.get_loans ()[loan];
 }
 
+const HIR::LifetimeParam *
+BorrowCheckerDiagnostics::get_lifetime_param (Polonius::Origin origin)
+
+{
+  return bir_function.region_hir_map.at (origin);
+}
+
 void
 BorrowCheckerDiagnostics::multi_label_error (
   const char *error_message, location_t error_location,
diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.h 
b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.h
index 136f4679075..9ab059152d7 100644
--- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.h
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.h
@@ -66,6 +66,7 @@ private:
 
   const BIR::Statement &get_statement (Polonius::Point point);
   const BIR::Loan &get_loan (Polonius::Loan loan);
+  const HIR::LifetimeParam *get_lifetime_param (Polonius::Origin origin);
 
   struct LabelLocationPair
   {
diff --git a/gcc/testsuite/rust/borrowck/subset.rs 
b/gcc/testsuite/rust/borrowck/subset.rs
index d7c00ca966c..5b4a663a0c3 100644
--- a/gcc/testsuite/rust/borrowck/subset.rs
+++ b/gcc/testsuite/rust/borrowck/subset.rs
@@ -1,8 +1,19 @@
-// { dg-additional-options "-frust-compile-until=compilation 
-frust-borrowcheck" }
+// { dg-additional-options "-frust-compile-until=compilation 
-frust-borrowcheck -fdiagnostics-show-caret -fdiagnostics-show-line-numbers" }
+// { dg-enable-nn-line-numbers "" }
 
 fn missing_subset<'a, 'b>(x: &'a u32, y: &'b u32) -> &'a u32 {
-    // { dg-error "Found subset errors in function missing_subset" "" { target 
*-*-* } .-1 }
+    // { dg-error "subset error, some lifetime constraints need to be added" 
"" { target *-*-* } .-1 }
     y //~ ERROR
+    /*
+     { dg-begin-multiline-output "" }
+   NN | fn missing_subset<'a, 'b>(x: &'a u32, y: &'b u32) -> &'a u32 {
+      | ^~                ~~  ~~
+      | |                 |   |
+      | |                 |   lifetime defined here
+      | |                 lifetime defined here
+      | subset error occurs in this function
+     { dg-end-multiline-output "" }
+    */
 }
 
 fn missing_subset_fixed<'a, 'b>(x: &'a u32, y: &'b u32) -> &'a u32 where 'b: 
'a {
@@ -10,12 +21,22 @@ fn missing_subset_fixed<'a, 'b>(x: &'a u32, y: &'b u32) -> 
&'a u32 where 'b: 'a
 }
 
 fn complex_cfg_subset<'a, 'b>(b: bool, x: &'a u32, y: &'b u32) -> &'a u32 {
-    // { dg-error "Found subset errors in function complex_cfg_subset" "" { 
target *-*-* } .-1 }
+    // { dg-error "subset error, some lifetime constraints need to be added" 
"" { target *-*-* } .-1 }
     if b {
         y //~ ERROR
     } else {
         x
     }
+    /*
+     { dg-begin-multiline-output "" }
+   NN | fn complex_cfg_subset<'a, 'b>(b: bool, x: &'a u32, y: &'b u32) -> &'a 
u32 {
+      | ^~                    ~~  ~~
+      | |                     |   |
+      | |                     |   lifetime defined here
+      | |                     lifetime defined here
+      | subset error occurs in this function
+     { dg-end-multiline-output "" }
+    */
 }
 
 fn complex_cfg_subset_fixed<'a, 'b>(b: bool, x: &'a u32, y: &'b u32) -> &'a 
u32 where 'b: 'a {
@@ -24,4 +45,4 @@ fn complex_cfg_subset_fixed<'a, 'b>(b: bool, x: &'a u32, y: 
&'b u32) -> &'a u32
     } else {
         y
     }
-}
\ No newline at end of file
+}
-- 
2.45.2

Reply via email to