As explained in Why is the move keyword needed when returning a closure which captures a Copy type? and How to copy instead of borrow an i64 into a closure in Rust?, if a closure captures a type that implements Copy
, we need to use the move
keyword to eagerly copy the value:
fn use_move_to_copy_into_closure() -> impl FnOnce(i32) -> bool {
let captured = 0;
move |value| value > captured
}
As of Rust 2021, disjoint capture in closures means that only the specific fields used in a closure are captured by the closure:
struct Wrapper(i32);
fn edition_2021_only_captures_specific_fields(captured: Wrapper) -> impl FnOnce(i32) -> bool {
let ret = move |value| value > captured.0;
drop(captured); // fails in 2015, 2018, succeeds in 2021
ret
}
If I capture a Copy
field belonging to a reference, however, the field is not copied:
struct Wrapper(i32);
fn capturing_a_field_of_a_reference(captured: &Wrapper) -> impl FnOnce(i32) -> bool {
move |value| value > captured.0
}
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> src/lib.rs:15:60
|
15 | fn capturing_a_field_of_a_reference(captured: &Wrapper) -> impl FnOnce(i32) -> bool {
| -------- ^^^^^^^^^^^^^^^^^^^^^^^^
| |
| hidden type `[closure@src/lib.rs:16:5: 16:36]` captures the anonymous lifetime defined here
|
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
|
15 | fn capturing_a_field_of_a_reference(captured: &Wrapper) -> impl FnOnce(i32) -> bool + '_ {
| ++++
I expected that the field .0
would be copied in, just like in the unwrapped i32
or the owned Wrapper
cases. What causes this difference?