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.
 * Since Rust 1.56, the pattern after the can also contain bindings, if the type implements.
 * Literal (e.g., , , ): Matches exactly that literal
 * Range (e.g., ): Matches any value in the given range. Not all kinds of ranges are allowed in patterns:
 * Currently, only inclusive ranges are allowed
 * Half-open ranges such as are expected to reach stable in Rust 1.56.
 * is allowed in patterns, but has a different meaning than in expressions: It means that zero or more elements are omitted.
 * 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, and  can be written as.
 * 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
 * Or-patterns (e.g. ): Matches any of the patterns separated with a vertical bar.
 * Or-patterns weren't available before Rust 1.53, but arms could still have multiple patterns separated with.
 * An or-pattern must be wrapped in parentheses (e.g. ) if:
 * it is not in a tuple, array, slice, struct or enum variant pattern, unless the pattern is in a arm
 * it is behind a reference, e.g.
 * 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.

Binding modes
There are several ways how a value can be bound to a variable:


 * is the default, it creates an immutable binding.
 * creates a mutable binding.
 * creates a shared (immutable) reference to the matched value.
 * creates an exclusive (mutable) reference to the matched value.

For example:

The and  binding modes are rarely needed because of match ergonomics.

Match ergonomics
Match ergonomics (also called default binding modes) make it easier to match on borrowed values by automatically adding, , and  in the pattern where necessary. 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.

Many people find the naming and  confusing. The rationale behind this syntax 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.

Destructuring assignment
The left-hand side of assignments (e.g. ) is an expression. More precisely, it is a place expression, because it must refer to a memory location.

Destructuring assignment will make the left-hand side of assignments look more like patterns, because it will allow to destructure a value while assigning it:

is an expression, even though it looks a lot like a pattern: It contains a wildcard, which is usually not allowed in expressions, and the full range is treated as omission of the remaining elements. On the other hand, it contains a field access, which is not allowed in patterns. This is unfortunate because it blurs the distinction between patterns and expressions. However, destructuring assignment is a very useful feature, so it is considered to be worth the additional complexity.