Following sample code doesn't compile:
fn invoke(i: i32, mut f: impl FnMut(i32)) {
f(i)
}
fn main() {
let f: fn(i32, _) = invoke;
let mut sum: i32 = 0;
for i in 0..10 {
_ = f(i, |x| sum += x);
}
println!("{:?}", sum);
}
The compiler returns following error:
Compiling playground v0.0.1 (/playground)
error[E0499]: cannot borrow `sum` as mutable more than once at a time
--> src/main.rs:10:18
|
10 | _ = f(i, |x| sum += x);
| - ^^^ --- borrows occur due to use of `sum` in closure
| | |
| | `sum` was mutably borrowed here in the previous iteration of the loop
| first borrow used here, in later iteration of loop
For more information about this error, try `rustc --explain E0499`.
error: could not compile `playground` due to previous error
If I move f
assignment to the for
loop, the code compiles:
fn invoke(i: i32, mut f: impl FnMut(i32)) {
f(i)
}
fn main() {
let mut sum: i32 = 0;
for i in 0..10 {
let f: fn(i32, _) = invoke;
_ = f(i, |x| sum += x);
}
println!("{:?}", sum);
}
I'm confused why the first code doesn't compile. The variable f
is of type fn
, which means that it is stateless. Variable f
is also immutable, so even if its type were stateful, it could not store the closure. Consequently, the compiler should be able to conclude that the closure will be dropped before the next iteration of the for
loop. Yet the compiler behaves as if f
were mutable and it could store the closure. Could you please explain why the compiler behaves this was.
rustc version: Stable v1.68.2