9
9
[ `if let` ] : https://github.com/rust-lang/rfcs/pull/160
10
10
[ `while let` ] : https://github.com/rust-lang/rfcs/pull/214
11
11
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:
12
+ Enables "or" patterns for [ ` if let ` ] and [ ` while let ` ] expressions
13
+ as well as ` let ` and ` for ` statements. In other words,
14
+ examples like the following are now possible:
14
15
15
16
``` rust
16
17
enum E <T > {
@@ -28,9 +29,12 @@ while let A(x) | B(x) = source() {
28
29
}
29
30
30
31
enum ParameterKind <T , L = T > { Ty (T ), Lifetime (L ), }
32
+ use ParameterKind :: * ;
31
33
32
34
// Only possible when `L = T` such that `kind : ParameterKind<T, T>`.
33
35
let Ty (x ) | Lifetime (x ) = kind ;
36
+
37
+ for Ty (x ) | Lifetime (x ) in :: std :: iter :: once (kind );
34
38
```
35
39
36
40
# Motivation
@@ -136,9 +140,9 @@ loop {
136
140
137
141
Another major motivation of the RFC is consistency with ` match ` .
138
142
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.
143
+ To keep ` let ` and ` for ` statements consistent with ` if let ` ,
144
+ and to enable the scenario exemplified by ` ParameterKind ` in the [ motivation] ,
145
+ these or-patterns are allowed at the top level of ` let ` and ` for ` statements.
142
146
143
147
In addition to the ` ParameterKind ` example, we can also consider
144
148
` slice.binary_search(&x) ` . If we are only interested in the ` index ` at where
@@ -165,7 +169,7 @@ words: cover all cases, be exhaustive, this is not the case (currently) with
165
169
This RFC does not change this.
166
170
167
171
The RFC only extends the use of or-patterns at the top level from ` match ` es
168
- to ` if let ` and ` while let ` expressions as well as ` let ` statements.
172
+ to ` if let ` and ` while let ` expressions as well as ` let ` and ` for ` statements.
169
173
170
174
For examples, see [ motivation] .
171
175
@@ -189,7 +193,7 @@ if_let_expr : "if" "let" pat '=' expr '{' block '}'
189
193
to:
190
194
191
195
```
192
- if_let_expr : "if" "let" pat [ '|' pat ] * '=' expr '{' block '}'
196
+ if_let_expr : "if" "let" '|'? pat [ '|' pat ] * '=' expr '{' block '}'
193
197
else_tail ? ;
194
198
```
195
199
@@ -204,7 +208,23 @@ while_let_expr : [ lifetime ':' ] ? "while" "let" pat '=' expr '{' block '}' ;
204
208
to:
205
209
206
210
```
207
- while_let_expr : [ lifetime ':' ] ? "while" "let" pat [ '|' pat ] * '=' expr '{' block '}' ;
211
+ while_let_expr : [ lifetime ':' ] ? "while" "let" '|'? pat [ '|' pat ] * '=' expr '{' block '}' ;
212
+ ```
213
+
214
+ ### ` for `
215
+
216
+ [ for_grammar ] : https://github.com/rust-lang/rust/blob/master/src/grammar/parser-lalr.y
217
+
218
+ The ` expr_for ` grammar is changed [ from] [ for_grammar ] :
219
+
220
+ ```
221
+ expr_for : maybe_label FOR pat IN expr_nostruct block ;
222
+ ```
223
+
224
+ to:
225
+
226
+ ```
227
+ expr_for : maybe_label FOR '|'? pat ('|' pat)* IN expr_nostruct block ;
208
228
```
209
229
210
230
### ` let ` statements
@@ -218,12 +238,12 @@ stmt ::= old_stmt_grammar
218
238
219
239
let_stmt_many ::= "let" pat_two_plus "=" expr ";"
220
240
221
- pat_two_plus ::= pat [ '|' pat ] + ;
241
+ pat_two_plus ::= '|'? pat [ '|' pat ] + ;
222
242
```
223
243
224
244
## Syntax lowering
225
245
226
- The changes proposed in this RFC with respect to ` if let ` and ` while let `
246
+ The changes proposed in this RFC with respect to ` if let ` , ` while let ` , and ` for `
227
247
can be implemented by transforming the ` if/while let ` constructs with a
228
248
syntax-lowering pass into ` match ` and ` loop ` + ` match ` expressions.
229
249
@@ -239,7 +259,7 @@ duplicating any details already specified there.
239
259
240
260
Source:
241
261
``` rust
242
- if let PAT [| PAT ]* = EXPR { BODY }
262
+ if let | ? PAT [| PAT ]* = EXPR { BODY }
243
263
```
244
264
Result:
245
265
``` rust
@@ -251,7 +271,7 @@ match EXPR {
251
271
252
272
Source:
253
273
``` rust
254
- if let PAT [| PAT ]* = EXPR { BODY_IF } else { BODY_ELSE }
274
+ if let | ? PAT [| PAT ]* = EXPR { BODY_IF } else { BODY_ELSE }
255
275
```
256
276
Result:
257
277
``` rust
@@ -265,7 +285,7 @@ Source:
265
285
``` rust
266
286
if COND {
267
287
BODY_IF
268
- } else if let PAT [| PAT ]* = EXPR {
288
+ } else if let | ? PAT [| PAT ]* = EXPR {
269
289
BODY_ELSE_IF
270
290
} else {
271
291
BODY_ELSE
@@ -277,15 +297,15 @@ if COND {
277
297
BODY_IF
278
298
} else {
279
299
match EXPR {
280
- PAT [| PAT ]* => { BODY_ELSE_IF }
300
+ | ? PAT [| PAT ]* => { BODY_ELSE_IF }
281
301
_ => { BODY_ELSE }
282
302
}
283
303
}
284
304
```
285
305
286
306
Source
287
307
``` rust
288
- if let PAT [| PAT ]* = EXPR {
308
+ if let | ? PAT [| PAT ]* = EXPR {
289
309
BODY_IF
290
310
} else if COND {
291
311
BODY_ELSE_IF_1
@@ -296,7 +316,7 @@ if let PAT [| PAT]* = EXPR {
296
316
Result:
297
317
``` rust
298
318
match EXPR {
299
- PAT [| PAT ]* => { BODY_IF }
319
+ | ? PAT [| PAT ]* => { BODY_IF }
300
320
_ if COND => { BODY_ELSE_IF_1 }
301
321
_ if OTHER_COND => { BODY_ELSE_IF_2 }
302
322
_ => {}
@@ -311,7 +331,7 @@ The following example is an extension on the [`while let` RFC].
311
331
312
332
Source
313
333
``` rust
314
- ['label : ] while let PAT [| PAT ]* = EXPR {
334
+ ['label : ] while let | ? PAT [| PAT ]* = EXPR {
315
335
BODY
316
336
}
317
337
```
@@ -325,6 +345,34 @@ Result:
325
345
}
326
346
```
327
347
348
+ ### Examples, ` for `
349
+
350
+ Assuming that the semantics of ` for ` is defined by a desugaring from:
351
+
352
+ ``` rust
353
+ for PAT in EXPR_ITER {
354
+ BODY
355
+ }
356
+ ```
357
+
358
+ into:
359
+
360
+ ``` rust
361
+ match IntoIterator :: into_iter (EXPR_ITER ) {
362
+ mut iter => loop {
363
+ let next = match iter . next () {
364
+ Some (val ) => val ,
365
+ None => break ,
366
+ };
367
+ let PAT = next ;
368
+ { BODY };
369
+ },
370
+ };
371
+ ```
372
+
373
+ then the only thing that changes is that ` PAT ` may include ` | ` at the top level
374
+ in the ` for ` loop and the desugaring as per the section on grammar.
375
+
328
376
## Desugaring ` let ` statements with ` | ` in the top-level pattern
329
377
330
378
This is a possible desugaring that a Rust compiler may do.
@@ -371,7 +419,7 @@ It could be claimed that the `if/while let` RFCs already mandate this RFC,
371
419
this RFC does answer that question and instead simply mandates it now.
372
420
373
421
Another alternative is to only deal with ` if/while let ` expressions but not
374
- ` let ` statements.
422
+ ` let ` and ` for ` statements.
375
423
376
424
# Unresolved questions
377
425
[ unresolved ] : #unresolved-questions
0 commit comments