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 "" } + */ +}