Misleading error when a value moved into a closure gets depleted (moved away) when that closure is called #133881
Labels
A-diagnostics
Area: Messages for errors, warnings, and lints
T-compiler
Relevant to the compiler team, which will review and decide on the PR/issue.
Code
Check out this repo:
https://github.com/mcclure/rs-bug/tree/z_bug_clone_error
branch
z_bug_clone_error
.There are two adjacent commits.
2b22470
exhibits the bad error,be44a0022
fixes the bad error (by adding a.clone()
.To reproduce, you must run
cargo build --example vim
.This is a somewhat heaviweight example. I attempted to produce a simpler example, and it actually produced a subtly different (better actually, but still confusing) error. So I guess I now have two examples. Here's example #2.
Current output
Example #1 ("z_bug_clone_error"):
Example #2 (inline in post above)
Rationale and extra context
In both code examples, the same process is happening: There is a
move ||
closure, the closure captures a variable, the closure does something that causes the variable to get consumed/moved out, the closure gets called more than once. The solution is to either call the closure only once, or to clone the value inside the closure rather than moving it.Desired output
I have a couple problems with these errors.
The biggest problem is both errors describe my closure as "implementing" FnOnce or FnMut. Of course I don't implement any traits, I'm relying on builtin syntax to create the closure. I would understand the sentence "you've written a closure that can only be called once, but you call it more than once" but both errors word it "you implemented FnOnce instead of FnMut". This is technically correct, but it is phrasing the problem in terms of compiler concepts which are here hidden from the user.
The second problem is exclusive to error #1, and it is that the error describes the problem as a problem with the type of the closure whereas the actual issue is a problem with how next_value gets called or a problem with how
reset_adjust
/garbage
is being treated. This is not made clear in the current wording. I don't understand why the two bits of very similar code produce different errors.I am also a little confused by the wording "moves the variable
reset_adjust out of its environment
". In retrospect, I'm not sure it's reasonable I was confused, but I'll do my best: I have amove
closure which moves the reset_adjust value out of its original environment (the stack frame from which it is captured). Then the linestate.adjust = reset_adjust
moves it out of its new environment and into state.adjust (although it doesn't move very far, becausestate.adjust
also lives inside themove ||
; maybe this is my fault for not understanding the meaning of "environment", but that kinda looks like the same environment to me). Because there are multiple moves and multiple different possible "environment"s in play, "the variable is moved out of its environment" does not guide me to the correct point in the code.That's a lot of typing and I never said what my desired output would be. I don't actually know how you shold fix this error. But I think my recommendation would be to make the error look more like "example #2" than "example #1", and add another hint to indicate that the problem can be solved by cloning (or, in general, by making a change to
reset_adjust
/garbage
). Earlier I commented there are two possible fixes: Fix the usage ofnext_value
outside the closure, or fix the usage ofreset_adjust
/garbage
inside the closure. The "Example #2" error above pushes you toward the first solution, but neither error pushes me toward the second.I did get this error "in the wild", and it was slow for me to figure out the fix even though the fix is simple.
Rust Version
Anything else?
No response
The text was updated successfully, but these errors were encountered: