]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/expressions/if-expr.md
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / src / doc / reference / src / expressions / if-expr.md
CommitLineData
ea8adc8c
XL
1# `if` and `if let` expressions
2
3## `if` expressions
4
8faf50e0
XL
5> **<sup>Syntax</sup>**\
6> _IfExpression_ :\
7> &nbsp;&nbsp; `if` [_Expression_]<sub>_except struct expression_</sub> [_BlockExpression_]\
ff7c6d11
XL
8> &nbsp;&nbsp; (`else` (
9> [_BlockExpression_]
10> | _IfExpression_
8faf50e0 11> | _IfLetExpression_ ) )<sup>\?</sup>
ff7c6d11 12
6a06907d
XL
13An `if` expression is a conditional branch in program control.
14The syntax of an `if` expression is a condition operand, followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` block.
15The condition operands must have the [boolean type].
16If a condition operand evaluates to `true`, the consequent block is executed and any subsequent `else if` or `else` block is skipped.
17If a condition operand evaluates to `false`, the consequent block is skipped and any subsequent `else if` condition is evaluated.
18If all `if` and `else if` conditions evaluate to `false` then any `else` block is executed.
19An if expression evaluates to the same value as the executed block, or `()` if no block is evaluated.
20An `if` expression must have the same type in all situations.
ea8adc8c
XL
21
22```rust
23# let x = 3;
24if x == 4 {
25 println!("x is four");
26} else if x == 3 {
27 println!("x is three");
28} else {
29 println!("x is something else");
30}
31
32let y = if 12 * 15 > 150 {
33 "Bigger"
34} else {
35 "Smaller"
36};
37assert_eq!(y, "Bigger");
38```
ff7c6d11 39
ea8adc8c
XL
40## `if let` expressions
41
8faf50e0
XL
42> **<sup>Syntax</sup>**\
43> _IfLetExpression_ :\
532ac7d7 44> &nbsp;&nbsp; `if` `let` [_MatchArmPatterns_] `=` [_Expression_]<sub>_except struct or lazy boolean operator expression_</sub>
8faf50e0 45> [_BlockExpression_]\
ff7c6d11
XL
46> &nbsp;&nbsp; (`else` (
47> [_BlockExpression_]
48> | _IfExpression_
8faf50e0 49> | _IfLetExpression_ ) )<sup>\?</sup>
ff7c6d11 50
6a06907d
XL
51An `if let` expression is semantically similar to an `if` expression but in place of a condition operand it expects the keyword `let` followed by a pattern, an `=` and a [scrutinee] operand.
52If the value of the scrutinee matches the pattern, the corresponding block will execute.
53Otherwise, flow proceeds to the following `else` block if it exists.
54Like `if` expressions, `if let` expressions have a value determined by the block that is evaluated.
ea8adc8c
XL
55
56```rust
57let dish = ("Ham", "Eggs");
58
59// this body will be skipped because the pattern is refuted
60if let ("Bacon", b) = dish {
61 println!("Bacon is served with {}", b);
62} else {
63 // This block is evaluated instead.
64 println!("No bacon will be served");
65}
66
67// this body will execute
68if let ("Ham", b) = dish {
69 println!("Ham is served with {}", b);
70}
532ac7d7
XL
71
72if let _ = 5 {
73 println!("Irrefutable patterns are always true");
74}
ea8adc8c 75```
ff7c6d11
XL
76
77`if` and `if let` expressions can be intermixed:
78
79```rust
80let x = Some(3);
81let a = if let Some(1) = x {
82 1
83} else if x == Some(2) {
84 2
85} else if let Some(y) = x {
86 y
87} else {
88 -1
89};
90assert_eq!(a, 3);
91```
92
532ac7d7 93An `if let` expression is equivalent to a [`match` expression] as follows:
0bf4aa26 94
60c5eb7d 95<!-- ignore: expansion example -->
0bf4aa26 96```rust,ignore
532ac7d7 97if let PATS = EXPR {
0bf4aa26
XL
98 /* body */
99} else {
100 /*else */
101}
102```
103
104is equivalent to
105
60c5eb7d 106<!-- ignore: expansion example -->
0bf4aa26
XL
107```rust,ignore
108match EXPR {
532ac7d7 109 PATS => { /* body */ },
0bf4aa26
XL
110 _ => { /* else */ }, // () if there is no else
111}
112```
113
6a06907d 114Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in `match` expressions:
532ac7d7
XL
115
116```rust
117enum E {
118 X(u8),
119 Y(u8),
120 Z(u8),
121}
122let v = E::Y(12);
123if let E::X(n) | E::Y(n) = v {
124 assert_eq!(n, 12);
125}
126```
127
0bf4aa26 128The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_].
6a06907d
XL
129Use of a lazy boolean operator is ambiguous with a planned feature change of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]).
130When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below:
0bf4aa26 131
60c5eb7d 132<!-- ignore: psuedo code -->
0bf4aa26
XL
133```rust,ignore
134// Before...
135if let PAT = EXPR && EXPR { .. }
136
137// After...
138if let PAT = ( EXPR && EXPR ) { .. }
139
140// Before...
141if let PAT = EXPR || EXPR { .. }
142
143// After...
144if let PAT = ( EXPR || EXPR ) { .. }
145```
146
416331ca
XL
147[_BlockExpression_]: block-expr.md
148[_Expression_]: ../expressions.md
149[_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators
150[_MatchArmPatterns_]: match-expr.md
0bf4aa26 151[_eRFCIfLetChain_]: https://github.com/rust-lang/rfcs/blob/master/text/2497-if-let-chains.md#rollout-plan-and-transitioning-to-rust-2018
416331ca 152[`match` expression]: match-expr.md
6a06907d 153[boolean type]: ../types/boolean.md
416331ca 154[scrutinee]: ../glossary.md#scrutinee