]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/expressions/loop-expr.md
New upstream version 1.34.2+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.
ff7c6d11 22* A [`while let` expression](#predicate-pattern-loops) tests a refutable 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
13cf67c4 40has type [`!`](types/never.html). 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_ :\
ff7c6d11
XL
48> &nbsp;&nbsp; `while` [_Expression_]<sub>except struct expression</sub> [_BlockExpression_]
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_] :\
0bf4aa26 70> &nbsp;&nbsp; `while` `let` [_Pattern_] `=` [_Expression_]<sub>except struct expression</sub>
8faf50e0 71> [_BlockExpression_]
ea8adc8c
XL
72
73A `while let` loop is semantically similar to a `while` loop but in place of a
74condition expression it expects the keyword `let` followed by a refutable
9fa01778
XL
75pattern, an `=`, a [scrutinee] expression and a block expression. If the value of
76the expression on the right hand side of the `=` matches the pattern, the loop
77body block executes then control returns to the pattern matching statement.
78Otherwise, the while expression completes.
ea8adc8c
XL
79
80```rust
81let mut x = vec![1, 2, 3];
82
83while let Some(y) = x.pop() {
84 println!("y = {}", y);
85}
86```
87
0bf4aa26
XL
88A `while let` loop is equivalent to a `loop` expression containing a `match`
89expression as follows.
90
91```rust,ignore
92'label: while let PAT = EXPR {
93 /* loop body */
94}
95```
96
97is equivalent to
98
99```rust,ignore
100'label: loop {
101 match EXPR {
102 PAT => { /* loop body */ },
103 _ => break,
104 }
105}
106```
107
ea8adc8c
XL
108## Iterator loops
109
8faf50e0
XL
110> **<sup>Syntax</sup>**\
111> _IteratorLoopExpression_ :\
0bf4aa26 112> &nbsp;&nbsp; `for` [_Pattern_] `in` [_Expression_]<sub>except struct expression</sub>
ff7c6d11
XL
113> [_BlockExpression_]
114
ea8adc8c
XL
115A `for` expression is a syntactic construct for looping over elements provided
116by an implementation of `std::iter::IntoIterator`. If the iterator yields a
117value, that value is given the specified name and the body of the loop is
118executed, then control returns to the head of the `for` loop. If the iterator
119is empty, the `for` expression completes.
120
121An example of a `for` loop over the contents of an array:
122
123```rust
124let v = &["apples", "cake", "coffee"];
125
126for text in v {
127 println!("I like {}.", text);
128}
129```
130
131An example of a for loop over a series of integers:
132
133```rust
134let mut sum = 0;
135for n in 1..11 {
136 sum += n;
137}
138assert_eq!(sum, 55);
139```
140
0bf4aa26
XL
141A for loop is equivalent to the following block expression.
142
143```rust,ignore
144'label: for PATTERN in iter_expr {
145 /* loop body */
146}
147```
148
149is equivalent to
150
151```rust,ignore
152{
153 let result = match IntoIterator::into_iter(iter_expr) {
154 mut iter => 'label: loop {
155 let mut next;
156 match Iterator::next(&mut iter) {
157 Option::Some(val) => next = val,
158 Option::None => break,
159 };
160 let PAT = next;
161 let () = { /* loop body */ };
162 },
163 };
164 result
165}
166```
167
168`IntoIterator`, `Iterator` and `Option` are always the standard library items
169here, not whatever those names resolve to in the current scope. The variable
170names `next`, `iter` and `val` are for exposition only, they do not actually
171have names the user can type.
172
173> **Note**: that the outer `match` is used to ensure that any
174> [temporary values] in `iter_expr` don't get dropped before the loop is
175> finished. `next` is declared before being assigned because it results in
176> types being inferred correctly more often.
177
ea8adc8c
XL
178## Loop labels
179
8faf50e0
XL
180> **<sup>Syntax</sup>**\
181> _LoopLabel_ :\
ff7c6d11
XL
182> &nbsp;&nbsp; [LIFETIME_OR_LABEL] `:`
183
ea8adc8c
XL
184A loop expression may optionally have a _label_. The label is written as
185a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`,
186`'bar: while false {}`, `'humbug: for _ in 0..0 {}`.
187If a label is present, then labeled `break` and `continue` expressions nested
188within this loop may exit out of this loop or return control to its head.
189See [break expressions](#break-expressions) and [continue
190expressions](#continue-expressions).
191
192## `break` expressions
193
8faf50e0
XL
194> **<sup>Syntax</sup>**\
195> _BreakExpression_ :\
ff7c6d11
XL
196> &nbsp;&nbsp; `break` [LIFETIME_OR_LABEL]<sup>?</sup> [_Expression_]<sup>?</sup>
197
ea8adc8c
XL
198When `break` is encountered, execution of the associated loop body is
199immediately terminated, for example:
200
201```rust
202let mut last = 0;
203for x in 1..100 {
204 if x > 12 {
205 break;
206 }
207 last = x;
208}
209assert_eq!(last, 12);
210```
211
212A `break` expression is normally associated with the innermost `loop`, `for` or
213`while` loop enclosing the `break` expression, but a [label](#loop-labels) can
214be used to specify which enclosing loop is affected. Example:
215
216```rust
217'outer: loop {
218 while true {
219 break 'outer;
220 }
221}
222```
223
224A `break` expression is only permitted in the body of a loop, and has one of
225the forms `break`, `break 'label` or ([see below](#break-and-loop-values))
226`break EXPR` or `break 'label EXPR`.
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
ea8adc8c
XL
234When `continue` is encountered, the current iteration of the associated loop
235body is immediately terminated, returning control to the loop *head*. In
236the case of a `while` loop, the head is the conditional expression controlling
237the loop. In the case of a `for` loop, the head is the call-expression
238controlling the loop.
239
240Like `break`, `continue` is normally associated with the innermost enclosing
241loop, but `continue 'label` may be used to specify the loop affected.
242A `continue` expression is only permitted in the body of a loop.
243
244## `break` and loop values
245
246When associated with a `loop`, a break expression may be used to return a value
247from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where
248`EXPR` is an expression whose result is returned from the `loop`. For example:
249
250```rust
251let (mut a, mut b) = (1, 1);
252let result = loop {
253 if b > 10 {
254 break b;
255 }
256 let c = a + b;
257 a = b;
258 b = c;
259};
260// first number in Fibonacci sequence over 10:
261assert_eq!(result, 13);
262```
263
264In the case a `loop` has an associated `break`, it is not considered diverging,
265and the `loop` must have a type compatible with each `break` expression.
266`break` without an expression is considered identical to `break` with
267expression `()`.
ff7c6d11
XL
268
269[IDENTIFIER]: identifiers.html
0bf4aa26 270[temporary values]: expressions.html#temporary-lifetimes
ff7c6d11
XL
271
272[_Expression_]: expressions.html
273[_BlockExpression_]: expressions/block-expr.html
0bf4aa26 274[_Pattern_]: patterns.html
ff7c6d11 275
0531ce1d 276[LIFETIME_OR_LABEL]: tokens.html#lifetimes-and-loop-labels
9fa01778
XL
277
278[scrutinee]: glossary.html#scrutinee