Moving structs with Copy fields into closures causes surprising behavior #111376
Labels
A-closures
Area: Closures (`|…| { … }`)
A-lints
Area: Lints (warnings about flaws in source code) such as unused_mut.
C-bug
Category: This is a bug.
T-compiler
Relevant to the compiler team, which will review and decide on the PR/issue.
I noticed some counterintuitive behavior related to partial moves of Copy struct fields (ex: u64 fields) into closures.
Minimal Reproducible Example
This code compiles and prints
Playground Link
What I Expected
I would have expected a
borrow of partially moved value: 'statistics'
error at theprintln!
, since the closure takes ownership of thestatistics.calls
field and then the field is later read by the print call.The actual behavior, where the updates to
statistics.calls
have no observable effect, looks just like a silent copy of the whole struct. This surprised me. When I wrote the code, I expected either a compiler error or an output ofStatistics { calls: 1, successes: 1 }
.Investigation
I experimented a bit with the types of the fields within the struct, and I do get the compiler error I expect if
Statistics.calls
is a non-Copy type likeVec
.I didn't know about partial moves when I wrote the initial code. I expected the whole struct to move into the closure. It's still surprising to me that partial moves can create this type of "silent copy" behavior depending on the type of the struct's fields.
I did find a similar issue titled Move closure copies :Copy variables silently, but the code that I wrote is not covered by the "unused variable" warning added in response to that issue.
Solution
I'm new to Rust so I'm not sure this is a bug, but it's still confusing behavior. Perhaps, like the other issue I linked, there is room for a lint or warning here. Something that warned me that the closure's modification of
statistics.calls
had no effect would be helpful, for example.The text was updated successfully, but these errors were encountered: