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

gcc/rust/ChangeLog:

        * checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
        (BorrowCheckerDiagnostics::report_loan_errors): Add label to
        where the borrow occurs and where the invalid access occurs.
        (BorrowCheckerDiagnostics::get_statement):
        Fetch BIR::Statement from Polonius::Point
        (BorrowCheckerDiagnostics::get_loan):
        Fetch BIR::Loan from Polonius::Loan
        * checks/errors/borrowck/rust-borrow-checker-diagnostics.h:
        Function definition of helpers.

gcc/testsuite/ChangeLog:

        * rust/borrowck/reference.rs: Test rich errors for
        borrow-checker.
        * rust/borrowck/return_ref_to_local.rs: Likewise.
        * rust/borrowck/tmp.rs: Likewise.
        * rust/borrowck/use_while_mut.rs: Likewise.
        * rust/borrowck/use_while_mut_fr.rs: Likewise.
        * rust/borrowck/well_formed_function_inputs.rs: Likewise.

Signed-off-by: Kushal Pal <kushalpal...@gmail.com>
---
 .../rust-borrow-checker-diagnostics.cc        | 47 ++++++++-
 .../rust-borrow-checker-diagnostics.h         | 13 +++
 gcc/testsuite/rust/borrowck/reference.rs      | 96 +++++++++++++++++--
 .../rust/borrowck/return_ref_to_local.rs      | 15 ++-
 gcc/testsuite/rust/borrowck/tmp.rs            | 95 ++++++++++++++++--
 gcc/testsuite/rust/borrowck/use_while_mut.rs  | 21 +++-
 .../rust/borrowck/use_while_mut_fr.rs         | 19 +++-
 .../borrowck/well_formed_function_inputs.rs   | 21 +++-
 8 files changed, 295 insertions(+), 32 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 a8eaa807ebb..0365dc3bd6f 100644
--- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
@@ -17,6 +17,8 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-borrow-checker-diagnostics.h"
+#include "polonius/rust-polonius-ffi.h"
+#include "rust-diagnostics.h"
 
 namespace Rust {
 namespace BIR {
@@ -43,11 +45,16 @@ BorrowCheckerDiagnostics::report_move_errors ()
 void
 BorrowCheckerDiagnostics::report_loan_errors ()
 {
-  if (!loan_errors.empty ())
+  for (const auto &pair : loan_errors)
     {
-      rust_error_at (hir_function->get_locus (),
-                    "Found loan errors in function %s",
-                    hir_function->get_function_name ().as_string ().c_str ());
+      auto error_location = get_statement (pair.first).get_location ();
+      for (const auto &loan : pair.second)
+       {
+         auto loan_struct = get_loan (loan);
+         multi_label_error ("use of borrowed value", error_location,
+                            {{"borrow occurs here", loan_struct.location},
+                             {"borrowed value used here", error_location}});
+       }
     }
 }
 
@@ -63,5 +70,37 @@ BorrowCheckerDiagnostics::report_subset_errors ()
     }
 }
 
+const BIR::Statement &
+BorrowCheckerDiagnostics::get_statement (Polonius::Point point)
+{
+  auto statement_index = Polonius::FullPoint::extract_stmt (point);
+  auto bb_index = Polonius::FullPoint::extract_bb (point);
+  // assert that the extracted indexes are valid
+  rust_assert (bb_index < bir_function.basic_blocks.size ());
+  rust_assert (statement_index
+              < bir_function.basic_blocks[bb_index].statements.size ());
+  return bir_function.basic_blocks[bb_index].statements[statement_index];
+}
+
+const BIR::Loan &
+BorrowCheckerDiagnostics::get_loan (Polonius::Loan loan)
+{
+  return bir_function.place_db.get_loans ()[loan];
+}
+
+void
+BorrowCheckerDiagnostics::multi_label_error (
+  const char *error_message, location_t error_location,
+  std::vector<LabelLocationPair> location_label_pairs)
+{
+  rich_location r{line_table, error_location};
+  for (auto &label_location : location_label_pairs)
+    {
+      r.add_range (label_location.location, SHOW_RANGE_WITHOUT_CARET,
+                  &label_location.label);
+    }
+  rust_error_at (r, "%s", error_message);
+}
+
 } // namespace BIR
 } // namespace Rust
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 90d5ed8aaef..136f4679075 100644
--- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.h
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.h
@@ -22,6 +22,7 @@
 #include "polonius/rust-polonius.h"
 #include "rust-bir.h"
 #include "rust-hir-item.h"
+#include "text-range-label.h"
 
 namespace Rust {
 namespace BIR {
@@ -62,6 +63,18 @@ private:
   void report_move_errors ();
   void report_loan_errors ();
   void report_subset_errors ();
+
+  const BIR::Statement &get_statement (Polonius::Point point);
+  const BIR::Loan &get_loan (Polonius::Loan loan);
+
+  struct LabelLocationPair
+  {
+    text_range_label label;
+    location_t location;
+  };
+  static void
+  multi_label_error (const char *error_message, location_t error_location,
+                    std::vector<LabelLocationPair> location_label_pairs);
 };
 
 } // namespace BIR
diff --git a/gcc/testsuite/rust/borrowck/reference.rs 
b/gcc/testsuite/rust/borrowck/reference.rs
index b825a9686b7..c4b9f7d9d89 100644
--- a/gcc/testsuite/rust/borrowck/reference.rs
+++ b/gcc/testsuite/rust/borrowck/reference.rs
@@ -1,5 +1,5 @@
-// { 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 "" }
 
 #[lang = "sized"]
 pub trait Sized {}
@@ -32,27 +32,63 @@ fn immutable_borrow_while_immutable_borrowed_struct() {
 }
 
 fn immutable_borrow_while_mutable_borrowed_struct() {
-    // { dg-error "Found loan errors in function 
immutable_borrow_while_mutable_borrowed_struct" "" { target *-*-* } .-1 }
     let mut x = 0;
     let y = ReferenceMut::new(&mut x);
     let z = &x; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let w = y;
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = ReferenceMut::new(&mut x);
+      |                               ~
+      |                               |
+      |                               borrow occurs here
+   NN |     let z = &x; //~ ERROR
+      |             ^
+      |             |
+      |             borrowed value used here
+     { dg-end-multiline-output "" }
+     */
 }
 
 fn mutable_borrow_while_immutable_borrowed_struct() {
-    // { dg-error "Found loan errors in function 
mutable_borrow_while_immutable_borrowed_struct" "" { target *-*-* } .-1 }
     let x = 0;
     let y = Reference::new(&x);
     let z = &mut x; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let w = y;
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = Reference::new(&x);
+      |                            ~
+      |                            |
+      |                            borrow occurs here
+   NN |     let z = &mut x; //~ ERROR
+      |             ^
+      |             |
+      |             borrowed value used here
+     { dg-end-multiline-output "" }
+     */
 }
 
 fn mutable_borrow_while_mutable_borrowed_struct() {
-    // { dg-error "Found loan errors in function 
mutable_borrow_while_mutable_borrowed_struct" "" { target *-*-* } .-1 }
     let mut x = 0;
     let y = ReferenceMut::new(&mut x);
     let z = &mut x; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let w = y;
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = ReferenceMut::new(&mut x);
+      |                               ~
+      |                               |
+      |                               borrow occurs here
+   NN |     let z = &mut x; //~ ERROR
+      |             ^
+      |             |
+      |             borrowed value used here
+     { dg-end-multiline-output "" }
+     */
 }
 
 fn immutable_reborrow_while_immutable_borrowed_struct() {
@@ -69,31 +105,73 @@ fn immutable_reborrow_while_mutable_borrowed_struct() {
 
 fn mutable_reborrow_while_immutable_borrowed_struct() {
     // { dg-error "Cannot reborrow immutable borrow as mutable" "" { target 
*-*-* } .-1 }
+    /*
+    { dg-begin-multiline-output "" }
+   NN | fn mutable_reborrow_while_immutable_borrowed_struct() {
+      | ^~
+    { dg-end-multiline-output "" }
+    */
     let x = 0;
     let y = Reference::new(&x);
     let z = &mut *y.value; //~ ERROR
 }
 
 fn read_while_mutable_borrowed_struct() {
-    // { dg-error "Found loan errors in function 
read_while_mutable_borrowed_struct" "" { target *-*-* } .-1 }
     let mut x = 0;
     let y = ReferenceMut::new(&mut x);
     let z = x; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let w = y;
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = ReferenceMut::new(&mut x);
+      |                               ~
+      |                               |
+      |                               borrow occurs here
+   NN |     let z = x; //~ ERROR
+      |             ^
+      |             |
+      |             borrowed value used here
+     { dg-end-multiline-output "" }
+     */
 }
 
 fn write_while_borrowed_struct() {
-    // { dg-error "Found loan errors in function write_while_borrowed_struct" 
"" { target *-*-* } .-1 }
     let mut x = 0;
     let y = Reference::new(&x);
     x = 1; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let z = y;
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = Reference::new(&x);
+      |                            ~
+      |                            |
+      |                            borrow occurs here
+   NN |     x = 1; //~ ERROR
+      |     ^
+      |     |
+      |     borrowed value used here
+     { dg-end-multiline-output "" }
+     */
 }
 
 fn write_while_immutable_borrowed_struct() {
-    // { dg-error "Found loan errors in function 
write_while_immutable_borrowed_struct" "" { target *-*-* } .-1 }
     let x = 0;
     let y = Reference::new(&x);
     x = 1; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let z = y;
-}
\ No newline at end of file
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = Reference::new(&x);
+      |                            ~
+      |                            |
+      |                            borrow occurs here
+   NN |     x = 1; //~ ERROR
+      |     ^
+      |     |
+      |     borrowed value used here
+     { dg-end-multiline-output "" }
+     */
+}
diff --git a/gcc/testsuite/rust/borrowck/return_ref_to_local.rs 
b/gcc/testsuite/rust/borrowck/return_ref_to_local.rs
index 994dc5d358b..ce23f918c85 100644
--- a/gcc/testsuite/rust/borrowck/return_ref_to_local.rs
+++ b/gcc/testsuite/rust/borrowck/return_ref_to_local.rs
@@ -1,6 +1,17 @@
-// { 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 "" }
 
-pub fn return_ref_to_local() -> &'static i32 { // { dg-error "Found loan 
errors in function return_ref_to_local" }
+pub fn return_ref_to_local() -> &'static i32 {
     let x = 0;
     &x //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     &x //~ ERROR
+      |     ^
+      |     |
+      |     borrow occurs here
+      |     borrowed value used here
+     { dg-end-multiline-output "" }
+    */
 }
diff --git a/gcc/testsuite/rust/borrowck/tmp.rs 
b/gcc/testsuite/rust/borrowck/tmp.rs
index a604bea3d91..545a278df05 100644
--- a/gcc/testsuite/rust/borrowck/tmp.rs
+++ b/gcc/testsuite/rust/borrowck/tmp.rs
@@ -1,4 +1,5 @@
-// { 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 "" }
 
 #[lang = "sized"]
 pub trait Sized {}
@@ -12,27 +13,63 @@ fn immutable_borrow_while_immutable_borrowed() {
 
 
 fn immutable_borrow_while_mutable_borrowed() {
-    // { dg-error "Found loan errors in function 
immutable_borrow_while_mutable_borrowed" "" { target *-*-* } .-1 }
     let mut x = 0;
     let y = &mut x;
     let z = &x; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let w = y;
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = &mut x;
+      |             ~
+      |             |
+      |             borrow occurs here
+   NN |     let z = &x; //~ ERROR
+      |             ^
+      |             |
+      |             borrowed value used here
+     { dg-end-multiline-output "" }
+    */
 }
 
 fn mutable_borrow_while_immutable_borrowed() {
-    // { dg-error "Found loan errors in function 
mutable_borrow_while_immutable_borrowed" "" { target *-*-* } .-1 }
     let x = 0;
     let y = &x;
     let z = &mut x; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let w = y;
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = &x;
+      |             ~
+      |             |
+      |             borrow occurs here
+   NN |     let z = &mut x; //~ ERROR
+      |             ^
+      |             |
+      |             borrowed value used here
+     { dg-end-multiline-output "" }
+    */
 }
 
 fn mutable_borrow_while_mutable_borrowed() {
-    // { dg-error "Found loan errors in function 
mutable_borrow_while_mutable_borrowed" "" { target *-*-* } .-1 }
     let mut x = 0;
     let y = &mut x;
     let z = &mut x; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let w = y;
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = &mut x;
+      |             ~
+      |             |
+      |             borrow occurs here
+   NN |     let z = &mut x; //~ ERROR
+      |             ^
+      |             |
+      |             borrowed value used here
+     { dg-end-multiline-output "" }
+    */
 }
 
 fn immutable_reborrow_while_immutable_borrowed() {
@@ -52,28 +89,70 @@ fn mutable_reborrow_while_immutable_borrowed() {
     let x = 0;
     let y = &x;
     let z = &mut *y; //~ ERROR
+    /*
+     { dg-begin-multiline-output "" }
+   NN | fn mutable_reborrow_while_immutable_borrowed() {
+      | ^~
+     { dg-end-multiline-output "" }
+    */
 }
 
 fn read_while_mutable_borrowed() {
-    // { dg-error "Found loan errors in function read_while_mutable_borrowed" 
"" { target *-*-* } .-1 }
     let mut x = 0;
     let y = &mut x;
     let z = x; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let w = y;
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = &mut x;
+      |             ~
+      |             |
+      |             borrow occurs here
+   NN |     let z = x; //~ ERROR
+      |             ^
+      |             |
+      |             borrowed value used here
+     { dg-end-multiline-output "" }
+    */
 }
 
 fn write_while_borrowed() {
-    // { dg-error "Found loan errors in function write_while_borrowed" "" { 
target *-*-* } .-1 }
     let mut x = 0;
     let y = &x;
     x = 1; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let z = y;
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = &x;
+      |             ~
+      |             |
+      |             borrow occurs here
+   NN |     x = 1; //~ ERROR
+      |     ^
+      |     |
+      |     borrowed value used here
+     { dg-end-multiline-output "" }
+    */
 }
 
 fn write_while_immutable_borrowed() {
-    // { dg-error "Found loan errors in function 
write_while_immutable_borrowed" "" { target *-*-* } .-1 }
     let x = 0;
     let y = &x;
     x = 1; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let z = y;
-}
\ No newline at end of file
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = &x;
+      |             ~
+      |             |
+      |             borrow occurs here
+   NN |     x = 1; //~ ERROR
+      |     ^
+      |     |
+      |     borrowed value used here
+     { dg-end-multiline-output "" }
+    */
+}
diff --git a/gcc/testsuite/rust/borrowck/use_while_mut.rs 
b/gcc/testsuite/rust/borrowck/use_while_mut.rs
index 57ed25521a9..a973f7dbcf3 100644
--- a/gcc/testsuite/rust/borrowck/use_while_mut.rs
+++ b/gcc/testsuite/rust/borrowck/use_while_mut.rs
@@ -1,7 +1,22 @@
-// { dg-additional-options "-frust-compile-until=compilation 
-frust-borrowcheck" }
-pub fn use_while_mut() {  // { dg-error "Found loan errors in function 
use_while_mut" }
+// { dg-additional-options "-frust-compile-until=compilation 
-frust-borrowcheck -fdiagnostics-show-caret -fdiagnostics-show-line-numbers" }
+// { dg-enable-nn-line-numbers "" }
+
+pub fn use_while_mut() {
     let mut x = 0;
     let y = &mut x;
     let z = x; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     let w = y;
-}
\ No newline at end of file
+    /*
+    { dg-begin-multiline-output "" }
+   NN |     let y = &mut x;
+      |             ~
+      |             |
+      |             borrow occurs here
+   NN |     let z = x; //~ ERROR
+      |             ^
+      |             |
+      |             borrowed value used here
+        { dg-end-multiline-output "" }
+    */
+}
diff --git a/gcc/testsuite/rust/borrowck/use_while_mut_fr.rs 
b/gcc/testsuite/rust/borrowck/use_while_mut_fr.rs
index 736aac0279d..c2dc168b44d 100644
--- a/gcc/testsuite/rust/borrowck/use_while_mut_fr.rs
+++ b/gcc/testsuite/rust/borrowck/use_while_mut_fr.rs
@@ -1,8 +1,21 @@
-// { dg-additional-options "-frust-compile-until=compilation 
-frust-borrowcheck" }
-
-pub fn use_while_mut_fr(x: &mut i32) -> &mut i32 {  // { dg-error "Found loan 
errors in function use_while_mut_fr" }
+// { dg-additional-options "-frust-compile-until=compilation 
-frust-borrowcheck -fdiagnostics-show-caret -fdiagnostics-show-line-numbers" }
+// { dg-enable-nn-line-numbers "" }
+pub fn use_while_mut_fr(x: &mut i32) -> &mut i32 {
     let y = &mut *x;
     let z = x; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     y
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let y = &mut *x;
+      |             ~
+      |             |
+      |             borrow occurs here
+   NN |     let z = x; //~ ERROR
+      |             ^
+      |             |
+      |             borrowed value used here
+     { dg-end-multiline-output "" }
+    */
 }
 
diff --git a/gcc/testsuite/rust/borrowck/well_formed_function_inputs.rs 
b/gcc/testsuite/rust/borrowck/well_formed_function_inputs.rs
index 6815f44fc69..9102356315c 100644
--- a/gcc/testsuite/rust/borrowck/well_formed_function_inputs.rs
+++ b/gcc/testsuite/rust/borrowck/well_formed_function_inputs.rs
@@ -1,10 +1,11 @@
-// { 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 foo<'a, 'b>(p: &'b &'a mut usize) -> &'b&'a mut usize {
     p
 }
 
-fn well_formed_function_inputs() { // { dg-error "Found loan errors in 
function well_formed_function_inputs" }
+fn well_formed_function_inputs() {
     let s = &mut 1;
     let r = &mut *s;
     let tmp = foo(&r  );
@@ -12,5 +13,19 @@ fn well_formed_function_inputs() { // { dg-error "Found loan 
errors in function
     // let aarg = &*arg;
     // let tmp = arg;
     s; //~ ERROR
+    // { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
     tmp;
-}
\ No newline at end of file
+    /*
+     { dg-begin-multiline-output "" }
+   NN |     let r = &mut *s;
+      |             ~
+      |             |
+      |             borrow occurs here
+......
+   NN |     s; //~ ERROR
+      |     ^
+      |     |
+      |     borrowed value used here
+     { dg-end-multiline-output "" }
+    */
+}
-- 
2.45.2

Reply via email to