-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NLL: Improve move error loop detection #54015
Comments
I'm adding this to "RC 2" list as a "nice to have" |
I think @blitzerr is going to work on this |
Context: The
we would rather add "in previous iteration of loop" to the "value moved here" message:
This error reporting occurs in this function: rust/src/librustc_mir/borrow_check/error_reporting.rs Lines 33 to 39 in f17c230
The first thing it does is to compute the "move out indices" that may be relevant:
To understand this, you have to understand a bit about the In the case of our example, the Now, right now, what we do is to iterate over those resulting move-outs:
For each of them we issue a "value moved here" label. We sometimes print "in previous iteration of loop", but our heuristic is kind of insufficient. We look for a case where the "use" and the previous move have the same span: rust/src/librustc_mir/borrow_check/error_reporting.rs Lines 106 to 111 in f17c230
This only works when you have something like The right way to detect this case is to look for a "backedge". In compiler terminology, a "backedge" in the control-flow graph is an edge B -> A where A dominates B. Put another way: in order to get to the point B, you have to go through A (because A dominates B), but this edge B->A then lets you get from B back to A. This is basically the definition of a loop. I think perhaps the easiest thing for us to do, then, is to modify the function The point where we traverse edges is here:
what we could do is to keep a "boolean" as we traverse. It would start out false, but become true if ever traverse a backedge. I'd probably start by adding a struct IsBackEdge(bool); So change that call to stack.extend(
mir.predecessor_locations(l)
.map(|predecessor| {
// There is an edge `predecessor -> l`. This is a backedge if `l` dominates `predecessor`.
let is_backedge = l.dominates(predecessor, &self.dominators);
(predecessor, IsBackEdge(is_backedge))
}
); This will put Vec<(MoveOutIndex, IsBackEdge)> then we can adjust the code to add the ", in previous iteration of loop" only if |
That is one hell of an explanation. Thank you so much for taking time to put your thoughts in such an elaborate manner. Thanks |
In #53995, errors were deduplicated and generally this kept errors with the improved "previous iteration of loop" diagnostic:
However, in one case, liveness-move-in-while.rs, the remaining error did not have the improved loop diagnostic.
From @nikomatsakis, in a comment from that PR (context mine):
The text was updated successfully, but these errors were encountered: