You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* A [`loop` expression](#infinite-loops) denotes an infinite loop.
@@ -25,29 +29,47 @@ Rust supports five loop expressions:
25
29
* A [`for` expression](#iterator-loops) extracts values from an iterator, looping until the iterator is empty.
26
30
* A [labelled block expression](#labelled-block-expressions) runs a loop exactly once, but allows exiting the loop early with `break`.
27
31
32
+
r[expr.loop.break-label]
28
33
All five types of loop support [`break` expressions](#break-expressions), and [labels](#loop-labels).
34
+
35
+
r[expr.loop.continue]
29
36
All except labelled block expressions support [`continue` expressions](#continue-expressions).
37
+
38
+
r[expr.loop.explicit-result]
30
39
Only `loop` and labelled block expressions support [evaluation to non-trivial values](#break-and-loop-values).
31
40
32
41
## Infinite loops
33
42
43
+
r[expr.loop.infinite]
44
+
45
+
r[expr.loop.infinite.syntax]
34
46
> **<sup>Syntax</sup>**\
35
47
> _InfiniteLoopExpression_ :\
36
48
> `loop`[_BlockExpression_]
37
49
50
+
r[expr.loop.infinite.intro]
38
51
A `loop` expression repeats execution of its body continuously:
39
52
`loop { println!("I live."); }`.
40
53
54
+
r[expr.loop.infinite.diverging]
41
55
A `loop` expression without an associated `break` expression is diverging and has type [`!`](../types/never.md).
56
+
57
+
r[expr.loop.infinite.break]
42
58
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).
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]
74
102
If the value of the scrutinee matches the pattern, the loop body block executes then control returns to the pattern matching statement.
75
103
Otherwise, the while expression completes.
76
104
@@ -87,6 +115,7 @@ while let _ = 5 {
87
115
}
88
116
```
89
117
118
+
r[expr.loop.while.let.desugar]
90
119
A `while let` loop is equivalent to a `loop` expression containing a [`match` expression] as follows.
91
120
92
121
<!-- ignore: expansion example -->
@@ -108,6 +137,7 @@ is equivalent to
108
137
}
109
138
```
110
139
140
+
r[expr.loop.while.let.or-pattern]
111
141
Multiple patterns may be specified with the `|` operator.
112
142
This has the same semantics as with `|` in `match` expressions:
113
143
@@ -119,16 +149,23 @@ while let Some(v @ 1) | Some(v @ 2) = vals.pop() {
119
149
}
120
150
```
121
151
152
+
r[expr.loop.while.let.restriction]
122
153
As is the case in [`if let` expressions], the scrutinee cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_].
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]
132
169
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.
133
170
If the iterator is empty, the `for` expression completes.
134
171
@@ -152,6 +189,7 @@ for n in 1..11 {
152
189
assert_eq!(sum, 55);
153
190
```
154
191
192
+
r[expr.loop.for.desugar]
155
193
A `for` loop is equivalent to a `loop` expression containing a [`match` expression] as follows:
156
194
157
195
<!-- ignore: expansion example -->
@@ -181,22 +219,31 @@ is equivalent to
181
219
}
182
220
```
183
221
222
+
r[expr.loop.for.lang-items]
184
223
`IntoIterator`, `Iterator`, and `Option` are always the standard library items here, not whatever those names resolve to in the current scope.
224
+
185
225
The variable names `next`, `iter`, and `val` are for exposition only, they do not actually have names the user can type.
186
226
187
227
> **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.
188
228
> `next` is declared before being assigned because it results in types being inferred correctly more often.
189
229
190
230
## Loop labels
191
231
232
+
r[expr.loop.label]
233
+
234
+
r[expr.loop.label.syntax]
192
235
> **<sup>Syntax</sup>**\
193
236
> _LoopLabel_ :\
194
237
> [LIFETIME_OR_LABEL]`:`
195
238
239
+
r[expr.loop.label.intro]
196
240
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]
197
243
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.
198
244
See [break expressions](#break-expressions) and [continue expressions](#continue-expressions).
199
245
246
+
r[expr.loop.label.ref]
200
247
Labels follow the hygiene and shadowing rules of local variables. For example, this code will print "outer loop":
201
248
202
249
```rust
@@ -213,10 +260,14 @@ Labels follow the hygiene and shadowing rules of local variables. For example, t
When `break` is encountered, execution of the associated loop body is immediately terminated, for example:
221
272
222
273
```rust
@@ -230,6 +281,7 @@ for x in 1..100 {
230
281
assert_eq!(last, 12);
231
282
```
232
283
284
+
r[expr.loop.break.label]
233
285
A `break` expression is normally associated with the innermost `loop`, `for` or `while` loop enclosing the `break` expression,
234
286
but a [label](#loop-labels) can be used to specify which enclosing loop is affected.
235
287
Example:
@@ -242,16 +294,24 @@ Example:
242
294
}
243
295
```
244
296
297
+
r[expr.loop.break.value]
245
298
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`.
246
299
247
300
## Labelled block expressions
248
301
302
+
r[expr.loop.block-labels]
303
+
249
304
> **<sup>Syntax</sup>**\
250
305
> _LabelBlockExpression_ :\
251
306
> [_BlockExpression_]
252
307
308
+
r[expr.loop.block-labels.intro]
253
309
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]
254
312
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]
255
315
Similarly, labelled block expressions *must* begin with a label.
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]
283
349
In the case of a `while` loop, the head is the conditional expression controlling the loop.
350
+
351
+
r[expr.loop.continue.for]
284
352
In the case of a `for` loop, the head is the call-expression controlling the loop.
285
353
354
+
r[expr.loop.continue.label]
286
355
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]
287
358
A `continue` expression is only permitted in the body of a loop.
288
359
289
360
## `break` and loop values
290
361
362
+
r[expr.loop.break-value]
363
+
364
+
r[expr.loop.break-value.intro]
291
365
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`.
292
366
For example:
293
367
@@ -305,6 +379,7 @@ let result = loop {
305
379
assert_eq!(result, 13);
306
380
```
307
381
382
+
r[expr.loop.break-value.loop]
308
383
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.
309
384
`break` without an expression is considered identical to `break` with expression `()`.
Copy file name to clipboardExpand all lines: src/expressions/match-expr.md
+38Lines changed: 38 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,8 @@
1
1
# `match` expressions
2
2
3
+
r[expr.match]
4
+
5
+
r[expr.match.syntax]
3
6
> **<sup>Syntax</sup>**\
4
7
> _MatchExpression_ :\
5
8
> `match`_Scrutinee_`{`\
@@ -23,15 +26,24 @@
23
26
> _MatchArmGuard_ :\
24
27
> `if`[_Expression_]
25
28
29
+
r[expr.match.intro]
26
30
A *`match` expression* branches on a pattern.
27
31
The exact form of matching that occurs depends on the [pattern].
32
+
33
+
r[expr.match.scrutinee]
28
34
A `match` expression has a *[scrutinee] expression*, which is the value to compare to the patterns.
35
+
36
+
r[expr.match.scrutinee-constraint]
29
37
The scrutinee expression and the patterns must have the same type.
30
38
39
+
r[expr.match.scrutinee-behaviour]
31
40
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]
32
43
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.
33
44
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.
34
45
46
+
r[expr.match.scrutinee-place]
35
47
When the scrutinee expression is a [place expression], the match does not allocate a temporary location;
36
48
however, a by-value binding may copy or move from the memory location.
37
49
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 {
51
63
}
52
64
```
53
65
66
+
r[expr.match.pattern-vars]
54
67
Variables bound within the pattern are scoped to the match guard and the arm's expression.
68
+
69
+
r[expr.match.pattern-var-binding]
55
70
The [binding mode] (move, copy, or reference) depends on the pattern.
56
71
72
+
r[expr.match.or-pattern]
57
73
Multiple match patterns may be joined with the `|` operator.
58
74
Each pattern will be tested in left-to-right sequence until a successful match is found.
59
75
@@ -79,16 +95,27 @@ match S(1, 2) {
79
95
> Note: The `2..=9` is a [Range Pattern], not a [Range Expression].
80
96
> Thus, only those types of ranges supported by range patterns can be used in match arms.
81
97
98
+
r[expr.match.or-patterns-restriction]
82
99
Every binding in each `|` separated pattern must appear in all of the patterns in the arm.
100
+
101
+
r[expr.match.binding-restriction]
83
102
Every binding of the same name must have the same type, and have the same binding mode.
84
103
85
104
## Match guards
86
105
106
+
r[expr.match.guard]
107
+
108
+
r[expr.match.guard.intro]
87
109
Match arms can accept _match guards_ to further refine the criteria for matching a case.
110
+
111
+
r[expr.match.guard.type]
88
112
Pattern guards appear after the pattern and consist of a `bool`-typed expression following the `if` keyword.
89
113
114
+
r[expr.match.guard.behaviour]
90
115
When the pattern matches successfully, the pattern guard expression is executed.
91
116
If the expression evaluates to true, the pattern is successfully matched against.
117
+
118
+
r[expr.match.guard.next]
92
119
Otherwise, the next pattern, including other matches with the `|` operator in the same arm, is tested.
93
120
94
121
```rust
@@ -115,18 +142,29 @@ let message = match maybe_digit {
0 commit comments