https://gcc.gnu.org/g:65bf72fcfb9eca1ab3011c29510eb67faf3b02c3

commit 65bf72fcfb9eca1ab3011c29510eb67faf3b02c3
Author: Kushal Pal <kushalpal...@gmail.com>
Date:   Thu Jul 18 08:12:49 2024 +0000

    Loan errors with locations
    
    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>

Diff:
---
 .../borrowck/rust-borrow-checker-diagnostics.cc    | 47 ++++++++++-
 .../borrowck/rust-borrow-checker-diagnostics.h     | 13 +++
 gcc/testsuite/rust/borrowck/reference.rs           | 96 ++++++++++++++++++++--
 gcc/testsuite/rust/borrowck/return_ref_to_local.rs | 15 +++-
 gcc/testsuite/rust/borrowck/tmp.rs                 | 95 +++++++++++++++++++--
 gcc/testsuite/rust/borrowck/use_while_mut.rs       | 21 ++++-
 gcc/testsuite/rust/borrowck/use_while_mut_fr.rs    | 19 ++++-
 .../rust/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 a8eaa807ebb0..0365dc3bd6fe 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 90d5ed8aaef7..c46e8d848c00 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 "gcc-rich-location.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 b825a9686b75..c4b9f7d9d890 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 994dc5d358ba..ce23f918c853 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 a604bea3d91c..545a278df052 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 57ed25521a9a..a973f7dbcf30 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 736aac0279df..c2dc168b44d9 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 6815f44fc696..9102356315c7 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 "" }
+    */
+}

Reply via email to