Skip to content

Commit 65bf72f

Browse files
braw-leeCohenArthur
authored andcommitted
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 <[email protected]>
1 parent 155f6a9 commit 65bf72f

8 files changed

+295
-32
lines changed

gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
// <http://www.gnu.org/licenses/>.
1818

1919
#include "rust-borrow-checker-diagnostics.h"
20+
#include "polonius/rust-polonius-ffi.h"
21+
#include "rust-diagnostics.h"
2022

2123
namespace Rust {
2224
namespace BIR {
@@ -43,11 +45,16 @@ BorrowCheckerDiagnostics::report_move_errors ()
4345
void
4446
BorrowCheckerDiagnostics::report_loan_errors ()
4547
{
46-
if (!loan_errors.empty ())
48+
for (const auto &pair : loan_errors)
4749
{
48-
rust_error_at (hir_function->get_locus (),
49-
"Found loan errors in function %s",
50-
hir_function->get_function_name ().as_string ().c_str ());
50+
auto error_location = get_statement (pair.first).get_location ();
51+
for (const auto &loan : pair.second)
52+
{
53+
auto loan_struct = get_loan (loan);
54+
multi_label_error ("use of borrowed value", error_location,
55+
{{"borrow occurs here", loan_struct.location},
56+
{"borrowed value used here", error_location}});
57+
}
5158
}
5259
}
5360

@@ -63,5 +70,37 @@ BorrowCheckerDiagnostics::report_subset_errors ()
6370
}
6471
}
6572

73+
const BIR::Statement &
74+
BorrowCheckerDiagnostics::get_statement (Polonius::Point point)
75+
{
76+
auto statement_index = Polonius::FullPoint::extract_stmt (point);
77+
auto bb_index = Polonius::FullPoint::extract_bb (point);
78+
// assert that the extracted indexes are valid
79+
rust_assert (bb_index < bir_function.basic_blocks.size ());
80+
rust_assert (statement_index
81+
< bir_function.basic_blocks[bb_index].statements.size ());
82+
return bir_function.basic_blocks[bb_index].statements[statement_index];
83+
}
84+
85+
const BIR::Loan &
86+
BorrowCheckerDiagnostics::get_loan (Polonius::Loan loan)
87+
{
88+
return bir_function.place_db.get_loans ()[loan];
89+
}
90+
91+
void
92+
BorrowCheckerDiagnostics::multi_label_error (
93+
const char *error_message, location_t error_location,
94+
std::vector<LabelLocationPair> location_label_pairs)
95+
{
96+
rich_location r{line_table, error_location};
97+
for (auto &label_location : location_label_pairs)
98+
{
99+
r.add_range (label_location.location, SHOW_RANGE_WITHOUT_CARET,
100+
&label_location.label);
101+
}
102+
rust_error_at (r, "%s", error_message);
103+
}
104+
66105
} // namespace BIR
67106
} // namespace Rust

gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "polonius/rust-polonius.h"
2323
#include "rust-bir.h"
2424
#include "rust-hir-item.h"
25+
#include "gcc-rich-location.h"
2526

2627
namespace Rust {
2728
namespace BIR {
@@ -62,6 +63,18 @@ class BorrowCheckerDiagnostics
6263
void report_move_errors ();
6364
void report_loan_errors ();
6465
void report_subset_errors ();
66+
67+
const BIR::Statement &get_statement (Polonius::Point point);
68+
const BIR::Loan &get_loan (Polonius::Loan loan);
69+
70+
struct LabelLocationPair
71+
{
72+
text_range_label label;
73+
location_t location;
74+
};
75+
static void
76+
multi_label_error (const char *error_message, location_t error_location,
77+
std::vector<LabelLocationPair> location_label_pairs);
6578
};
6679

6780
} // namespace BIR

gcc/testsuite/rust/borrowck/reference.rs

Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// { dg-additional-options "-frust-compile-until=compilation -frust-borrowcheck" }
2-
1+
// { dg-additional-options "-frust-compile-until=compilation -frust-borrowcheck -fdiagnostics-show-caret -fdiagnostics-show-line-numbers" }
2+
// { dg-enable-nn-line-numbers "" }
33

44
#[lang = "sized"]
55
pub trait Sized {}
@@ -32,27 +32,63 @@ fn immutable_borrow_while_immutable_borrowed_struct() {
3232
}
3333

3434
fn immutable_borrow_while_mutable_borrowed_struct() {
35-
// { dg-error "Found loan errors in function immutable_borrow_while_mutable_borrowed_struct" "" { target *-*-* } .-1 }
3635
let mut x = 0;
3736
let y = ReferenceMut::new(&mut x);
3837
let z = &x; //~ ERROR
38+
// { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
3939
let w = y;
40+
/*
41+
{ dg-begin-multiline-output "" }
42+
NN | let y = ReferenceMut::new(&mut x);
43+
| ~
44+
| |
45+
| borrow occurs here
46+
NN | let z = &x; //~ ERROR
47+
| ^
48+
| |
49+
| borrowed value used here
50+
{ dg-end-multiline-output "" }
51+
*/
4052
}
4153

4254
fn mutable_borrow_while_immutable_borrowed_struct() {
43-
// { dg-error "Found loan errors in function mutable_borrow_while_immutable_borrowed_struct" "" { target *-*-* } .-1 }
4455
let x = 0;
4556
let y = Reference::new(&x);
4657
let z = &mut x; //~ ERROR
58+
// { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
4759
let w = y;
60+
/*
61+
{ dg-begin-multiline-output "" }
62+
NN | let y = Reference::new(&x);
63+
| ~
64+
| |
65+
| borrow occurs here
66+
NN | let z = &mut x; //~ ERROR
67+
| ^
68+
| |
69+
| borrowed value used here
70+
{ dg-end-multiline-output "" }
71+
*/
4872
}
4973

5074
fn mutable_borrow_while_mutable_borrowed_struct() {
51-
// { dg-error "Found loan errors in function mutable_borrow_while_mutable_borrowed_struct" "" { target *-*-* } .-1 }
5275
let mut x = 0;
5376
let y = ReferenceMut::new(&mut x);
5477
let z = &mut x; //~ ERROR
78+
// { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
5579
let w = y;
80+
/*
81+
{ dg-begin-multiline-output "" }
82+
NN | let y = ReferenceMut::new(&mut x);
83+
| ~
84+
| |
85+
| borrow occurs here
86+
NN | let z = &mut x; //~ ERROR
87+
| ^
88+
| |
89+
| borrowed value used here
90+
{ dg-end-multiline-output "" }
91+
*/
5692
}
5793

5894
fn immutable_reborrow_while_immutable_borrowed_struct() {
@@ -69,31 +105,73 @@ fn immutable_reborrow_while_mutable_borrowed_struct() {
69105

70106
fn mutable_reborrow_while_immutable_borrowed_struct() {
71107
// { dg-error "Cannot reborrow immutable borrow as mutable" "" { target *-*-* } .-1 }
108+
/*
109+
{ dg-begin-multiline-output "" }
110+
NN | fn mutable_reborrow_while_immutable_borrowed_struct() {
111+
| ^~
112+
{ dg-end-multiline-output "" }
113+
*/
72114
let x = 0;
73115
let y = Reference::new(&x);
74116
let z = &mut *y.value; //~ ERROR
75117
}
76118

77119
fn read_while_mutable_borrowed_struct() {
78-
// { dg-error "Found loan errors in function read_while_mutable_borrowed_struct" "" { target *-*-* } .-1 }
79120
let mut x = 0;
80121
let y = ReferenceMut::new(&mut x);
81122
let z = x; //~ ERROR
123+
// { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
82124
let w = y;
125+
/*
126+
{ dg-begin-multiline-output "" }
127+
NN | let y = ReferenceMut::new(&mut x);
128+
| ~
129+
| |
130+
| borrow occurs here
131+
NN | let z = x; //~ ERROR
132+
| ^
133+
| |
134+
| borrowed value used here
135+
{ dg-end-multiline-output "" }
136+
*/
83137
}
84138

85139
fn write_while_borrowed_struct() {
86-
// { dg-error "Found loan errors in function write_while_borrowed_struct" "" { target *-*-* } .-1 }
87140
let mut x = 0;
88141
let y = Reference::new(&x);
89142
x = 1; //~ ERROR
143+
// { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
90144
let z = y;
145+
/*
146+
{ dg-begin-multiline-output "" }
147+
NN | let y = Reference::new(&x);
148+
| ~
149+
| |
150+
| borrow occurs here
151+
NN | x = 1; //~ ERROR
152+
| ^
153+
| |
154+
| borrowed value used here
155+
{ dg-end-multiline-output "" }
156+
*/
91157
}
92158

93159
fn write_while_immutable_borrowed_struct() {
94-
// { dg-error "Found loan errors in function write_while_immutable_borrowed_struct" "" { target *-*-* } .-1 }
95160
let x = 0;
96161
let y = Reference::new(&x);
97162
x = 1; //~ ERROR
163+
// { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
98164
let z = y;
99-
}
165+
/*
166+
{ dg-begin-multiline-output "" }
167+
NN | let y = Reference::new(&x);
168+
| ~
169+
| |
170+
| borrow occurs here
171+
NN | x = 1; //~ ERROR
172+
| ^
173+
| |
174+
| borrowed value used here
175+
{ dg-end-multiline-output "" }
176+
*/
177+
}
Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
1-
// { dg-additional-options "-frust-compile-until=compilation -frust-borrowcheck" }
1+
// { dg-additional-options "-frust-compile-until=compilation -frust-borrowcheck -fdiagnostics-show-caret -fdiagnostics-show-line-numbers" }
2+
// { dg-enable-nn-line-numbers "" }
23

3-
pub fn return_ref_to_local() -> &'static i32 { // { dg-error "Found loan errors in function return_ref_to_local" }
4+
pub fn return_ref_to_local() -> &'static i32 {
45
let x = 0;
56
&x //~ ERROR
7+
// { dg-error "use of borrowed value" "" { target *-*-* } .-1 }
8+
/*
9+
{ dg-begin-multiline-output "" }
10+
NN | &x //~ ERROR
11+
| ^
12+
| |
13+
| borrow occurs here
14+
| borrowed value used here
15+
{ dg-end-multiline-output "" }
16+
*/
617
}

0 commit comments

Comments
 (0)