Closures should infer to capture by copy
Inspired by a common stumbling block with Iterator::flat_map.
This code does not compile:
(0..10).flat_map(|i| (0..i).map(|j| i + j))
error: `i` does not live long enough
The problem: i is a local variable and captured by reference in a closure we're trying to return. It's an integer, its data size is equal or smaller as a value instead of a reference.
Can rustc infer that the closure should capture i by "move" here (Copy)?
That seems a bit magical. What if
iwere mutable?Steven Allen at 2016-09-18 21:01:02
The compiler can already infer
movesometimes, for example when you consume a value like this. This compiles without error:(0..10).flat_map(|_| { let s = String::new(); Some(1).map(|_| s) });(It's valid to return because the closure to Option::map is an FnOnce, but FnOnceness is really orthogonal to capture mode.)
I don't immediately see the issue with mutability. It works the same to the closure if a variable is captured by mutable reference or copy, you can mutate it anyway.
(0..10).flat_map(|mut i| (0..10).map(move |j| { i += j; i })); // this is finebluss at 2016-09-18 21:16:27
I don't immediately see the issue with mutability. It works the same to the closure if a variable is captured by mutable reference or copy, you can mutate it anyway.
I was more worried about the case where something outside the closure mutates
i. However, that would require aCopytype with interior mutability (which I don't think is even possible).The compiler can already infer move sometimes, for example when you consume a value like this.
Given this, I'd have to agree. Note: "sometimes" is when the closure is
FnOnce.Steven Allen at 2016-09-19 01:45:13
That would be lifetime inference affecting type inference. I don't feel like this is going to happen.
Ariel Ben-Yehuda at 2016-09-24 15:43:42
@arielb1 That I can absolutely understand. But do you think it would have to be like that, could it not simply infer to Copy here because it can copy and preserve the exact same functionality in the closure?
bluss at 2016-09-24 17:09:35
@bluss
But that won't help when
iis notCopy.Without nested closures, we already have a "closure may outlive the current function" error message, but it is not shown there because of laziness. This issue was already known since we had unboxed closures.
Ariel Ben-Yehuda at 2016-09-25 09:13:05
Triage: no change
Maayan Hanin at 2022-03-22 08:50:26