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.
 * 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.
 * 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
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. Individual patterns are separated with a vertical bar. Example:

Match arms with multiple patterns must have the same bindings with the same types in each pattern. The  guard, if present, can access these bindings:

Rust processes match arms in consecutive order from top to bottom. It executes the first match arm where at least one pattern matches and the  guard, if present, returns. It always executes at most one match arm.

blocks must be exhaustive: Every possible value of the matched type must be covered. For example, the following doesn't compile: The reason why  blocks must be exhaustive, is that they are expressions and can return a value:

Usually, exactly one  arm in a   expression is executed, but there are two exceptions:


 * 1) When matching on an enum with no variants or on the never type, there are no match arms, and the code is never executed:


 * 1) When an   guard panics or diverges, no match arm is executed: