- Start Date: 2014-08-27
- RFC PR: rust-lang/rfcs#214
- Rust Issue: rust-lang/rust#17687
Summary
Introduce a new while let PAT = EXPR { BODY }
construct. This allows for using a refutable pattern
match (with optional variable binding) as the condition of a loop.
Motivation
Just as if let
was inspired by Swift, it turns out Swift supports while let
as well. This was
not discovered until much too late to include it in the if let
RFC. It turns out that this sort of
looping is actually useful on occasion. For example, the desugaring for
loop is actually a variant
on this; if while let
existed it could have been implemented to map for PAT in EXPR { BODY }
to
// the match here is so `for` can accept an rvalue for the iterator,
// and was used in the "real" desugaring version.
match &mut EXPR {
i => {
while let Some(PAT) = i.next() {
BODY
}
}
}
(note that the non-desugared form of for
is no longer equivalent).
More generally, this construct can be used any time looping + pattern-matching is desired.
This also makes the language a bit more consistent; right now, any condition that can be used with
if
can be used with while
. The new if let
adds a form of if
that doesn’t map to while
.
Supporting while let
restores the equivalence of these two control-flow constructs.
Detailed design
while let
operates similarly to if let
, in that it desugars to existing syntax. Specifically,
the syntax
['ident:] while let PAT = EXPR {
BODY
}
desugars to
['ident:] loop {
match EXPR {
PAT => BODY,
_ => break
}
}
Just as with if let
, an irrefutable pattern given to while let
is considered an error. This is
largely an artifact of the fact that the desugared match
ends up with an unreachable pattern,
and is not actually a goal of this syntax. The error may be suppressed in the future, which would be
a backwards-compatible change.
Just as with if let
, while let
will be introduced under a feature gate (named while_let
).
Drawbacks
Yet another addition to the grammar. Unlike if let
, it’s not obvious how useful this syntax will
be.
Alternatives
As with if let
, this could plausibly be done with a macro, but it would be ugly and produce bad
error messages.
while let
could be extended to support alternative patterns, just as match arms do. This is not
part of the main proposal for the same reason it was left out of if let
, which is that a) it looks
weird, and b) it’s a bit of an odd coupling with the let
keyword as alternatives like this aren’t
going to be introducing variable bindings. However, it would make while let
more general and able
to replace more instances of loop { match { ... } }
than is possible with the main design.
Unresolved questions
None.