Skip to content

Commit e7f5d48

Browse files
committed
Auto merge of #54976 - davidtwco:issue-52663-special-case-closures, r=nikomatsakis
NLL lacks various special case handling of closures Part of #52663. Firstly, this PR extends existing handling of closures to also support generators. Second, this PR adds the note found in the AST when a closure is invoked twice and captures a variable by-value: ```text note: closure cannot be invoked more than once because it moves the variable `dict` out of its environment --> $DIR/issue-42065.rs:16:29 | LL | for (key, value) in dict { | ^^^^ ``` r? @nikomatsakis cc @pnkfelix
2 parents 121320d + d088edc commit e7f5d48

10 files changed

+343
-202
lines changed

src/librustc_borrowck/borrowck/check_loans.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -609,12 +609,12 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
609609
new_loan.span, &nl, old_loan.span, previous_end_span, Origin::Ast),
610610
(ty::UniqueImmBorrow, _) =>
611611
self.bccx.cannot_uniquely_borrow_by_one_closure(
612-
new_loan.span, &nl, &new_loan_msg,
612+
new_loan.span, "closure", &nl, &new_loan_msg,
613613
old_loan.span, &ol_pronoun, &old_loan_msg, previous_end_span, Origin::Ast),
614614
(_, ty::UniqueImmBorrow) => {
615615
let new_loan_str = &new_loan.kind.to_user_str();
616616
self.bccx.cannot_reborrow_already_uniquely_borrowed(
617-
new_loan.span, &nl, &new_loan_msg, new_loan_str,
617+
new_loan.span, "closure", &nl, &new_loan_msg, new_loan_str,
618618
old_loan.span, &old_loan_msg, previous_end_span, Origin::Ast)
619619
}
620620
(..) =>

src/librustc_mir/borrow_check/error_reporting.rs

+292-115
Large diffs are not rendered by default.

src/librustc_mir/util/borrowck_errors.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
221221
fn cannot_uniquely_borrow_by_one_closure(
222222
self,
223223
new_loan_span: Span,
224+
container_name: &str,
224225
desc_new: &str,
225226
opt_via: &str,
226227
old_loan_span: Span,
@@ -241,7 +242,7 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
241242
);
242243
err.span_label(
243244
new_loan_span,
244-
format!("closure construction occurs here{}", opt_via),
245+
format!("{} construction occurs here{}", container_name, opt_via),
245246
);
246247
err.span_label(old_loan_span, format!("borrow occurs here{}", old_opt_via));
247248
if let Some(previous_end_span) = previous_end_span {
@@ -253,6 +254,7 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
253254
fn cannot_reborrow_already_uniquely_borrowed(
254255
self,
255256
new_loan_span: Span,
257+
container_name: &str,
256258
desc_new: &str,
257259
opt_via: &str,
258260
kind_new: &str,
@@ -275,7 +277,7 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
275277
err.span_label(new_loan_span, format!("borrow occurs here{}", opt_via));
276278
err.span_label(
277279
old_loan_span,
278-
format!("closure construction occurs here{}", old_opt_via),
280+
format!("{} construction occurs here{}", container_name, old_opt_via),
279281
);
280282
if let Some(previous_end_span) = previous_end_span {
281283
err.span_label(previous_end_span, "borrow from closure ends here");

src/test/ui/closure_context/issue-42065.nll.stderr

-11
This file was deleted.

src/test/ui/generator/borrowing.nll.stderr

+16-15
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
error[E0597]: `a` does not live long enough
2-
--> $DIR/borrowing.rs:18:18
2+
--> $DIR/borrowing.rs:18:29
33
|
44
LL | unsafe { (|| yield &a).resume() }
5-
| ^^^^^^^^^^^^^
6-
| |
7-
| borrowed value does not live long enough
5+
| -----------^-
6+
| || |
7+
| || borrowed value does not live long enough
8+
| |value captured here by generator
89
| a temporary with access to the borrow is created here ...
910
LL | //~^ ERROR: `a` does not live long enough
1011
LL | };
@@ -15,18 +16,18 @@ LL | };
1516
= note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
1617

1718
error[E0597]: `a` does not live long enough
18-
--> $DIR/borrowing.rs:24:9
19+
--> $DIR/borrowing.rs:25:20
1920
|
20-
LL | let _b = {
21-
| -- borrow later stored here
22-
LL | let a = 3;
23-
LL | / || {
24-
LL | | yield &a
25-
LL | | //~^ ERROR: `a` does not live long enough
26-
LL | | }
27-
| |_________^ borrowed value does not live long enough
28-
LL | };
29-
| - `a` dropped here while still borrowed
21+
LL | let _b = {
22+
| -- borrow later stored here
23+
LL | let a = 3;
24+
LL | || {
25+
| -- value captured here by generator
26+
LL | yield &a
27+
| ^ borrowed value does not live long enough
28+
...
29+
LL | };
30+
| - `a` dropped here while still borrowed
3031

3132
error: aborting due to 2 previous errors
3233

src/test/ui/generator/dropck.nll.stderr

+11-13
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,19 @@ LL | }
1313
= note: values in a scope are dropped in the opposite order they are defined
1414

1515
error[E0597]: `ref_` does not live long enough
16-
--> $DIR/dropck.rs:22:11
16+
--> $DIR/dropck.rs:24:18
1717
|
18-
LL | gen = || {
19-
| ___________^
20-
LL | | // but the generator can use it to drop a `Ref<'a, i32>`.
21-
LL | | let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
22-
LL | | yield;
23-
LL | | };
24-
| |_____^ borrowed value does not live long enough
18+
LL | gen = || {
19+
| -- value captured here by generator
20+
LL | // but the generator can use it to drop a `Ref<'a, i32>`.
21+
LL | let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
22+
| ^^^^ borrowed value does not live long enough
2523
...
26-
LL | }
27-
| -
28-
| |
29-
| `ref_` dropped here while still borrowed
30-
| borrow might be used here, when `gen` is dropped and runs the destructor for generator
24+
LL | }
25+
| -
26+
| |
27+
| `ref_` dropped here while still borrowed
28+
| borrow might be used here, when `gen` is dropped and runs the destructor for generator
3129
|
3230
= note: values in a scope are dropped in the opposite order they are defined
3331

src/test/ui/generator/yield-while-iterating.nll.stderr

+9-11
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,15 @@ LL | yield();
99
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
1010
--> $DIR/yield-while-iterating.rs:67:20
1111
|
12-
LL | let mut b = || {
13-
| _________________-
14-
LL | | for p in &mut x {
15-
LL | | yield p;
16-
LL | | }
17-
LL | | };
18-
| |_____- mutable borrow occurs here
19-
LL | println!("{}", x[0]); //~ ERROR
20-
| ^ immutable borrow occurs here
21-
LL | b.resume();
22-
| - mutable borrow later used here
12+
LL | let mut b = || {
13+
| -- mutable borrow occurs here
14+
LL | for p in &mut x {
15+
| - first borrow occurs due to use of `x` in generator
16+
...
17+
LL | println!("{}", x[0]); //~ ERROR
18+
| ^ immutable borrow occurs here
19+
LL | b.resume();
20+
| - mutable borrow later used here
2321

2422
error: aborting due to 2 previous errors
2523

src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
22
--> $DIR/yield-while-ref-reborrowed.rs:45:20
33
|
4-
LL | let mut b = || {
5-
| _________________-
6-
LL | | let a = &mut *x;
7-
LL | | yield();
8-
LL | | println!("{}", a);
9-
LL | | };
10-
| |_____- closure construction occurs here
11-
LL | println!("{}", x); //~ ERROR
12-
| ^ borrow occurs here
13-
LL | b.resume();
14-
| - first borrow later used here
4+
LL | let mut b = || {
5+
| -- generator construction occurs here
6+
LL | let a = &mut *x;
7+
| - first borrow occurs due to use of `x` in generator
8+
...
9+
LL | println!("{}", x); //~ ERROR
10+
| ^ borrow occurs here
11+
LL | b.resume();
12+
| - first borrow later used here
1513

1614
error: aborting due to previous error
1715

src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.nll.stderr

-11
This file was deleted.

src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.nll.stderr

-11
This file was deleted.

0 commit comments

Comments
 (0)