Skip to content

Commit aed7f00

Browse files
Rollup merge of #87460 - FabianWolff:issue-87456, r=Aaron1011
Point to closure when emitting 'cannot move out' for captured variable Attempts to fix #87456. The error message now points to the capturing closure, but I was not able to explain _why_ the closure implements `Fn` or `FnMut` (`TypeckResults::closure_kind_origins` did not contain anything for the closure in question). cc `@Aaron1011`
2 parents b6d0cca + 21b7052 commit aed7f00

13 files changed

+503
-215
lines changed

compiler/rustc_borrowck/src/diagnostics/move_errors.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -336,15 +336,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
336336
if def_id.as_local() == Some(self.mir_def_id()) && upvar_field.is_some() =>
337337
{
338338
let closure_kind_ty = closure_substs.as_closure().kind_ty();
339-
let closure_kind = closure_kind_ty.to_opt_closure_kind();
340-
let capture_description = match closure_kind {
341-
Some(ty::ClosureKind::Fn) => "captured variable in an `Fn` closure",
342-
Some(ty::ClosureKind::FnMut) => "captured variable in an `FnMut` closure",
339+
let closure_kind = match closure_kind_ty.to_opt_closure_kind() {
340+
Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind,
343341
Some(ty::ClosureKind::FnOnce) => {
344342
bug!("closure kind does not match first argument type")
345343
}
346344
None => bug!("closure kind not inferred by borrowck"),
347345
};
346+
let capture_description =
347+
format!("captured variable in an `{}` closure", closure_kind);
348348

349349
let upvar = &self.upvars[upvar_field.unwrap().index()];
350350
let upvar_hir_id = upvar.place.get_root_variable();
@@ -368,6 +368,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
368368
let mut diag = self.cannot_move_out_of(span, &place_description);
369369

370370
diag.span_label(upvar_span, "captured outer variable");
371+
diag.span_label(
372+
self.body.span,
373+
format!("captured by this `{}` closure", closure_kind),
374+
);
371375

372376
diag
373377
}

src/test/ui/borrowck/borrowck-in-static.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure
44
LL | let x = Box::new(0);
55
| - captured outer variable
66
LL | Box::new(|| x)
7-
| ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
7+
| ---^
8+
| | |
9+
| | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
10+
| captured by this `Fn` closure
811

912
error: aborting due to previous error
1013

src/test/ui/borrowck/borrowck-move-by-capture.stderr

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure
22
--> $DIR/borrowck-move-by-capture.rs:9:29
33
|
4-
LL | let bar: Box<_> = box 3;
5-
| --- captured outer variable
6-
LL | let _g = to_fn_mut(|| {
7-
LL | let _h = to_fn_once(move || -> isize { *bar });
8-
| ^^^^^^^^^^^^^^^^ ----
9-
| | |
10-
| | move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
11-
| | move occurs due to use in closure
12-
| move out of `bar` occurs here
4+
LL | let bar: Box<_> = box 3;
5+
| --- captured outer variable
6+
LL | let _g = to_fn_mut(|| {
7+
| ________________________-
8+
LL | | let _h = to_fn_once(move || -> isize { *bar });
9+
| | ^^^^^^^^^^^^^^^^ ----
10+
| | | |
11+
| | | move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
12+
| | | move occurs due to use in closure
13+
| | move out of `bar` occurs here
14+
LL | | });
15+
| |_____- captured by this `FnMut` closure
1316

1417
error: aborting due to previous error
1518

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Regression test for #87456.
2+
3+
fn take_mut(_val: impl FnMut()) {}
4+
5+
fn main() {
6+
let val = String::new();
7+
//~^ NOTE: captured outer variable
8+
take_mut(|| {
9+
//~^ NOTE: captured by this `FnMut` closure
10+
let _foo: String = val;
11+
//~^ ERROR: cannot move out of `val`, a captured variable in an `FnMut` closure [E0507]
12+
//~| NOTE: move occurs because
13+
})
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0507]: cannot move out of `val`, a captured variable in an `FnMut` closure
2+
--> $DIR/issue-87456-point-to-closure.rs:10:28
3+
|
4+
LL | let val = String::new();
5+
| --- captured outer variable
6+
LL |
7+
LL | take_mut(|| {
8+
| ______________-
9+
LL | |
10+
LL | | let _foo: String = val;
11+
| | ^^^
12+
| | |
13+
| | move occurs because `val` has type `String`, which does not implement the `Copy` trait
14+
| | help: consider borrowing here: `&val`
15+
LL | |
16+
LL | |
17+
LL | | })
18+
| |_____- captured by this `FnMut` closure
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0507`.

src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure
22
--> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9
33
|
4-
LL | let y = vec![format!("World")];
5-
| - captured outer variable
6-
LL | call(|| {
7-
LL | y.into_iter();
8-
| ^ move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
4+
LL | let y = vec![format!("World")];
5+
| - captured outer variable
6+
LL | call(|| {
7+
| __________-
8+
LL | | y.into_iter();
9+
| | ^ move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
10+
LL | |
11+
LL | | });
12+
| |_____- captured by this `Fn` closure
913

1014
error: aborting due to previous error
1115

src/test/ui/issues/issue-4335.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ error[E0507]: cannot move out of `*v`, as `v` is a captured variable in an `FnMu
44
LL | fn f<'r, T>(v: &'r T) -> Box<dyn FnMut() -> T + 'r> {
55
| - captured outer variable
66
LL | id(Box::new(|| *v))
7-
| ^^ move occurs because `*v` has type `T`, which does not implement the `Copy` trait
7+
| ---^^
8+
| | |
9+
| | move occurs because `*v` has type `T`, which does not implement the `Copy` trait
10+
| captured by this `FnMut` closure
811

912
error: aborting due to previous error
1013

src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ error[E0507]: cannot move out of `i`, a captured variable in an `Fn` closure
44
LL | let i = box 3;
55
| - captured outer variable
66
LL | let _f = to_fn(|| test(i));
7-
| ^ move occurs because `i` has type `Box<usize>`, which does not implement the `Copy` trait
7+
| --------^-
8+
| | |
9+
| | move occurs because `i` has type `Box<usize>`, which does not implement the `Copy` trait
10+
| captured by this `Fn` closure
811

912
error: aborting due to previous error
1013

src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn`
44
LL | let x = (vec![22], vec![44]);
55
| - captured outer variable
66
LL | expect_fn(|| drop(x.0));
7-
| ^^^ move occurs because `x.0` has type `Vec<i32>`, which does not implement the `Copy` trait
7+
| --------^^^-
8+
| | |
9+
| | move occurs because `x.0` has type `Vec<i32>`, which does not implement the `Copy` trait
10+
| captured by this `Fn` closure
811

912
error: aborting due to previous error
1013

src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr

+10-4
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,17 @@ LL | f.f.call_mut(())
2929
error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure
3030
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13
3131
|
32-
LL | let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
33-
| ----- captured outer variable
32+
LL | let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
33+
| ----- captured outer variable
3434
...
35-
LL | foo(f);
36-
| ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 54:6]`, which does not implement the `Copy` trait
35+
LL | f(Box::new(|a| {
36+
| ________________-
37+
LL | |
38+
LL | | foo(f);
39+
| | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 54:6]`, which does not implement the `Copy` trait
40+
LL | |
41+
LL | | }), 3);
42+
| |_____- captured by this `FnMut` closure
3743

3844
error[E0505]: cannot move out of `f` because it is borrowed
3945
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16

0 commit comments

Comments
 (0)