]> git.proxmox.com Git - rustc.git/blob - src/doc/reference/src/expressions/if-expr.md
New upstream version 1.55.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.
14 The 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.
15 The condition operands must have the [boolean type].
16 If a condition operand evaluates to `true`, the consequent block is executed and any subsequent `else if` or `else` block is skipped.
17 If a condition operand evaluates to `false`, the consequent block is skipped and any subsequent `else if` condition is evaluated.
18 If all `if` and `else if` conditions evaluate to `false` then any `else` block is executed.
19 An if expression evaluates to the same value as the executed block, or `()` if no block is evaluated.
20 An `if` expression must have the same type in all situations.
21
22 ```rust
23 # let x = 3;
24 if 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
32 let y = if 12 * 15 > 150 {
33 "Bigger"
34 } else {
35 "Smaller"
36 };
37 assert_eq!(y, "Bigger");
38 ```
39
40 ## `if let` expressions
41
42 > **<sup>Syntax</sup>**\
43 > _IfLetExpression_ :\
44 > &nbsp;&nbsp; `if` `let` [_Pattern_] `=` [_Scrutinee_]<sub>_except lazy boolean operator expression_</sub>
45 > [_BlockExpression_]\
46 > &nbsp;&nbsp; (`else` (
47 > [_BlockExpression_]
48 > | _IfExpression_
49 > | _IfLetExpression_ ) )<sup>\?</sup>
50
51 An `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.
52 If the value of the scrutinee matches the pattern, the corresponding block will execute.
53 Otherwise, flow proceeds to the following `else` block if it exists.
54 Like `if` expressions, `if let` expressions have a value determined by the block that is evaluated.
55
56 ```rust
57 let dish = ("Ham", "Eggs");
58
59 // this body will be skipped because the pattern is refuted
60 if 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
68 if let ("Ham", b) = dish {
69 println!("Ham is served with {}", b);
70 }
71
72 if let _ = 5 {
73 println!("Irrefutable patterns are always true");
74 }
75 ```
76
77 `if` and `if let` expressions can be intermixed:
78
79 ```rust
80 let x = Some(3);
81 let 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 };
90 assert_eq!(a, 3);
91 ```
92
93 An `if let` expression is equivalent to a [`match` expression] as follows:
94
95 <!-- ignore: expansion example -->
96 ```rust,ignore
97 if let PATS = EXPR {
98 /* body */
99 } else {
100 /*else */
101 }
102 ```
103
104 is equivalent to
105
106 <!-- ignore: expansion example -->
107 ```rust,ignore
108 match EXPR {
109 PATS => { /* body */ },
110 _ => { /* else */ }, // () if there is no else
111 }
112 ```
113
114 Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in `match` expressions:
115
116 ```rust
117 enum E {
118 X(u8),
119 Y(u8),
120 Z(u8),
121 }
122 let v = E::Y(12);
123 if let E::X(n) | E::Y(n) = v {
124 assert_eq!(n, 12);
125 }
126 ```
127
128 The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_].
129 Use 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_]).
130 When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below:
131
132 <!-- ignore: psuedo code -->
133 ```rust,ignore
134 // Before...
135 if let PAT = EXPR && EXPR { .. }
136
137 // After...
138 if let PAT = ( EXPR && EXPR ) { .. }
139
140 // Before...
141 if let PAT = EXPR || EXPR { .. }
142
143 // After...
144 if let PAT = ( EXPR || EXPR ) { .. }
145 ```
146
147 [_BlockExpression_]: block-expr.md
148 [_Expression_]: ../expressions.md
149 [_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators
150 [_Pattern_]: ../patterns.md
151 [_Scrutinee_]: match-expr.md
152 [_eRFCIfLetChain_]: https://github.com/rust-lang/rfcs/blob/master/text/2497-if-let-chains.md#rollout-plan-and-transitioning-to-rust-2018
153 [`match` expression]: match-expr.md
154 [boolean type]: ../types/boolean.md
155 [scrutinee]: ../glossary.md#scrutinee