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 @@
// .
#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 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 @@ class BorrowCheckerDiagnostics
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 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 "" }
+ */
+}