Skip to content

Commit 85f8cb0

Browse files
committed
rfc, if_while_or_patterns: amended with support for | in let statements
1 parent 7739d40 commit 85f8cb0

File tree

1 file changed

+68
-9
lines changed

1 file changed

+68
-9
lines changed

text/0000-if-while-or-patterns.md

+68-9
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
[`if let`]: https://github.com/rust-lang/rfcs/pull/160
1010
[`while let`]: https://github.com/rust-lang/rfcs/pull/214
1111

12-
Enables "or" patterns for [`if let`] and [`while let`] expressions. In other
13-
words, examples like the following are now possible:
12+
Enables "or" patterns for [`if let`] and [`while let`] expressions as well as
13+
`let` statements. In other words, examples like the following are now possible:
1414

1515
```rust
1616
enum E<T> {
@@ -26,6 +26,11 @@ let r = if let C | D = x { 1 } else { 2 };
2626
while let A(x) | B(x) = source() {
2727
react_to(x);
2828
}
29+
30+
enum ParameterKind<T, L = T> { Ty(T), Lifetime(L), }
31+
32+
// Only possible when `L = T` such that `kind : ParameterKind<T, T>`.
33+
let Ty(x) | Lifetime(x) = kind;
2934
```
3035

3136
# Motivation
@@ -107,7 +112,6 @@ which could have been written as:
107112

108113
This version is both shorter and clearer.
109114

110-
111115
With `while let`, the ergonomics and in particular the readability can be
112116
significantly improved.
113117

@@ -132,6 +136,10 @@ loop {
132136

133137
Another major motivation of the RFC is consistency with `match`.
134138

139+
To keep `let` statements consistent with `if let`, and to enable the scenario
140+
exemplified by `ParameterKind` in the [motivation], these or-patterns are
141+
allowed at the top level of `let` statements.
142+
135143
# Guide-level explanation
136144
[guide-level-explanation]: #guide-level-explanation
137145

@@ -145,8 +153,8 @@ words: cover all cases, be exhaustive, this is not the case (currently) with
145153
`if/while let`, which may have a refutable pattern.
146154
This RFC does not change this.
147155

148-
The RFC only extends the use of or-patterns from `match`es to `if let` and
149-
`while let` expressions.
156+
The RFC only extends the use of or-patterns at the top level from `match`es
157+
to `if let` and `while let` expressions as well as `let` statements.
150158

151159
For examples, see [motivation].
152160

@@ -188,11 +196,28 @@ to:
188196
while_let_expr : [ lifetime ':' ] ? "while" "let" pat [ '|' pat ] * '=' expr '{' block '}' ;
189197
```
190198

199+
### `let` statements
200+
201+
The statement `stmt` grammar is replaced with a language equivalent to:
202+
203+
```
204+
stmt ::= old_stmt_grammar
205+
| let_stmt_many
206+
;
207+
208+
let_stmt_many ::= "let" pat_two_plus "=" expr ";"
209+
210+
pat_two_plus ::= pat [ '|' pat ] + ;
211+
```
212+
191213
## Syntax lowering
192214

193-
The changes proposed in this RFC can be implemented by transforming the
194-
`if/while let` constructs with a syntax-lowering pass into `match` and
195-
`loop` + `match` expressions.
215+
The changes proposed in this RFC with respect to `if let` and `while let`
216+
can be implemented by transforming the `if/while let` constructs with a
217+
syntax-lowering pass into `match` and `loop` + `match` expressions.
218+
219+
Meanwhile, `let` statements can be transformed into a continuation with
220+
`match` as described below.
196221

197222
### Examples, `if let`
198223

@@ -289,10 +314,41 @@ Result:
289314
}
290315
```
291316

317+
## Desugaring `let` statements with `|` in the top-level pattern
318+
319+
This is a possible desugaring that a Rust compiler may do.
320+
While such a compiler may elect to implement this differently,
321+
these semantics should be kept.
322+
323+
Source:
324+
```rust
325+
{
326+
// prefix of statements:
327+
stmt*
328+
// The let statement which is the cause for desugaring:
329+
let_stmt_many
330+
// the continuation / suffix of statements:
331+
stmt*
332+
tail_expr? // Meta-variable for optional tail expression without ; at end
333+
}
334+
```
335+
Result
336+
```rust
337+
{
338+
stmt*
339+
match expr {
340+
pat_two_plus => {
341+
stmt*
342+
tail_expr?
343+
}
344+
}
345+
}
346+
```
347+
292348
# Drawbacks
293349
[drawbacks]: #drawbacks
294350

295-
It's one more addition to the grammar.
351+
This adds more additions to the grammar and makes the compiler more complex.
296352

297353
# Rationale and alternatives
298354
[alternatives]: #alternatives
@@ -303,6 +359,9 @@ Consistency with `match` is however on its own reason enough to do this.
303359
It could be claimed that the `if/while let` RFCs already mandate this RFC,
304360
this RFC does answer that question and instead simply mandates it now.
305361

362+
Another alternative is to only deal with `if/while let` expressions but not
363+
`let` statements.
364+
306365
# Unresolved questions
307366
[unresolved]: #unresolved-questions
308367

0 commit comments

Comments
 (0)