Skip to content

Commit 93f84e5

Browse files
authored
Rollup merge of #55494 - pnkfelix:issue-55492-borrowck-migrate-must-look-at-parents-of-closures, r=davidtwco
borrowck=migrate must look at parents of closures This fixes the NLL migration mode (which is the default with edition=2018) to inspect all parents of a closure in addition to the closure itself when looking to see if AST-borrowck issues an error for the given code. This should be a candidate for beta backport. Fix #55492
2 parents 50b8879 + 87ce5ec commit 93f84e5

11 files changed

+269
-66
lines changed

src/librustc_mir/borrow_check/mod.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,33 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
346346
mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span());
347347

348348
if tcx.migrate_borrowck() {
349-
match tcx.borrowck(def_id).signalled_any_error {
349+
// When borrowck=migrate, check if AST-borrowck would
350+
// error on the given code.
351+
352+
// rust-lang/rust#55492: loop over parents to ensure that
353+
// errors that AST-borrowck only detects in some parent of
354+
// a closure still allows NLL to signal an error.
355+
let mut curr_def_id = def_id;
356+
let signalled_any_error = loop {
357+
match tcx.borrowck(curr_def_id).signalled_any_error {
358+
SignalledError::NoErrorsSeen => {
359+
// keep traversing (and borrow-checking) parents
360+
}
361+
SignalledError::SawSomeError => {
362+
// stop search here
363+
break SignalledError::SawSomeError;
364+
}
365+
}
366+
367+
if tcx.is_closure(curr_def_id) {
368+
curr_def_id = tcx.parent_def_id(curr_def_id)
369+
.expect("a closure must have a parent_def_id");
370+
} else {
371+
break SignalledError::NoErrorsSeen;
372+
}
373+
};
374+
375+
match signalled_any_error {
350376
SignalledError::NoErrorsSeen => {
351377
// if AST-borrowck signalled no errors, then
352378
// downgrade all the buffered MIR-borrowck errors

src/test/ui/borrowck/borrowck-closures-unique.nll.stderr

+2-6
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,15 @@ LL | let c2 = || set(x); //~ ERROR two closures require unique access to `x`
4040
LL | c1;
4141
| -- first borrow later used here
4242

43-
warning[E0594]: cannot assign to `x`, as it is not declared as mutable
43+
error[E0594]: cannot assign to `x`, as it is not declared as mutable
4444
--> $DIR/borrowck-closures-unique.rs:57:38
4545
|
4646
LL | fn e(x: &'static mut isize) {
4747
| - help: consider changing this to be mutable: `mut x`
4848
LL | let c1 = |y: &'static mut isize| x = y; //~ ERROR closure cannot assign to immutable argument
4949
| ^^^^^ cannot assign
50-
|
51-
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
52-
It represents potential unsoundness in your code.
53-
This warning will become a hard error in the future.
5450

55-
error: aborting due to 3 previous errors
51+
error: aborting due to 4 previous errors
5652

5753
Some errors occurred: E0500, E0524, E0594.
5854
For more information about an error, try `rustc --explain E0500`.

src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr

+2-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ LL | //[mir]~^ ERROR cannot borrow `x` as mutable more than o
2020
LL | *y = 1;
2121
| ------ first borrow later used here
2222

23-
warning: captured variable cannot escape `FnMut` closure body
23+
error: captured variable cannot escape `FnMut` closure body
2424
--> $DIR/borrowck-describe-lvalue.rs:305:16
2525
|
2626
LL | || {
@@ -36,9 +36,6 @@ LL | | }
3636
|
3737
= note: `FnMut` closures only have access to their captured variables while they are executing...
3838
= note: ...therefore, they cannot allow references to captured variables to escape
39-
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
40-
It represents potential unsoundness in your code.
41-
This warning will become a hard error in the future.
4239

4340
error[E0503]: cannot use `f.x` because it was mutably borrowed
4441
--> $DIR/borrowck-describe-lvalue.rs:53:9
@@ -382,7 +379,7 @@ LL | drop(x); //[ast]~ ERROR use of moved value: `x`
382379
|
383380
= note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
384381

385-
error: aborting due to 29 previous errors
382+
error: aborting due to 30 previous errors
386383

387384
Some errors occurred: E0382, E0499, E0502, E0503.
388385
For more information about an error, try `rustc --explain E0382`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
error[E0595]: closure cannot assign to immutable argument `x`
2+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:21:22
3+
|
4+
LL | let mut c1 = |y: &'static mut isize| x = y;
5+
| ^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow mutably
6+
help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
7+
|
8+
LL | x
9+
|
10+
11+
error[E0595]: closure cannot assign to immutable argument `x`
12+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:29:22
13+
|
14+
LL | let mut c1 = |z: &'static mut isize| {
15+
| ^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow mutably
16+
help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
17+
|
18+
LL | x
19+
|
20+
21+
error[E0595]: closure cannot assign to immutable argument `x`
22+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:40:9
23+
|
24+
LL | pub fn capture_assign_whole(x: (i32,)) {
25+
| - help: make this binding mutable: `mut x`
26+
LL | || { x = (1,); };
27+
| ^^ cannot borrow mutably
28+
29+
error[E0595]: closure cannot assign to immutable argument `x`
30+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:43:9
31+
|
32+
LL | pub fn capture_assign_part(x: (i32,)) {
33+
| - help: make this binding mutable: `mut x`
34+
LL | || { x.0 = 1; };
35+
| ^^ cannot borrow mutably
36+
37+
error[E0595]: closure cannot assign to immutable argument `x`
38+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:46:9
39+
|
40+
LL | pub fn capture_reborrow_whole(x: (i32,)) {
41+
| - help: make this binding mutable: `mut x`
42+
LL | || { &mut x; };
43+
| ^^ cannot borrow mutably
44+
45+
error[E0595]: closure cannot assign to immutable argument `x`
46+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:49:9
47+
|
48+
LL | pub fn capture_reborrow_part(x: (i32,)) {
49+
| - help: make this binding mutable: `mut x`
50+
LL | || { &mut x.0; };
51+
| ^^ cannot borrow mutably
52+
53+
error: aborting due to 6 previous errors
54+
55+
For more information about this error, try `rustc --explain E0595`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
error[E0594]: cannot assign to `x`, as it is not declared as mutable
2+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:21:46
3+
|
4+
LL | pub fn e(x: &'static mut isize) {
5+
| - help: consider changing this to be mutable: `mut x`
6+
LL | static mut Y: isize = 3;
7+
LL | let mut c1 = |y: &'static mut isize| x = y;
8+
| ^^^^^ cannot assign
9+
10+
error[E0594]: cannot assign to `x`, as it is not declared as mutable
11+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:30:50
12+
|
13+
LL | pub fn ee(x: &'static mut isize) {
14+
| - help: consider changing this to be mutable: `mut x`
15+
...
16+
LL | let mut c2 = |y: &'static mut isize| x = y;
17+
| ^^^^^ cannot assign
18+
19+
error[E0594]: cannot assign to `x`, as it is not declared as mutable
20+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:40:14
21+
|
22+
LL | pub fn capture_assign_whole(x: (i32,)) {
23+
| - help: consider changing this to be mutable: `mut x`
24+
LL | || { x = (1,); };
25+
| ^^^^^^^^ cannot assign
26+
27+
error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
28+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:43:14
29+
|
30+
LL | pub fn capture_assign_part(x: (i32,)) {
31+
| - help: consider changing this to be mutable: `mut x`
32+
LL | || { x.0 = 1; };
33+
| ^^^^^^^ cannot assign
34+
35+
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
36+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:46:14
37+
|
38+
LL | pub fn capture_reborrow_whole(x: (i32,)) {
39+
| - help: consider changing this to be mutable: `mut x`
40+
LL | || { &mut x; };
41+
| ^^^^^^ cannot borrow as mutable
42+
43+
error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
44+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:49:14
45+
|
46+
LL | pub fn capture_reborrow_part(x: (i32,)) {
47+
| - help: consider changing this to be mutable: `mut x`
48+
LL | || { &mut x.0; };
49+
| ^^^^^^^^ cannot borrow as mutable
50+
51+
error: aborting due to 6 previous errors
52+
53+
Some errors occurred: E0594, E0596.
54+
For more information about an error, try `rustc --explain E0594`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
error[E0594]: cannot assign to `x`, as it is not declared as mutable
2+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:21:46
3+
|
4+
LL | pub fn e(x: &'static mut isize) {
5+
| - help: consider changing this to be mutable: `mut x`
6+
LL | static mut Y: isize = 3;
7+
LL | let mut c1 = |y: &'static mut isize| x = y;
8+
| ^^^^^ cannot assign
9+
10+
error[E0594]: cannot assign to `x`, as it is not declared as mutable
11+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:30:50
12+
|
13+
LL | pub fn ee(x: &'static mut isize) {
14+
| - help: consider changing this to be mutable: `mut x`
15+
...
16+
LL | let mut c2 = |y: &'static mut isize| x = y;
17+
| ^^^^^ cannot assign
18+
19+
error[E0594]: cannot assign to `x`, as it is not declared as mutable
20+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:40:14
21+
|
22+
LL | pub fn capture_assign_whole(x: (i32,)) {
23+
| - help: consider changing this to be mutable: `mut x`
24+
LL | || { x = (1,); };
25+
| ^^^^^^^^ cannot assign
26+
27+
error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
28+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:43:14
29+
|
30+
LL | pub fn capture_assign_part(x: (i32,)) {
31+
| - help: consider changing this to be mutable: `mut x`
32+
LL | || { x.0 = 1; };
33+
| ^^^^^^^ cannot assign
34+
35+
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
36+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:46:14
37+
|
38+
LL | pub fn capture_reborrow_whole(x: (i32,)) {
39+
| - help: consider changing this to be mutable: `mut x`
40+
LL | || { &mut x; };
41+
| ^^^^^^ cannot borrow as mutable
42+
43+
error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
44+
--> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:49:14
45+
|
46+
LL | pub fn capture_reborrow_part(x: (i32,)) {
47+
| - help: consider changing this to be mutable: `mut x`
48+
LL | || { &mut x.0; };
49+
| ^^^^^^^^ cannot borrow as mutable
50+
51+
error: aborting due to 6 previous errors
52+
53+
Some errors occurred: E0594, E0596.
54+
For more information about an error, try `rustc --explain E0594`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// rust-lang/rust#55492: errors detected during MIR-borrowck's
2+
// analysis of a closure body may only be caught when AST-borrowck
3+
// looks at some parent.
4+
5+
// revisions: ast migrate nll
6+
7+
// Since we are testing nll (and migration) explicitly as a separate
8+
// revisions, don't worry about the --compare-mode=nll on this test.
9+
10+
// ignore-compare-mode-nll
11+
12+
//[ast]compile-flags: -Z borrowck=ast
13+
//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
14+
//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows
15+
16+
17+
// transcribed from borrowck-closures-unique.rs
18+
mod borrowck_closures_unique {
19+
pub fn e(x: &'static mut isize) {
20+
static mut Y: isize = 3;
21+
let mut c1 = |y: &'static mut isize| x = y;
22+
unsafe { c1(&mut Y); }
23+
}
24+
}
25+
26+
mod borrowck_closures_unique_grandparent {
27+
pub fn ee(x: &'static mut isize) {
28+
static mut Z: isize = 3;
29+
let mut c1 = |z: &'static mut isize| {
30+
let mut c2 = |y: &'static mut isize| x = y;
31+
c2(z);
32+
};
33+
unsafe { c1(&mut Z); }
34+
}
35+
}
36+
37+
// adapted from mutability_errors.rs
38+
mod mutability_errors {
39+
pub fn capture_assign_whole(x: (i32,)) {
40+
|| { x = (1,); };
41+
}
42+
pub fn capture_assign_part(x: (i32,)) {
43+
|| { x.0 = 1; };
44+
}
45+
pub fn capture_reborrow_whole(x: (i32,)) {
46+
|| { &mut x; };
47+
}
48+
pub fn capture_reborrow_part(x: (i32,)) {
49+
|| { &mut x.0; };
50+
}
51+
}
52+
53+
fn main() {
54+
static mut X: isize = 2;
55+
unsafe { borrowck_closures_unique::e(&mut X); }
56+
57+
mutability_errors::capture_assign_whole((1000,));
58+
mutability_errors::capture_assign_part((2000,));
59+
mutability_errors::capture_reborrow_whole((3000,));
60+
mutability_errors::capture_reborrow_part((4000,));
61+
}

src/test/ui/borrowck/mutability-errors.nll.stderr

+5-21
Original file line numberDiff line numberDiff line change
@@ -277,57 +277,41 @@ LL | &mut x; //~ ERROR
277277
LL | &mut x.0; //~ ERROR
278278
| ^^^^^^^^ cannot borrow as mutable
279279

280-
warning[E0594]: cannot assign to `x`, as it is not declared as mutable
280+
error[E0594]: cannot assign to `x`, as it is not declared as mutable
281281
--> $DIR/mutability-errors.rs:70:9
282282
|
283283
LL | fn imm_capture(x: (i32,)) {
284284
| - help: consider changing this to be mutable: `mut x`
285285
LL | || { //~ ERROR
286286
LL | x = (1,);
287287
| ^^^^^^^^ cannot assign
288-
|
289-
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
290-
It represents potential unsoundness in your code.
291-
This warning will become a hard error in the future.
292288

293-
warning[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
289+
error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
294290
--> $DIR/mutability-errors.rs:71:9
295291
|
296292
LL | fn imm_capture(x: (i32,)) {
297293
| - help: consider changing this to be mutable: `mut x`
298294
...
299295
LL | x.0 = 1;
300296
| ^^^^^^^ cannot assign
301-
|
302-
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
303-
It represents potential unsoundness in your code.
304-
This warning will become a hard error in the future.
305297

306-
warning[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
298+
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
307299
--> $DIR/mutability-errors.rs:72:9
308300
|
309301
LL | fn imm_capture(x: (i32,)) {
310302
| - help: consider changing this to be mutable: `mut x`
311303
...
312304
LL | &mut x;
313305
| ^^^^^^ cannot borrow as mutable
314-
|
315-
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
316-
It represents potential unsoundness in your code.
317-
This warning will become a hard error in the future.
318306

319-
warning[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
307+
error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
320308
--> $DIR/mutability-errors.rs:73:9
321309
|
322310
LL | fn imm_capture(x: (i32,)) {
323311
| - help: consider changing this to be mutable: `mut x`
324312
...
325313
LL | &mut x.0;
326314
| ^^^^^^^^ cannot borrow as mutable
327-
|
328-
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
329-
It represents potential unsoundness in your code.
330-
This warning will become a hard error in the future.
331315

332316
error[E0594]: cannot assign to `x`, as it is not declared as mutable
333317
--> $DIR/mutability-errors.rs:76:9
@@ -389,7 +373,7 @@ error[E0596]: cannot borrow `X.0` as mutable, as `X` is an immutable static item
389373
LL | &mut X.0; //~ ERROR
390374
| ^^^^^^^^ cannot borrow as mutable
391375

392-
error: aborting due to 34 previous errors
376+
error: aborting due to 38 previous errors
393377

394378
Some errors occurred: E0594, E0596.
395379
For more information about an error, try `rustc --explain E0594`.

0 commit comments

Comments
 (0)