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