Skip to content

Commit

Permalink
Loan errors with locations
Browse files Browse the repository at this point in the history
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 <kushalpal109@gmail.com>
  • Loading branch information
braw-lee authored and CohenArthur committed Aug 2, 2024
1 parent 155f6a9 commit 65bf72f
Show file tree
Hide file tree
Showing 8 changed files with 295 additions and 32 deletions.
47 changes: 43 additions & 4 deletions gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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}});
}
}
}

Expand All @@ -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
13 changes: 13 additions & 0 deletions gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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<LabelLocationPair> location_label_pairs);
};

} // namespace BIR
Expand Down
96 changes: 87 additions & 9 deletions gcc/testsuite/rust/borrowck/reference.rs
Original file line number Diff line number Diff line change
@@ -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 {}
Expand Down Expand Up @@ -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() {
Expand All @@ -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;
}
/*
{ 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 "" }
*/
}
15 changes: 13 additions & 2 deletions gcc/testsuite/rust/borrowck/return_ref_to_local.rs
Original file line number Diff line number Diff line change
@@ -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 "" }
*/
}
Loading

0 comments on commit 65bf72f

Please sign in to comment.