The following code compiles and executes just fine:
fn b(a: &mut u32) -> &mut u32 {
let f = || {
*a = 43;
a
};
f()
}
fn main() {
let mut a: u32 = 42;
let r = &mut a;
b(r);
println!("{:?}", a);
}
If I now explicitly annotate the closure with let mut f = || -> &mut u32
, rust complains:
error: captured variable cannot escape `FnMut` closure body
--> src/main.rs:4:9
|
1 | fn b(a: &mut u32) -> &mut u32 {
| - variable defined here
2 | let mut f = || -> &mut u32 {
| - inferred to be a `FnMut` closure
3 | *a = 43;
| - variable captured here
4 | a
| ^ returns a reference to a captured variable which escapes the closure body
|
= note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape
I can't make sense of this error.
Closures have complex, subtle, and minimally documented inference rules regarding lifetimes and Fn
traits. From the error message, I can tell that adding the return type adds FnMut
to this closure's inferred traits, however I don't know why.
If you need to specify the return type, you can fix this by passing the closure through a function that requires FnOnce
.
fn b(a: &mut u32) -> &mut u32 {
let f = make_fn_once(|| -> &mut u32 {
*a = 43;
a
});
f()
}
fn make_fn_once<F, T>(f: F) -> F
where
F: FnOnce() -> T,
{
f
}
Note that even defining the closure and then passing it to the function will not work; it has to be passed directly to the function.
fn b(a: &mut u32) -> &mut u32 {
// error: captured variable cannot escape `FnMut` closure body
let f = || -> &mut u32 {
*a = 43;
a
};
let f = make_fn_once(f);
f()
}