Skip to content

Document interaction of | patterns and pattern guards #378

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions src/expressions/match-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
> _MatchArmGuard_ :\
>    `if` [_Expression_]

A `match` expression branches on a *pattern*. The exact form of matching that
occurs depends on the pattern. Patterns consist of some combination of
A *`match` expression* branches on a pattern. The exact form of matching that
occurs depends on the pattern. *Patterns* consist of some combination of
literals, destructured arrays or enum constructors, structs and tuples,
variable binding specifications, wildcards (`..`), and placeholders (`_`). A
`match` expression has a *head expression*, which is the value to compare to
Expand Down Expand Up @@ -99,11 +99,12 @@ symbols, as appropriate. For example, these two matches on `x: &i32` are
equivalent:

```rust
# let x = &3;
let y = match *x { 0 => "zero", _ => "some" };
let z = match x { &0 => "zero", _ => "some" };
let int_reference = &3;

assert_eq!(y, z);
let a = match *int_reference { 0 => "zero", _ => "some" };
let b = match int_reference { &0 => "zero", _ => "some" };

assert_eq!(a, b);
```

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

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

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

When the pattern matches successfully, the pattern guard expression is executed.
If the expression is truthy, the pattern is successfully matched against.
Otherwise, the next pattern, including other matches with the `|` operator in
the same arm, is tested.

```rust
# let maybe_digit = Some(0);
# fn process_digit(i: i32) { }
Expand All @@ -175,6 +181,21 @@ let message = match maybe_digit {
};
```

> Note: Multiple matches using the `|` operator can cause the pattern guard and
> and side effects it has to execute multiple times. For example:
>
> ```rust
> use std::cell::Cell;
> fn main() {
> let i : Cell<i32> = Cell::new(0);
> match 1 {
> 1 | _ if { i.set(i.get() + 1); false } => {}
> _ => {}
> }
> assert_eq!(i.get(), 2);
> }
> ```

## Attributes on match arms

Outer attributes are allowed on match arms. The only attributes that have
Expand All @@ -190,3 +211,4 @@ meaning on match arms are [`cfg`], `cold`, and the [lint check attributes].
[_OuterAttribute_]: attributes.html
[`cfg`]: attributes.html#conditional-compilation
[lint check attributes]: attributes.html#lint-check-attributes
[range]: expressions/range-expr.html