]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/expressions/loop-expr.md
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / src / doc / reference / src / expressions / loop-expr.md
CommitLineData
ea8adc8c
XL
1# Loops
2
8faf50e0
XL
3> **<sup>Syntax</sup>**\
4> _LoopExpression_ :\
5> &nbsp;&nbsp; [_LoopLabel_]<sup>?</sup> (\
6> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_InfiniteLoopExpression_]\
7> &nbsp;&nbsp; &nbsp;&nbsp; | [_PredicateLoopExpression_]\
8> &nbsp;&nbsp; &nbsp;&nbsp; | [_PredicatePatternLoopExpression_]\
9> &nbsp;&nbsp; &nbsp;&nbsp; | [_IteratorLoopExpression_]\
10> &nbsp;&nbsp; )
ff7c6d11
XL
11
12[_LoopLabel_]: #loop-labels
13[_InfiniteLoopExpression_]: #infinite-loops
14[_PredicateLoopExpression_]: #predicate-loops
15[_PredicatePatternLoopExpression_]: #predicate-pattern-loops
16[_IteratorLoopExpression_]: #iterator-loops
17
ea8adc8c
XL
18Rust supports four loop expressions:
19
20* A [`loop` expression](#infinite-loops) denotes an infinite loop.
21* A [`while` expression](#predicate-loops) loops until a predicate is false.
532ac7d7 22* A [`while let` expression](#predicate-pattern-loops) tests a pattern.
6a06907d 23* A [`for` expression](#iterator-loops) extracts values from an iterator, looping until the iterator is empty.
ea8adc8c 24
6a06907d 25All four types of loop support [`break` expressions](#break-expressions), [`continue` expressions](#continue-expressions), and [labels](#loop-labels).
ea8adc8c
XL
26Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values).
27
28## Infinite loops
29
8faf50e0
XL
30> **<sup>Syntax</sup>**\
31> _InfiniteLoopExpression_ :\
ff7c6d11
XL
32> &nbsp;&nbsp; `loop` [_BlockExpression_]
33
ea8adc8c
XL
34A `loop` expression repeats execution of its body continuously:
35`loop { println!("I live."); }`.
36
6a06907d
XL
37A `loop` expression without an associated `break` expression is diverging and has type [`!`](../types/never.md).
38A `loop` expression containing associated [`break` expression(s)](#break-expressions) may terminate, and must have type compatible with the value of the `break` expression(s).
ea8adc8c
XL
39
40## Predicate loops
41
8faf50e0
XL
42> **<sup>Syntax</sup>**\
43> _PredicateLoopExpression_ :\
ba9703b0 44> &nbsp;&nbsp; `while` [_Expression_]<sub>_except struct expression_</sub> [_BlockExpression_]
ff7c6d11 45
6a06907d
XL
46A `while` loop begins by evaluating the [boolean] loop conditional operand.
47If the loop conditional operand evaluates to `true`, the loop body block executes, then control returns to the loop conditional operand.
48If the loop conditional expression evaluates to `false`, the `while` expression completes.
ea8adc8c
XL
49
50An example:
51
52```rust
53let mut i = 0;
54
55while i < 10 {
56 println!("hello");
57 i = i + 1;
58}
59```
60
ff7c6d11
XL
61## Predicate pattern loops
62
8faf50e0
XL
63> **<sup>Syntax</sup>**\
64> [_PredicatePatternLoopExpression_] :\
ba9703b0 65> &nbsp;&nbsp; `while` `let` [_MatchArmPatterns_] `=` [_Expression_]<sub>_except struct or lazy boolean operator expression_</sub>
8faf50e0 66> [_BlockExpression_]
ea8adc8c 67
6a06907d
XL
68A `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.
69If the value of the scrutinee matches the pattern, the loop body block executes then control returns to the pattern matching statement.
70Otherwise, the while expression completes.
ea8adc8c
XL
71
72```rust
73let mut x = vec![1, 2, 3];
74
75while let Some(y) = x.pop() {
76 println!("y = {}", y);
77}
532ac7d7
XL
78
79while let _ = 5 {
80 println!("Irrefutable patterns are always true");
81 break;
82}
ea8adc8c
XL
83```
84
6a06907d 85A `while let` loop is equivalent to a `loop` expression containing a [`match` expression] as follows.
0bf4aa26 86
60c5eb7d 87<!-- ignore: expansion example -->
0bf4aa26 88```rust,ignore
532ac7d7 89'label: while let PATS = EXPR {
0bf4aa26
XL
90 /* loop body */
91}
92```
93
94is equivalent to
95
60c5eb7d 96<!-- ignore: expansion example -->
0bf4aa26
XL
97```rust,ignore
98'label: loop {
99 match EXPR {
532ac7d7 100 PATS => { /* loop body */ },
0bf4aa26
XL
101 _ => break,
102 }
103}
104```
105
6a06907d
XL
106Multiple patterns may be specified with the `|` operator.
107This has the same semantics as with `|` in `match` expressions:
532ac7d7
XL
108
109```rust
110let mut vals = vec![2, 3, 1, 2, 2];
111while let Some(v @ 1) | Some(v @ 2) = vals.pop() {
112 // Prints 2, 2, then 1
113 println!("{}", v);
114}
115```
116
ba9703b0
XL
117As is the case in [`if let` expressions], the scrutinee cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_].
118
ea8adc8c
XL
119## Iterator loops
120
8faf50e0
XL
121> **<sup>Syntax</sup>**\
122> _IteratorLoopExpression_ :\
ba9703b0 123> &nbsp;&nbsp; `for` [_Pattern_] `in` [_Expression_]<sub>_except struct expression_</sub>
ff7c6d11
XL
124> [_BlockExpression_]
125
6a06907d
XL
126A `for` expression is a syntactic construct for looping over elements provided by an implementation of `std::iter::IntoIterator`.
127If 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.
128If the iterator is empty, the `for` expression completes.
ea8adc8c
XL
129
130An example of a `for` loop over the contents of an array:
131
132```rust
133let v = &["apples", "cake", "coffee"];
134
135for text in v {
136 println!("I like {}.", text);
137}
138```
139
140An example of a for loop over a series of integers:
141
142```rust
143let mut sum = 0;
144for n in 1..11 {
145 sum += n;
146}
147assert_eq!(sum, 55);
148```
149
0bf4aa26
XL
150A for loop is equivalent to the following block expression.
151
60c5eb7d 152<!-- ignore: expansion example -->
0bf4aa26
XL
153```rust,ignore
154'label: for PATTERN in iter_expr {
155 /* loop body */
156}
157```
158
159is equivalent to
160
60c5eb7d 161<!-- ignore: expansion example -->
0bf4aa26
XL
162```rust,ignore
163{
164 let result = match IntoIterator::into_iter(iter_expr) {
165 mut iter => 'label: loop {
166 let mut next;
167 match Iterator::next(&mut iter) {
168 Option::Some(val) => next = val,
169 Option::None => break,
170 };
f035d41b 171 let PATTERN = next;
0bf4aa26
XL
172 let () = { /* loop body */ };
173 },
174 };
175 result
176}
177```
178
6a06907d
XL
179`IntoIterator`, `Iterator`, and `Option` are always the standard library items here, not whatever those names resolve to in the current scope.
180The variable names `next`, `iter`, and `val` are for exposition only, they do not actually have names the user can type.
0bf4aa26 181
6a06907d
XL
182> **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.
183> `next` is declared before being assigned because it results in types being inferred correctly more often.
0bf4aa26 184
ea8adc8c
XL
185## Loop labels
186
8faf50e0
XL
187> **<sup>Syntax</sup>**\
188> _LoopLabel_ :\
ff7c6d11
XL
189> &nbsp;&nbsp; [LIFETIME_OR_LABEL] `:`
190
6a06907d
XL
191A 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 {}`.
192If 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.
193See [break expressions](#break-expressions) and [continue expressions](#continue-expressions).
ea8adc8c
XL
194
195## `break` expressions
196
8faf50e0
XL
197> **<sup>Syntax</sup>**\
198> _BreakExpression_ :\
ff7c6d11
XL
199> &nbsp;&nbsp; `break` [LIFETIME_OR_LABEL]<sup>?</sup> [_Expression_]<sup>?</sup>
200
6a06907d 201When `break` is encountered, execution of the associated loop body is immediately terminated, for example:
ea8adc8c
XL
202
203```rust
204let mut last = 0;
205for x in 1..100 {
206 if x > 12 {
207 break;
208 }
209 last = x;
210}
211assert_eq!(last, 12);
212```
213
6a06907d
XL
214A `break` expression is normally associated with the innermost `loop`, `for` or `while` loop enclosing the `break` expression,
215but a [label](#loop-labels) can be used to specify which enclosing loop is affected.
216Example:
ea8adc8c
XL
217
218```rust
219'outer: loop {
220 while true {
221 break 'outer;
222 }
223}
224```
225
6a06907d 226A `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`.
ea8adc8c
XL
227
228## `continue` expressions
229
8faf50e0
XL
230> **<sup>Syntax</sup>**\
231> _ContinueExpression_ :\
ff7c6d11
XL
232> &nbsp;&nbsp; `continue` [LIFETIME_OR_LABEL]<sup>?</sup>
233
6a06907d
XL
234When `continue` is encountered, the current iteration of the associated loop body is immediately terminated, returning control to the loop *head*.
235In the case of a `while` loop, the head is the conditional expression controlling the loop.
236In the case of a `for` loop, the head is the call-expression controlling the loop.
ea8adc8c 237
6a06907d 238Like `break`, `continue` is normally associated with the innermost enclosing loop, but `continue 'label` may be used to specify the loop affected.
ea8adc8c
XL
239A `continue` expression is only permitted in the body of a loop.
240
241## `break` and loop values
242
6a06907d
XL
243When 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`.
244For example:
ea8adc8c
XL
245
246```rust
247let (mut a, mut b) = (1, 1);
248let result = loop {
249 if b > 10 {
250 break b;
251 }
252 let c = a + b;
253 a = b;
254 b = c;
255};
256// first number in Fibonacci sequence over 10:
257assert_eq!(result, 13);
258```
259
6a06907d
XL
260In 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.
261`break` without an expression is considered identical to `break` with expression `()`.
ff7c6d11 262
416331ca
XL
263[LIFETIME_OR_LABEL]: ../tokens.md#lifetimes-and-loop-labels
264[_BlockExpression_]: block-expr.md
e1599b0c 265[_Expression_]: ../expressions.md
416331ca
XL
266[_MatchArmPatterns_]: match-expr.md
267[_Pattern_]: ../patterns.md
268[`match` expression]: match-expr.md
6a06907d 269[boolean]: ../types/boolean.md
416331ca 270[scrutinee]: ../glossary.md#scrutinee
f9f354fc 271[temporary values]: ../expressions.md#temporaries
ba9703b0
XL
272[_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators
273[`if let` expressions]: if-expr.md#if-let-expressions