1. 1. Introduction
  2. 2. Getting Started
  3. 3. Tutorial: Guessing Game
  4. 4. Syntax and Semantics
    1. 4.1. Variable Bindings
    2. 4.2. Functions
    3. 4.3. Primitive Types
    4. 4.4. Comments
    5. 4.5. if
    6. 4.6. Loops
    7. 4.7. Vectors
    8. 4.8. Ownership
    9. 4.9. References and Borrowing
    10. 4.10. Lifetimes
    11. 4.11. Mutability
    12. 4.12. Structs
    13. 4.13. Enums
    14. 4.14. Match
    15. 4.15. Patterns
    16. 4.16. Method Syntax
    17. 4.17. Strings
    18. 4.18. Generics
    19. 4.19. Traits
    20. 4.20. Drop
    21. 4.21. if let
    22. 4.22. Trait Objects
    23. 4.23. Closures
    24. 4.24. Universal Function Call Syntax
    25. 4.25. Crates and Modules
    26. 4.26. `const` and `static`
    27. 4.27. Attributes
    28. 4.28. `type` aliases
    29. 4.29. Casting between types
    30. 4.30. Associated Types
    31. 4.31. Unsized Types
    32. 4.32. Operators and Overloading
    33. 4.33. Deref coercions
    34. 4.34. Macros
    35. 4.35. Raw Pointers
    36. 4.36. `unsafe`
  5. 5. Effective Rust
    1. 5.1. The Stack and the Heap
    2. 5.2. Testing
    3. 5.3. Conditional Compilation
    4. 5.4. Documentation
    5. 5.5. Iterators
    6. 5.6. Concurrency
    7. 5.7. Error Handling
    8. 5.8. Choosing your Guarantees
    9. 5.9. FFI
    10. 5.10. Borrow and AsRef
    11. 5.11. Release Channels
    12. 5.12. Using Rust without the standard library
  6. 6. Nightly Rust
    1. 6.1. Compiler Plugins
    2. 6.2. Inline Assembly
    3. 6.3. No stdlib
    4. 6.4. Intrinsics
    5. 6.5. Lang items
    6. 6.6. Advanced linking
    7. 6.7. Benchmark Tests
    8. 6.8. Box Syntax and Patterns
    9. 6.9. Slice Patterns
    10. 6.10. Associated Constants
    11. 6.11. Custom Allocators
  7. 7. Glossary
  8. 8. Syntax Index
  9. 9. Bibliography

Patterns

Patterns are quite common in Rust. We use them in variable bindings, match expressions, and other places, too. Let’s go on a whirlwind tour of all of the things patterns can do!

A quick refresher: you can match against literals directly, and _ acts as an ‘any’ case:

let x = 1;

match x {
    1 => println!("one"),
    2 => println!("two"),
    3 => println!("three"),
    _ => println!("anything"),
}Run

This prints one.

There’s one pitfall with patterns: like anything that introduces a new binding, they introduce shadowing. For example:

let x = 1;
let c = 'c';

match c {
    x => println!("x: {} c: {}", x, c),
}

println!("x: {}", x)Run

This prints:

x: c c: c
x: 1

In other words, x => matches the pattern and introduces a new binding named x. This new binding is in scope for the match arm and takes on the value of c. Notice that the value of x outside the scope of the match has no bearing on the value of x within it. Because we already have a binding named x, this new x shadows it.

Multiple patterns

You can match multiple patterns with |:

let x = 1;

match x {
    1 | 2 => println!("one or two"),
    3 => println!("three"),
    _ => println!("anything"),
}Run

This prints one or two.

Destructuring

If you have a compound data type, like a struct, you can destructure it inside of a pattern:

struct Point {
    x: i32,
    y: i32,
}

let origin = Point { x: 0, y: 0 };

match origin {
    Point { x, y } => println!("({},{})", x, y),
}Run

We can use : to give a value a different name.

struct Point {
    x: i32,
    y: i32,
}

let origin = Point { x: 0, y: 0 };

match origin {
    Point { x: x1, y: y1 } => println!("({},{})", x1, y1),
}Run

If we only care about some of the values, we don’t have to give them all names:

struct Point {
    x: i32,
    y: i32,
}

let point = Point { x: 2, y: 3 };

match point {
    Point { x, .. } => println!("x is {}", x),
}Run

This prints x is 2.

You can do this kind of match on any member, not only the first:

struct Point {
    x: i32,
    y: i32,
}

let point = Point { x: 2, y: 3 };

match point {
    Point { y, .. } => println!("y is {}", y),
}Run

This prints y is 3.

This ‘destructuring’ behavior works on any compound data type, like tuples or enums.

Ignoring bindings

You can use _ in a pattern to disregard the type and value. For example, here’s a match against a Result<T, E>:

match some_value {
    Ok(value) => println!("got a value: {}", value),
    Err(_) => println!("an error occurred"),
}Run

In the first arm, we bind the value inside the Ok variant to value. But in the Err arm, we use _ to disregard the specific error, and print a general error message.

_ is valid in any pattern that creates a binding. This can be useful to ignore parts of a larger structure:

fn coordinate() -> (i32, i32, i32) {
    // generate and return some sort of triple tuple
}

let (x, _, z) = coordinate();Run

Here, we bind the first and last element of the tuple to x and z, but ignore the middle element.

It’s worth noting that using _ never binds the value in the first place, which means that the value does not move:

let tuple: (u32, String) = (5, String::from("five"));

// Here, tuple is moved, because the String moved:
let (x, _s) = tuple;

// The next line would give "error: use of partially moved value: `tuple`"
// println!("Tuple is: {:?}", tuple);

// However,

let tuple = (5, String::from("five"));

// Here, tuple is _not_ moved, as the String was never moved, and u32 is Copy:
let (x, _) = tuple;

// That means this works:
println!("Tuple is: {:?}", tuple);Run

This also means that any temporary variables will be dropped at the end of the statement:

// Here, the String created will be dropped immediately, as it’s not bound:

let _ = String::from("  hello  ").trim();Run

You can also use .. in a pattern to disregard multiple values:

enum OptionalTuple {
    Value(i32, i32, i32),
    Missing,
}

let x = OptionalTuple::Value(5, -2, 3);

match x {
    OptionalTuple::Value(..) => println!("Got a tuple!"),
    OptionalTuple::Missing => println!("No such luck."),
}Run

This prints Got a tuple!.

ref and ref mut

If you want to get a reference, use the ref keyword:

let x = 5;

match x {
    ref r => println!("Got a reference to {}", r),
}Run

This prints Got a reference to 5.

Here, the r inside the match has the type &i32. In other words, the ref keyword creates a reference, for use in the pattern. If you need a mutable reference, ref mut will work in the same way:

let mut x = 5;

match x {
    ref mut mr => println!("Got a mutable reference to {}", mr),
}Run

Ranges

You can match a range of values with ...:

let x = 1;

match x {
    1 ... 5 => println!("one through five"),
    _ => println!("anything"),
}Run

This prints one through five.

Ranges are mostly used with integers and chars:

let x = '💅';

match x {
    'a' ... 'j' => println!("early letter"),
    'k' ... 'z' => println!("late letter"),
    _ => println!("something else"),
}Run

This prints something else.

Bindings

You can bind values to names with @:

let x = 1;

match x {
    e @ 1 ... 5 => println!("got a range element {}", e),
    _ => println!("anything"),
}Run

This prints got a range element 1. This is useful when you want to do a complicated match of part of a data structure:

#[derive(Debug)]
struct Person {
    name: Option<String>,
}

let name = "Steve".to_string();
let x: Option<Person> = Some(Person { name: Some(name) });
match x {
    Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
    _ => {}
}Run

This prints Some("Steve"): we’ve bound the inner name to a.

If you use @ with |, you need to make sure the name is bound in each part of the pattern:

let x = 5;

match x {
    e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
    _ => println!("anything"),
}Run

Guards

You can introduce ‘match guards’ with if:

enum OptionalInt {
    Value(i32),
    Missing,
}

let x = OptionalInt::Value(5);

match x {
    OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
    OptionalInt::Value(..) => println!("Got an int!"),
    OptionalInt::Missing => println!("No such luck."),
}Run

This prints Got an int!.

If you’re using if with multiple patterns, the if applies to both sides:

let x = 4;
let y = false;

match x {
    4 | 5 if y => println!("yes"),
    _ => println!("no"),
}Run

This prints no, because the if applies to the whole of 4 | 5, and not to only the 5. In other words, the precedence of if behaves like this:

(4 | 5) if y => ...

not this:

4 | (5 if y) => ...

Mix and Match

Whew! That’s a lot of different ways to match things, and they can all be mixed and matched, depending on what you’re doing:

match x {
    Foo { x: Some(ref name), y: None } => ...
}Run

Patterns are very powerful. Make good use of them.