Skip to content

Commit 249bc2f

Browse files
committed
Document interaction of | patterns and pattern guards
Fixes rust-lang#364
1 parent 219e261 commit 249bc2f

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

src/expressions/match-expr.md

+30-8
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
> _MatchArmGuard_ :\
2424
>    `if` [_Expression_]
2525
26-
A `match` expression branches on a *pattern*. The exact form of matching that
27-
occurs depends on the pattern. Patterns consist of some combination of
26+
A *`match` expression* branches on a pattern. The exact form of matching that
27+
occurs depends on the pattern. *Patterns* consist of some combination of
2828
literals, destructured arrays or enum constructors, structs and tuples,
2929
variable binding specifications, wildcards (`..`), and placeholders (`_`). A
3030
`match` expression has a *head expression*, which is the value to compare to
@@ -99,11 +99,12 @@ symbols, as appropriate. For example, these two matches on `x: &i32` are
9999
equivalent:
100100

101101
```rust
102-
# let x = &3;
103-
let y = match *x { 0 => "zero", _ => "some" };
104-
let z = match x { &0 => "zero", _ => "some" };
102+
let int_reference = &3;
105103

106-
assert_eq!(y, z);
104+
let a = match *int_reference { 0 => "zero", _ => "some" };
105+
let b = match int_reference { &0 => "zero", _ => "some" };
106+
107+
assert_eq!(a, b);
107108
```
108109

109110
Subpatterns can also be bound to variables by the use of the syntax `variable @
@@ -132,7 +133,7 @@ let message = match x {
132133
assert_eq!(message, "a few");
133134
```
134135

135-
Other forms of [range] \(`..` for an exclusive range, or any range with one or
136+
Other forms of [range] \(e.g `..` for an exclusive range, or any range with one or
136137
both endpoints left unspecified) are not supported in matches. The
137138
syntax `...` is also accepted for inclusive ranges in patterns only, for
138139
backwards compatibility.
@@ -159,11 +160,16 @@ match v[..] {
159160
}
160161
```
161162

162-
Finally, match patterns can accept *pattern guards* to further refine the
163+
Finally, match arms can accept *pattern guards* to further refine the
163164
criteria for matching a case. Pattern guards appear after the pattern and
164165
consist of a bool-typed expression following the `if` keyword. A pattern guard
165166
may refer to the variables bound within the pattern they follow.
166167

168+
When the pattern matches successfully, the pattern guard expression is executed.
169+
If the expression is truthy, the pattern is successfully matched against.
170+
Otherwise, the next pattern, including other matches with the `|` operator in
171+
the same arm, is tested.
172+
167173
```rust
168174
# let maybe_digit = Some(0);
169175
# fn process_digit(i: i32) { }
@@ -175,6 +181,21 @@ let message = match maybe_digit {
175181
};
176182
```
177183

184+
> Note: Multiple matches using the `|` operator can cause the pattern guard and
185+
> and side effects it has to execute multiple times. For example:
186+
>
187+
> ```rust
188+
> use std::cell::Cell;
189+
> fn main() {
190+
> let i : Cell<i32> = Cell::new(0);
191+
> match 1 {
192+
> 1 | _ if { i.set(i.get() + 1); false } => {}
193+
> _ => {}
194+
> }
195+
> assert_eq!(i.get(), 2);
196+
> }
197+
> ```
198+
178199
## Attributes on match arms
179200
180201
Outer attributes are allowed on match arms. The only attributes that have
@@ -190,3 +211,4 @@ meaning on match arms are [`cfg`], `cold`, and the [lint check attributes].
190211
[_OuterAttribute_]: attributes.html
191212
[`cfg`]: attributes.html#conditional-compilation
192213
[lint check attributes]: attributes.html#lint-check-attributes
214+
[range]: expressions/range-expr.html

0 commit comments

Comments
 (0)