From https://github.com/rust-lang/rust/pull/37487#issuecomment-258313472
As for whether
while break { }should break out of the while loop (as it does today) or out of the containing loop (as it does under this PR), it seems like neither is particularly intuitive. Our [NB: lang team] preference would be to simply make it an error to put break in the condition of a while loop.We can make it a hard error and do a test, but it may be that we want to go through a warning period here.
cc @nikomatsakis and the lang team in general
UPDATE: See this comment which includes a number of examples that we will want to check when fixing this bug.
While I agree that neither behaviour is exactly intuitive, I’d like to take some time to write down a number of intuitions that someone might use (perhaps helping to discuss the issue somewhat):
while COND { BODY } has an obvious desugaring to loop { if !COND { break } BODY }. Under this intuition the condition is the part of the loop and therefore should break from the while loop. The problem with this intuition is that its rarely the intuition your average programmer would use to guess the behaviour when presented with a trick question during an interview;COND and BODY may be executed multiple times, a conclusion follows that COND is a part of the loop; Under this intuition COND should also break out of the while loop, and this is also an intuition somebody could use during an interview. A derivation of desugaring intuition;while COND { BODY } it REALLY doesn’t look like COND is part of the loop.I personally see less issues with keeping the current behaviour over forbidding it (backward incompatibility) or changing it to the alternative (silent breaking change).
I personally see less issues with keeping the current behaviour over forbidding it (backward incompatibility) or changing it to the alternative (silent breaking change).
Note that the current behavior is to forbid it unless its nested inside of another loop (!). I think forbiding it in every case is the best behavior; if you need to break in the condition, you can always write the desugared form. There is no clearly correct behavior of loop { while break { } } in my opinion.
I would prefer forbidding regular break and continue in the condition, but allowing 'a: while break 'a {}, because then it's explicit what you're referring to.
One more data point re: existing behaviour... this is allowed:
fn main() {
while let true = break {
unreachable!();
}
}
(because the desugaring of while let applies before the check loops pass.)
Can #21751 be closed in favor of this?
Here are some further examples that @cramertj raised in #39867. The current compiler does not have consistent treatment, in short, so I think that we can't really cite the "current behavior" as precedent one way or another:
This can be closed since #39864 has landed.
Most helpful comment
I would prefer forbidding regular
breakandcontinuein the condition, but allowing'a: while break 'a {}, because then it's explicit what you're referring to.