You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Here, `guard_expr` is evaluated and matched against `subpattern`. If the `if let` expression in the guard matches successfully, the arm's body is executed. Otherwise, pattern matching continues to the next arm.
175
+
176
+
r[expr.match.if.let.guard.behavior]
177
+
When the pattern matches successfully, the `if let` expression in the guard is evaluated:
178
+
* The guard proceeds if the inner pattern (`subpattern`) matches the result of `guard_expr`.
179
+
* Otherwise, the next arm is tested.
180
+
181
+
```rust,ignore
182
+
let value = Some(10);
183
+
184
+
let msg = match value {
185
+
Some(x) if let Some(y) = Some(x - 1) => format!("Matched inner value: {}", y),
186
+
_ => "No match".to_string(),
187
+
};
188
+
```
189
+
190
+
r[expr.match.if.let.guard.scope]
191
+
* The `if let` guard may refer to variables bound by the outer match pattern.
192
+
* New variables bound inside the `if let` guard (e.g., `y` in the example above) are available within the body of the match arm where the guard evaluates to `true`, but are not accessible in other arms or outside the match expression.
193
+
194
+
```rust,ignore
195
+
let opt = Some(42);
196
+
197
+
match opt {
198
+
Some(x) if let Some(y) = Some(x + 1) => {
199
+
// Both `x` and `y` are available in this arm,
200
+
// since the pattern matched and the guard evaluated to true.
201
+
println!("x = {}, y = {}", x, y);
202
+
}
203
+
_ => {
204
+
// `y` is not available here --- it was only bound inside the guard above.
205
+
// Uncommenting the line below will cause a compile-time error:
206
+
// println!("{}", y); // error: cannot find value `y` in this scope
207
+
}
208
+
}
209
+
210
+
// Outside the match expression, neither `x` nor `y` are in scope.
211
+
```
212
+
213
+
* The outer pattern variables (`x`) follow the same borrowing behavior as in standard match guards (see below).
214
+
215
+
r[expr.match.if.let.guard.borrowing]
216
+
Variables bound by the outer pattern follow the same borrowing rules as standard match guards:
217
+
* A shared reference is taken to pattern variables before guard evaluation
218
+
* Values are moved or copied only when the guard succeeds
219
+
* Moving from outer pattern variables within the guard is restricted
220
+
221
+
```rust,ignore
222
+
fn take<T>(value: T) -> Option<T> { Some(value) }
223
+
224
+
let val = Some(vec![1, 2, 3]);
225
+
match val {
226
+
Some(v) if let Some(_) = take(v) => "moved", // ERROR: cannot move `v`
227
+
Some(v) if let Some(_) = take(v.clone()) => "cloned", // OK
228
+
_ => "none",
229
+
}
230
+
```
231
+
> [!NOTE]
232
+
> Multiple matches using the `|` operator can cause the pattern guard and the side effects it has to execute multiple times. For example:
233
+
> ```rust,ignore
234
+
> use std::cell::Cell;
235
+
>
236
+
> let i: Cell<i32> = Cell::new(0);
237
+
> match 1 {
238
+
> 1 | _ if let Some(_) = { i.set(i.get() + 1); Some(1) } => {}
239
+
> _ => {}
240
+
> }
241
+
> assert_eq!(i.get(), 2); // Guard is executed twice
0 commit comments