reference
reference copied to clipboard
Document let else statements
For the stabilization of let else statements.
Tracking issue: https://github.com/rust-lang/rust/issues/87335
Consider that you can already match against irrefutable pattern in let, and this is essentially just an extension to let in practice.
Originally I tried to extend the let section as you suggest. There are commonalities, but there are also a lot of differences. For let, the pattern must be irrefutable, for let else it must be refutable. For let, the = expr is optional, for let else it isn't. Explaining those differences would have made it harder to explain/comprehend how the thing works in the first place.
for
let elseit must be refutable.
No, by default it is only a warning to have an irrefutable binding in there.
warning: irrefutable `let...else` pattern
--> src/main.rs:4:5
|
4 | / let x = 5 else {
5 | | return;
6 | | };
| |______^
|
= note: `#[warn(irrefutable_let_patterns)]` on by default
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
Good point, it's only a warning. Should I change the text of the reference to extend it to all patterns?
Yes. But refutable patterns deserve a mention, something along the lines of
If the pattern is a refutable pattern, then the else block will be executed when the pattern is not matched. The else block must escape [/return/whatever we call it] ...
I haven't read much of the reference before so not sure whether it's appropriate to mention that refutable patterns are the whole point of it.
With let else stable, this is ready for review!
I think I too would prefer to see this defined as a single statement. I understand it can be a little awkward since it changes the semantics quite a bit, but I think it shouldn't be too difficult to describe. As it is, it looks like there is a lot of duplication.
To make it fit in the original let statements section, I think it should be sufficient to:
- Remove the word "irrefutable".
- Add a paragraph describing the
elseblock behavior. Here's a rough draft, but feel free to adjust:
When an else block follows the initializer, then the pattern may be a refutable pattern.
When the pattern does not match, the else block is executed.
The type of the else block must be the never type.
If there is no else block, then the pattern must be irrefutable.
- The grammar for Expression in the initializer needs to reject forbidden expressions. I would probably just add a dagger (†) that links to a sentence in the grammar section that explains it. Like:
Syntax
… [Expression] † …† When an
elseblock is specified, the Expression must not be a LazyBooleanExpression or end with a}.
I'm also a bit surprised this is how it works, as this adds unprecedented complexity to the grammar and I think would be quite difficult for many parsers.
- Add a note about irrefutability:
Note:
rustcwill emit a warning when using an irrefutable pattern with anelseblock since that makes it impossible for theelseblock to execute.
- Add an example. Illustrate both a basic
letbinding, and one with anelseblock.
@ehuss okay I gave up, I refactored the section so that it is unified with let. My second attempt of unifying feels less complicated than what I remember of my first attempt, so this was a good idea already, and I'm quite open towards this approach now.
r? @ehuss
@Havvy good catch! I've updated that sentence in the last commit.
No problem! It is great that consistency is important to you.