Skip to content

Commit 2e00df4

Browse files
chorman0773ehuss
authored andcommitted
Add identifier syntax to loop-expr and match-expr
1 parent c4ebffe commit 2e00df4

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

src/expressions/loop-expr.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Loops and other breakable expressions
22

3+
r[expr.block]
4+
5+
r[expr.loop.syntax]
36
> **<sup>Syntax</sup>**\
47
> _LoopExpression_ :\
58
> &nbsp;&nbsp; [_LoopLabel_]<sup>?</sup> (\
@@ -17,6 +20,7 @@
1720
[_IteratorLoopExpression_]: #iterator-loops
1821
[_LabelBlockExpression_]: #labelled-block-expressions
1922

23+
r[expr.loop.intro]
2024
Rust supports five loop expressions:
2125

2226
* A [`loop` expression](#infinite-loops) denotes an infinite loop.
@@ -25,29 +29,47 @@ Rust supports five loop expressions:
2529
* A [`for` expression](#iterator-loops) extracts values from an iterator, looping until the iterator is empty.
2630
* A [labelled block expression](#labelled-block-expressions) runs a loop exactly once, but allows exiting the loop early with `break`.
2731

32+
r[expr.loop.break-label]
2833
All five types of loop support [`break` expressions](#break-expressions), and [labels](#loop-labels).
34+
35+
r[expr.loop.continue]
2936
All except labelled block expressions support [`continue` expressions](#continue-expressions).
37+
38+
r[expr.loop.explicit-result]
3039
Only `loop` and labelled block expressions support [evaluation to non-trivial values](#break-and-loop-values).
3140

3241
## Infinite loops
3342

43+
r[expr.loop.infinite]
44+
45+
r[expr.loop.infinite.syntax]
3446
> **<sup>Syntax</sup>**\
3547
> _InfiniteLoopExpression_ :\
3648
> &nbsp;&nbsp; `loop` [_BlockExpression_]
3749
50+
r[expr.loop.infinite.intro]
3851
A `loop` expression repeats execution of its body continuously:
3952
`loop { println!("I live."); }`.
4053

54+
r[expr.loop.infinite.diverging]
4155
A `loop` expression without an associated `break` expression is diverging and has type [`!`](../types/never.md).
56+
57+
r[expr.loop.infinite.break]
4258
A `loop` expression containing associated [`break` expression(s)](#break-expressions) may terminate, and must have type compatible with the value of the `break` expression(s).
4359

4460
## Predicate loops
4561

62+
r[expr.loop.while]
63+
64+
r[expr.loop.while.syntax]
4665
> **<sup>Syntax</sup>**\
4766
> _PredicateLoopExpression_ :\
4867
> &nbsp;&nbsp; `while` [_Expression_]<sub>_except struct expression_</sub> [_BlockExpression_]
4968
69+
r[expr.loop.while.intro]
5070
A `while` loop begins by evaluating the [boolean] loop conditional operand.
71+
72+
r[expr.loop.while.condition]
5173
If the loop conditional operand evaluates to `true`, the loop body block executes, then control returns to the loop conditional operand.
5274
If the loop conditional expression evaluates to `false`, the `while` expression completes.
5375

@@ -64,13 +86,19 @@ while i < 10 {
6486

6587
## Predicate pattern loops
6688

89+
r[expr.loop.while.let]
90+
91+
r[expr.loop.while.let.syntax]
6792
> **<sup>Syntax</sup>**\
6893
> [_PredicatePatternLoopExpression_] :\
6994
> &nbsp;&nbsp; `while` `let` [_Pattern_] `=` [_Scrutinee_]<sub>_except lazy boolean operator expression_</sub>
7095
> [_BlockExpression_]
7196
7297

98+
r[expr.loop.while.let.intro]
7399
A `while let` loop is semantically similar to a `while` loop but in place of a condition expression it expects the keyword `let` followed by a pattern, an `=`, a [scrutinee] expression and a block expression.
100+
101+
r[expr.loop.while.let.condition]
74102
If the value of the scrutinee matches the pattern, the loop body block executes then control returns to the pattern matching statement.
75103
Otherwise, the while expression completes.
76104

@@ -87,6 +115,7 @@ while let _ = 5 {
87115
}
88116
```
89117

118+
r[expr.loop.while.let.desugar]
90119
A `while let` loop is equivalent to a `loop` expression containing a [`match` expression] as follows.
91120

92121
<!-- ignore: expansion example -->
@@ -108,6 +137,7 @@ is equivalent to
108137
}
109138
```
110139

140+
r[expr.loop.while.let.or-pattern]
111141
Multiple patterns may be specified with the `|` operator.
112142
This has the same semantics as with `|` in `match` expressions:
113143

@@ -119,16 +149,23 @@ while let Some(v @ 1) | Some(v @ 2) = vals.pop() {
119149
}
120150
```
121151

152+
r[expr.loop.while.let.restriction]
122153
As is the case in [`if let` expressions], the scrutinee cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_].
123154

124155
## Iterator loops
125156

157+
r[expr.loop.for]
158+
159+
r[expr.loop.for.syntax]
126160
> **<sup>Syntax</sup>**\
127161
> _IteratorLoopExpression_ :\
128162
> &nbsp;&nbsp; `for` [_Pattern_] `in` [_Expression_]<sub>_except struct expression_</sub>
129163
> [_BlockExpression_]
130164
165+
r[expr.loop.for.intro]
131166
A `for` expression is a syntactic construct for looping over elements provided by an implementation of `std::iter::IntoIterator`.
167+
168+
r[expr.loop.for.condition]
132169
If the iterator yields a value, that value is matched against the irrefutable pattern, the body of the loop is executed, and then control returns to the head of the `for` loop.
133170
If the iterator is empty, the `for` expression completes.
134171

@@ -152,6 +189,7 @@ for n in 1..11 {
152189
assert_eq!(sum, 55);
153190
```
154191

192+
r[expr.loop.for.desugar]
155193
A `for` loop is equivalent to a `loop` expression containing a [`match` expression] as follows:
156194

157195
<!-- ignore: expansion example -->
@@ -181,22 +219,31 @@ is equivalent to
181219
}
182220
```
183221

222+
r[expr.loop.for.lang-items]
184223
`IntoIterator`, `Iterator`, and `Option` are always the standard library items here, not whatever those names resolve to in the current scope.
224+
185225
The variable names `next`, `iter`, and `val` are for exposition only, they do not actually have names the user can type.
186226

187227
> **Note**: that the outer `match` is used to ensure that any [temporary values] in `iter_expr` don't get dropped before the loop is finished.
188228
> `next` is declared before being assigned because it results in types being inferred correctly more often.
189229
190230
## Loop labels
191231

232+
r[expr.loop.label]
233+
234+
r[expr.loop.label.syntax]
192235
> **<sup>Syntax</sup>**\
193236
> _LoopLabel_ :\
194237
> &nbsp;&nbsp; [LIFETIME_OR_LABEL] `:`
195238
239+
r[expr.loop.label.intro]
196240
A loop expression may optionally have a _label_. The label is written as a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`, `'bar: while false {}`, `'humbug: for _ in 0..0 {}`.
241+
242+
r[expr.loop.label.control-flow]
197243
If a label is present, then labeled `break` and `continue` expressions nested within this loop may exit out of this loop or return control to its head.
198244
See [break expressions](#break-expressions) and [continue expressions](#continue-expressions).
199245

246+
r[expr.loop.label.ref]
200247
Labels follow the hygiene and shadowing rules of local variables. For example, this code will print "outer loop":
201248

202249
```rust
@@ -213,10 +260,14 @@ Labels follow the hygiene and shadowing rules of local variables. For example, t
213260

214261
## `break` expressions
215262

263+
r[expr.loop.break]
264+
265+
r[expr.loop.break.syntax]
216266
> **<sup>Syntax</sup>**\
217267
> _BreakExpression_ :\
218268
> &nbsp;&nbsp; `break` [LIFETIME_OR_LABEL]<sup>?</sup> [_Expression_]<sup>?</sup>
219269
270+
r[expr.loop.break.intro]
220271
When `break` is encountered, execution of the associated loop body is immediately terminated, for example:
221272

222273
```rust
@@ -230,6 +281,7 @@ for x in 1..100 {
230281
assert_eq!(last, 12);
231282
```
232283

284+
r[expr.loop.break.label]
233285
A `break` expression is normally associated with the innermost `loop`, `for` or `while` loop enclosing the `break` expression,
234286
but a [label](#loop-labels) can be used to specify which enclosing loop is affected.
235287
Example:
@@ -242,16 +294,24 @@ Example:
242294
}
243295
```
244296

297+
r[expr.loop.break.value]
245298
A `break` expression is only permitted in the body of a loop, and has one of the forms `break`, `break 'label` or ([see below](#break-and-loop-values)) `break EXPR` or `break 'label EXPR`.
246299

247300
## Labelled block expressions
248301

302+
r[expr.loop.block-labels]
303+
249304
> **<sup>Syntax</sup>**\
250305
> _LabelBlockExpression_ :\
251306
> &nbsp;&nbsp; [_BlockExpression_]
252307
308+
r[expr.loop.block-labels.intro]
253309
Labelled block expressions are exactly like block expressions, except that they allow using `break` expressions within the block.
310+
311+
r[expr.loop.block-labels.break]
254312
Unlike loops, `break` expressions within a labelled block expression *must* have a label (i.e. the label is not optional).
313+
314+
r[expr.loop.block-labels.restriction]
255315
Similarly, labelled block expressions *must* begin with a label.
256316

257317
```rust
@@ -275,19 +335,33 @@ let result = 'block: {
275335

276336
## `continue` expressions
277337

338+
r[expr.loop.continue]
339+
340+
r[expr.loop.continue.syntax]
278341
> **<sup>Syntax</sup>**\
279342
> _ContinueExpression_ :\
280343
> &nbsp;&nbsp; `continue` [LIFETIME_OR_LABEL]<sup>?</sup>
281344
345+
r[expr.loop.continue.intro]
282346
When `continue` is encountered, the current iteration of the associated loop body is immediately terminated, returning control to the loop *head*.
347+
348+
r[expr.loop.continue.while]
283349
In the case of a `while` loop, the head is the conditional expression controlling the loop.
350+
351+
r[expr.loop.continue.for]
284352
In the case of a `for` loop, the head is the call-expression controlling the loop.
285353

354+
r[expr.loop.continue.label]
286355
Like `break`, `continue` is normally associated with the innermost enclosing loop, but `continue 'label` may be used to specify the loop affected.
356+
357+
r[expr.loop.continue.constraint]
287358
A `continue` expression is only permitted in the body of a loop.
288359

289360
## `break` and loop values
290361

362+
r[expr.loop.break-value]
363+
364+
r[expr.loop.break-value.intro]
291365
When associated with a `loop`, a break expression may be used to return a value from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where `EXPR` is an expression whose result is returned from the `loop`.
292366
For example:
293367

@@ -305,6 +379,7 @@ let result = loop {
305379
assert_eq!(result, 13);
306380
```
307381

382+
r[expr.loop.break-value.loop]
308383
In the case a `loop` has an associated `break`, it is not considered diverging, and the `loop` must have a type compatible with each `break` expression.
309384
`break` without an expression is considered identical to `break` with expression `()`.
310385

src/expressions/match-expr.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# `match` expressions
22

3+
r[expr.match]
4+
5+
r[expr.match.syntax]
36
> **<sup>Syntax</sup>**\
47
> _MatchExpression_ :\
58
> &nbsp;&nbsp; `match` _Scrutinee_ `{`\
@@ -23,15 +26,24 @@
2326
> _MatchArmGuard_ :\
2427
> &nbsp;&nbsp; `if` [_Expression_]
2528
29+
r[expr.match.intro]
2630
A *`match` expression* branches on a pattern.
2731
The exact form of matching that occurs depends on the [pattern].
32+
33+
r[expr.match.scrutinee]
2834
A `match` expression has a *[scrutinee] expression*, which is the value to compare to the patterns.
35+
36+
r[expr.match.scrutinee-constraint]
2937
The scrutinee expression and the patterns must have the same type.
3038

39+
r[expr.match.scrutinee-behaviour]
3140
A `match` behaves differently depending on whether or not the scrutinee expression is a [place expression or value expression][place expression].
41+
42+
r[expr.match.scrutinee-value]
3243
If the scrutinee expression is a [value expression], it is first evaluated into a temporary location, and the resulting value is sequentially compared to the patterns in the arms until a match is found.
3344
The first arm with a matching pattern is chosen as the branch target of the `match`, any variables bound by the pattern are assigned to local variables in the arm's block, and control enters the block.
3445

46+
r[expr.match.scrutinee-place]
3547
When the scrutinee expression is a [place expression], the match does not allocate a temporary location;
3648
however, a by-value binding may copy or move from the memory location.
3749
When possible, it is preferable to match on place expressions, as the lifetime of these matches inherits the lifetime of the place expression rather than being restricted to the inside of the match.
@@ -51,9 +63,13 @@ match x {
5163
}
5264
```
5365

66+
r[expr.match.pattern-vars]
5467
Variables bound within the pattern are scoped to the match guard and the arm's expression.
68+
69+
r[expr.match.pattern-var-binding]
5570
The [binding mode] (move, copy, or reference) depends on the pattern.
5671

72+
r[expr.match.or-pattern]
5773
Multiple match patterns may be joined with the `|` operator.
5874
Each pattern will be tested in left-to-right sequence until a successful match is found.
5975

@@ -79,16 +95,27 @@ match S(1, 2) {
7995
> Note: The `2..=9` is a [Range Pattern], not a [Range Expression].
8096
> Thus, only those types of ranges supported by range patterns can be used in match arms.
8197
98+
r[expr.match.or-patterns-restriction]
8299
Every binding in each `|` separated pattern must appear in all of the patterns in the arm.
100+
101+
r[expr.match.binding-restriction]
83102
Every binding of the same name must have the same type, and have the same binding mode.
84103

85104
## Match guards
86105

106+
r[expr.match.guard]
107+
108+
r[expr.match.guard.intro]
87109
Match arms can accept _match guards_ to further refine the criteria for matching a case.
110+
111+
r[expr.match.guard.type]
88112
Pattern guards appear after the pattern and consist of a `bool`-typed expression following the `if` keyword.
89113

114+
r[expr.match.guard.behaviour]
90115
When the pattern matches successfully, the pattern guard expression is executed.
91116
If the expression evaluates to true, the pattern is successfully matched against.
117+
118+
r[expr.match.guard.next]
92119
Otherwise, the next pattern, including other matches with the `|` operator in the same arm, is tested.
93120

94121
```rust
@@ -115,18 +142,29 @@ let message = match maybe_digit {
115142
> assert_eq!(i.get(), 2);
116143
> ```
117144
145+
r[expr.match.guard.bound-variables]
118146
A pattern guard may refer to the variables bound within the pattern they follow.
147+
148+
r[expr.match.guard.shared-ref]
119149
Before evaluating the guard, a shared reference is taken to the part of the scrutinee the variable matches on.
120150
While evaluating the guard, this shared reference is then used when accessing the variable.
151+
152+
r[expr.match.guard.value]
121153
Only when the guard evaluates to true is the value moved, or copied, from the scrutinee into the variable.
122154
This allows shared borrows to be used inside guards without moving out of the scrutinee in case guard fails to match.
155+
156+
r[expr.match.guard.restriction]
123157
Moreover, by holding a shared reference while evaluating the guard, mutation inside guards is also prevented.
124158
125159
## Attributes on match arms
126160
161+
r[expr.match.attributes]
162+
163+
r[expr.match.attributes.outer]
127164
Outer attributes are allowed on match arms.
128165
The only attributes that have meaning on match arms are [`cfg`] and the [lint check attributes].
129166
167+
r[expr.match.attributes.inner]
130168
[Inner attributes] are allowed directly after the opening brace of the match expression in the same expression contexts as [attributes on block expressions].
131169
132170
[_Expression_]: ../expressions.md

0 commit comments

Comments
 (0)