-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
borrow checker does not work correctly with explicit return statements inside for-in loops #37737
Comments
The for loop is using a mutable iterator which has the borrow In this case, you might consider using a range query, and indexing |
@keeperofdakeys whether the iterator is mutable or not ( I do realize that this program can be rewritten to work, that is not the issue here and this code is just an example to illustrate the problem. Lets not try to correct it. The issue is that in my understanding explicit return statement should effectively end the for-loop scope (end borrowing done by the iterator), since this is the last expression that will be executed in the scope, and all other variables not referenced in the return expression must be safely discarded (dropped) before returning anyway. Please note that when I do realize that there are more such problems with the borrow checker and I've learnt to work around them, however I filled this issue in hope that this fix/optimization might not be too difficult to implement? |
The problem is that you're mutably borrowing
Any code inside a block will be executed before the end of that block. If return statements were excluded, you wouldn't be able to, e.g., write: for x in vec![1u32, 2, 3], iter() {
// x: &u32;
if x < 3 {
return x + 1; // Under your proposal, `x` would be out of scope in this statement.
}
} However, there has been some thought put into something called non-lexical lifetimes. This feature might (depending on how (and if) it's implemented) allow the compiler to "unborrow" variables early in cases like this. However, there's a non-trivial amount of design work needed to even understand how this feature would work (let alone how it would be implemented) to avoid surprising the programmer. See rust-lang/rfcs#811 for more. |
@Stebalien Thanks very much for the link, "non-lexical lifetimes" is precisely the optimization/fix I had in mind!. Basically finalization of scope's lifetime should be done as early as possible. I hope this feature will be implemented, as fighting with the borrow checker in a logically correct code is rather annoying.
Of course not, that is why I used the phrase "in this case" at the end of the sentence. The case being that in my particular example the return statement does not use any binding from the for-in loop scope. I am closing this, and I will follow the discussion in the RFC. |
When I try this:
it gives me a compilation error:
link to Rust Playground: https://play.rust-lang.org/?gist=4d192eaabfc22904c9fb20e14ea39acc&version=nightly&backtrace=0
Now, when I simply change it to this:
(break instead of explicit return) everything works OK.
Link to Rust Playground: https://play.rust-lang.org/?gist=196c27cc90694c7b6daefe7ceeb517d3&version=nightly&backtrace=0
Clearly the borrow checker is working incorrectly when there is an explicit return inside a loop, as those programs are equivalent.
The text was updated successfully, but these errors were encountered: