Pattern matching

Pattern matching has two purposes in Rust: To check if a value has certain characteristics, and to bind parts of the value to variables.

Example
Patterns are used in many places. For example, they appear on the left side of match arms.

When this example is run, the match arms are matched against the value from top to bottom, and the first arm that matches the value is executed.

Pattern matching in a  expression must always be exhaustive. If the third or last match arm was removed, this example would no longer be accepted by the compiler, because every possible value has to be covered by at least one pattern.

Bindings
When pattern matching, parts of the value can be bound to new variables. These can be made mutable by prepending the  keyword:

In this example, if the first arm matches the value, the whole value is bound to the variable. In the second arm, only the field  is bound to.

Note that  is a different binding in each match arm. They have different types, and only the binding in the second match arm is mutable.

Refutability
Patterns can either be irrefutable, meaning that matching the pattern can never fail; otherwise they are refutable. For example, the wildcard pattern and variable bindings are irrefutable, as matching them will always succeed.

Irrefutable patterns are used in  bindings and in function and closure parameters:

In this example,  and   are patterns. is an,   is a  ,   is a.

The process of taking a value apart with pattern matching and binding its components to new variables is called destructuring.

Patterns
There are many ways how values can be matched:


 * Wildcard : Matches any value and ignores it
 * Binding (e.g. ): Matches any value and binds it to a new variable
 * Binding with additional pattern (e.g. ): Matches a value against the pattern after the  . If it succeeds, the whole value is bound to the variable.
 * Currently, the pattern after  can't introduce new bindings. This restriction will be lifted when the   nightly-only feature is stabilized.
 * Literal (e.g.,  ,  ,  ): Matches exactly that literal
 * Range (e.g.,  ): Matches any value in the given range. This looks identical to but is not that same as the range operator.
 * Ranges with  are exclusive — they don't include the upper bound
 * Ranges with  are inclusive. It's also possible to write , but this syntax is deprecated and produces a warning.
 * Unlike in expressions, half-open and unbounded ranges are not allowed in patterns.
 * Constant (e.g. ): Matches a constant.
 * Reference : Matches the dereferenced value
 * Tuple (e.g. ): Destructures a tuple of values
 * May contain two dots to ignore an arbitrary number of components
 * Array/slice (e.g. )
 * May contain two dots to ignore an arbitrary number of elements. These can be bound as an array/slice to a new variable with
 * Struct (e.g.,  )
 * May contain two dots to ignore an arbitrary number of struct fields
 * If a field is bound to a variable of the same name, the pattern can be omitted. For example,  is equivalent to
 * A tuple struct can be pattern-matched with the regular struct syntax, e.g.
 * Enum variant (e.g. )
 * Enum variants are always refutable, except if the enum contains at most one variant and doesn't have the  attribute
 * To the enum variant fields apply the same pattern-matching rules as to struct fields
 * ref (e.g. ): This syntax is only required in specific scenarios thanks to match ergonomics. A pattern after   only borrows the matched value, instead of taking ownership.
 * Currently, by-move and by- bindings can't be combined in the same pattern. This restriction will be lifted when the   nightly-only feature is stabilized.
 * box (e.g. ): This is a nightly feature to destructure a . It's discouraged to use this feature, since it might be removed in the future.

Match ergonomics
Match ergonomics make it easier to match on borrowed values. Imagine you are writing a function to unwrap a struct from a borrowed, which doesn't implement the trait:

Without match ergonomics, we have to use  to match on the reference, and then use the   keyword to bind the content by reference:

However, with match ergonomics, this isn't necessary, because  is treated the same as   or   in patterns; the reference can be moved inside structs or enums:

This also works for tuples, arrays, slices and unions.

block
Full article: Match

With the keyword, a value is pattern matched against several match arms. Each match arm consists of at least one pattern and an optional  guard. Patterns in a  block must be exhaustive.

and
These blocks are syntactic sugar for the often more verbose  block. For example:

Like  blocks,   and   blocks can have multiple patterns separated with vertical bars. However, they can't have an  guard.

Some people find the naming  and   confusing. The rationale is that both  and   accept a pattern. However, the pattern must be irrefutable for, but can be refutable for.

bindings
bindings are patterns. This is why it's possible to destructure values on assignment:

loops
loops accept a pattern to bind the iterated-over values, for example:

Function and closure parameters
Function and closure parameters are patterns, for example:

Macros
Macros using  can accept patterns with a   parameter, for example:

In fact, a similar macro,, is part of the standard library.

Future extensions
There are several upcoming features that will make pattern matching simpler and more ergonomic. Some of them were discussed in an Inside-Rust blop post.

Nested OR-patterns
blocks support several patterns separated with vertical bars. However, they can't be nested, for example,  is illegal as a pattern.

Patterns like this will be allowed when the experimental  feature is stabilized. This will also allow irrefutable OR-patterns in  bindings and function/closure parameters, for example:

Bindings after
As mentioned above, patterns after a  can't introduce new bindings. For example,  is illegal.

This restriction will be lifted when the experimental  feature is stabilized. Note that the matched type must implement the trait:

Combining by-move and by- bindings
As mentioned above, by-move and by- bindings can't be combined in the same pattern. For example,  is illegal.

However, this will be allowed when the experimental  feature is stabilized, for example: