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