The Rust Programming Language › Using Trait Objects to Abstract over Shared Behavior

In Chapter 8, we mentioned that one limitation of vectors is that they can
store elements of only one type. We created a workaround in Listing 8-9 where
we defined a `SpreadsheetCell` enum that had variants to hold integers, floats,
and text. This meant we could store different types of data in each cell and
still have a vector that represented a row of cells. This is a perfectly good
solution when our interchangeable items are a fixed set of types that we know
when our code is compiled.
However, sometimes we want our library user to be able to extend the set of
types that are valid in a particular situation. To show how we might achieve
this, we’ll create an example graphical user interface (GUI) tool that iterates
through a list of items, calling a `draw` method on each one to draw it to the
screen—a common technique for GUI tools. We’ll create a library crate called
`gui` that contains the structure of a GUI library. This crate might include
some types for people to use, such as `Button` or `TextField`. In addition,
`gui` users will want to create their own types that can be drawn: For
instance, one programmer might add an `Image`, and another might add a
`SelectBox`.
At the time of writing the library, we can’t know and define all the types
other programmers might want to create. But we do know that `gui` needs to keep
track of many values of different types, and it needs to call a `draw` method
on each of these differently typed values. It doesn’t need to know exactly what
will happen when we call the `draw` method, just that the value will have that
method available for us to call.


The Rust Programming Language › Using Trait Objects to Abstract over Shared Behavior

To do this in a language with inheritance, we might define a class named
`Component` that has a method named `draw` on it. The other classes, such as
`Button`, `Image`, and `SelectBox`, would inherit from `Component` and thus
inherit the `draw` method. They could each override the `draw` method to define
their custom behavior, but the framework could treat all of the types as if
they were `Component` instances and call `draw` on them. But because Rust
doesn’t have inheritance, we need another way to structure the `gui` library to
allow users to create new types compatible with the library.


The Rust Programming Language › Using Trait Objects to Abstract over Shared Behavior › Defining a Trait for Common Behavior

To implement the behavior that we want `gui` to have, we’ll define a trait
named `Draw` that will have one method named `draw`. Then, we can define a
vector that takes a trait object. A _trait object_ points to both an instance
of a type implementing our specified trait and a table used to look up trait
methods on that type at runtime. We create a trait object by specifying some
sort of pointer, such as a reference or a `Box<T>` smart pointer, then the
`dyn` keyword, and then specifying the relevant trait. (We’ll talk about the
reason trait objects must use a pointer in “Dynamically Sized Types and the
`Sized` Trait” in Chapter 20.) We can use
trait objects in place of a generic or concrete type. Wherever we use a trait
object, Rust’s type system will ensure at compile time that any value used in
that context will implement the trait object’s trait. Consequently, we don’t
need to know all the possible types at compile time.
We’ve mentioned that, in Rust, we refrain from calling structs and enums
“objects” to distinguish them from other languages’ objects. In a struct or
enum, the data in the struct fields and the behavior in `impl` blocks are
separated, whereas in other languages, the data and behavior combined into one
concept is often labeled an object. Trait objects differ from objects in other
languages in that we can’t add data to a trait object. Trait objects aren’t as
generally useful as objects in other languages: Their specific purpose is to
allow abstraction across common behavior.
Listing 18-3 shows how to define a trait named `Draw` with one method named
`draw`.
Listing 18-3: Definition of the `Draw` trait (src/lib.rs)
```rust,noplayground
pub trait Draw {
    fn draw(&self);
}
```


The Rust Programming Language › Using Trait Objects to Abstract over Shared Behavior › Defining a Trait for Common Behavior

This syntax should look familiar from our discussions on how to define traits
in Chapter 10. Next comes some new syntax: Listing 18-4 defines a struct named
`Screen` that holds a vector named `components`. This vector is of type
`Box<dyn Draw>`, which is a trait object; it’s a stand-in for any type inside a
`Box` that implements the `Draw` trait.
Listing 18-4: Definition of the `Screen` struct with a `components` field holding a vector of trait objects that implement the `Draw` trait (src/lib.rs)
```rust,noplayground
pub struct Screen {
    pub components: Vec<Box<dyn Draw>>,
}
```
On the `Screen` struct, we’ll define a method named `run` that will call the
`draw` method on each of its `components`, as shown in Listing 18-5.
Listing 18-5: A `run` method on `Screen` that calls the `draw` method on each component (src/lib.rs)
```rust,noplayground
impl Screen {
    pub fn run(&self) {
        for component in self.components.iter() {
            component.draw();
        }
    }
}
```
This works differently from defining a struct that uses a generic type
parameter with trait bounds. A generic type parameter can be substituted with
only one concrete type at a time, whereas trait objects allow for multiple
concrete types to fill in for the trait object at runtime. For example, we
could have defined the `Screen` struct using a generic type and a trait bound,
as in Listing 18-6.
Listing 18-6: An alternate implementation of the `Screen` struct and its `run` method using generics and trait bounds (src/lib.rs)


The Rust Programming Language › Using Trait Objects to Abstract over Shared Behavior › Defining a Trait for Common Behavior

```rust,noplayground
pub struct Screen<T: Draw> {
    pub components: Vec<T>,
}

impl<T> Screen<T>
where
    T: Draw,
{
    pub fn run(&self) {
        for component in self.components.iter() {
            component.draw();
        }
    }
}
```
This restricts us to a `Screen` instance that has a list of components all of
type `Button` or all of type `TextField`. If you’ll only ever have homogeneous
collections, using generics and trait bounds is preferable because the
definitions will be monomorphized at compile time to use the concrete types.
On the other hand, with the method using trait objects, one `Screen` instance
can hold a `Vec<T>` that contains a `Box<Button>` as well as a
`Box<TextField>`. Let’s look at how this works, and then we’ll talk about the
runtime performance implications.


The Rust Programming Language › Using Trait Objects to Abstract over Shared Behavior › Implementing the Trait

Now we’ll add some types that implement the `Draw` trait. We’ll provide the
`Button` type. Again, actually implementing a GUI library is beyond the scope
of this book, so the `draw` method won’t have any useful implementation in its
body. To imagine what the implementation might look like, a `Button` struct
might have fields for `width`, `height`, and `label`, as shown in Listing 18-7.
Listing 18-7: A `Button` struct that implements the `Draw` trait (src/lib.rs)
```rust,noplayground
pub struct Button {
    pub width: u32,
    pub height: u32,
    pub label: String,
}

impl Draw for Button {
    fn draw(&self) {
        // code to actually draw a button
    }
}
```
The `width`, `height`, and `label` fields on `Button` will differ from the
fields on other components; for example, a `TextField` type might have those
same fields plus a `placeholder` field. Each of the types we want to draw on
the screen will implement the `Draw` trait but will use different code in the
`draw` method to define how to draw that particular type, as `Button` has here
(without the actual GUI code, as mentioned). The `Button` type, for instance,
might have an additional `impl` block containing methods related to what
happens when a user clicks the button. These kinds of methods won’t apply to
types like `TextField`.
If someone using our library decides to implement a `SelectBox` struct that has
`width`, `height`, and `options` fields, they would implement the `Draw` trait
on the `SelectBox` type as well, as shown in Listing 18-8.


The Rust Programming Language › Using Trait Objects to Abstract over Shared Behavior › Implementing the Trait

Listing 18-8: Another crate using `gui` and implementing the `Draw` trait on a `SelectBox` struct (src/main.rs)
```rust,ignore
use gui::Draw;

struct SelectBox {
    width: u32,
    height: u32,
    options: Vec<String>,
}

impl Draw for SelectBox {
    fn draw(&self) {
        // code to actually draw a select box
    }
}
```
Our library’s user can now write their `main` function to create a `Screen`
instance. To the `Screen` instance, they can add a `SelectBox` and a `Button`
by putting each in a `Box<T>` to become a trait object. They can then call the
`run` method on the `Screen` instance, which will call `draw` on each of the
components. Listing 18-9 shows this implementation.
Listing 18-9: Using trait objects to store values of different types that implement the same trait (src/main.rs)
```rust,ignore
use gui::{Button, Screen};

fn main() {
    let screen = Screen {
        components: vec![
            Box::new(SelectBox {
                width: 75,
                height: 10,
                options: vec![
                    String::from("Yes"),
                    String::from("Maybe"),
                    String::from("No"),
                ],
            }),
            Box::new(Button {
                width: 50,
                height: 10,
                label: String::from("OK"),
            }),
        ],
    };

    screen.run();
}
```
When we wrote the library, we didn’t know that someone might add the
`SelectBox` type, but our `Screen` implementation was able to operate on the
new type and draw it because `SelectBox` implements the `Draw` trait, which
means it implements the `draw` method.


The Rust Programming Language › Using Trait Objects to Abstract over Shared Behavior › Implementing the Trait

This concept—of being concerned only with the messages a value responds to
rather than the value’s concrete type—is similar to the concept of _duck
typing_ in dynamically typed languages: If it walks like a duck and quacks like
a duck, then it must be a duck! In the implementation of `run` on `Screen` in
Listing 18-5, `run` doesn’t need to know what the concrete type of each
component is. It doesn’t check whether a component is an instance of a `Button`
or a `SelectBox`, it just calls the `draw` method on the component. By
specifying `Box<dyn Draw>` as the type of the values in the `components`
vector, we’ve defined `Screen` to need values that we can call the `draw`
method on.
The advantage of using trait objects and Rust’s type system to write code
similar to code using duck typing is that we never have to check whether a
value implements a particular method at runtime or worry about getting errors
if a value doesn’t implement a method but we call it anyway. Rust won’t compile
our code if the values don’t implement the traits that the trait objects need.
For example, Listing 18-10 shows what happens if we try to create a `Screen`
with a `String` as a component.
Listing 18-10: Attempting to use a type that doesn’t implement the trait object’s trait (src/main.rs)
```rust,ignore,does_not_compile
use gui::Screen;

fn main() {
    let screen = Screen {
        components: vec![Box::new(String::from("Hi"))],
    };

    screen.run();
}
```
We’ll get this error because `String` doesn’t implement the `Draw` trait:


The Rust Programming Language › Using Trait Objects to Abstract over Shared Behavior › Implementing the Trait

```console
$ cargo run
   Compiling gui v0.1.0 (file:///projects/gui)
error[E0277]: the trait bound `String: Draw` is not satisfied
  --> src/main.rs:5:26
   |
 5 |         components: vec![Box::new(String::from("Hi"))],
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Draw` is not implemented for `String`
   |
help: the trait `Draw` is implemented for `Button`
  --> src/lib.rs:23:1
   |
23 | impl Draw for Button {
   | ^^^^^^^^^^^^^^^^^^^^
   = note: required for the cast from `Box<String>` to `Box<dyn Draw>`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `gui` (bin "gui") due to 1 previous error
```
This error lets us know that either we’re passing something to `Screen` that we
didn’t mean to pass and so should pass a different type, or we should implement
`Draw` on `String` so that `Screen` is able to call `draw` on it.


The Rust Programming Language › Using Trait Objects to Abstract over Shared Behavior › Performing Dynamic Dispatch

Recall in “Performance of Code Using
Generics” in Chapter 10 our
discussion on the monomorphization process performed on generics by the
compiler: The compiler generates nongeneric implementations of functions and
methods for each concrete type that we use in place of a generic type
parameter. The code that results from monomorphization is doing _static
dispatch_, which is when the compiler knows what method you’re calling at
compile time. This is opposed to _dynamic dispatch_, which is when the compiler
can’t tell at compile time which method you’re calling. In dynamic dispatch
cases, the compiler emits code that at runtime will know which method to call.
When we use trait objects, Rust must use dynamic dispatch. The compiler doesn’t
know all the types that might be used with the code that’s using trait objects,
so it doesn’t know which method implemented on which type to call. Instead, at
runtime, Rust uses the pointers inside the trait object to know which method to
call. This lookup incurs a runtime cost that doesn’t occur with static dispatch.
Dynamic dispatch also prevents the compiler from choosing to inline a method’s
code, which in turn prevents some optimizations, and Rust has some rules about
where you can and cannot use dynamic dispatch, called _dyn compatibility_. Those
rules are beyond the scope of this discussion, but you can read more about them
in the reference. However, we did get extra
flexibility in the code that we wrote in Listing 18-5 and were able to support
in Listing 18-9, so it’s a trade-off to consider.


The Rust Programming Language › Implementing an Object-Oriented Design Pattern

The _state pattern_ is an object-oriented design pattern. The crux of the
pattern is that we define a set of states a value can have internally. The
states are represented by a set of _state objects_, and the value’s behavior
changes based on its state. We’re going to work through an example of a blog
post struct that has a field to hold its state, which will be a state object
from the set “draft,” “review,” or “published.”
The state objects share functionality: In Rust, of course, we use structs and
traits rather than objects and inheritance. Each state object is responsible
for its own behavior and for governing when it should change into another
state. The value that holds a state object knows nothing about the different
behavior of the states or when to transition between states.
The advantage of using the state pattern is that, when the business
requirements of the program change, we won’t need to change the code of the
value holding the state or the code that uses the value. We’ll only need to
update the code inside one of the state objects to change its rules or perhaps
add more state objects.
First, we’re going to implement the state pattern in a more traditional
object-oriented way. Then, we’ll use an approach that’s a bit more natural in
Rust. Let’s dig in to incrementally implement a blog post workflow using the
state pattern.
The final functionality will look like this:
1. A blog post starts as an empty draft.
1. When the draft is done, a review of the post is requested.
1. When the post is approved, it gets published.
1. Only published blog posts return content to print so that unapproved posts
   can’t accidentally be published.
Any other changes attempted on a post should have no effect. For example, if we
try to approve a draft blog post before we’ve requested a review, the post
should remain an unpublished draft.


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Attempting Traditional Object-Oriented Style

There are infinite ways to structure code to solve the same problem, each with
different trade-offs. This section’s implementation is more of a traditional
object-oriented style, which is possible to write in Rust, but doesn’t take
advantage of some of Rust’s strengths. Later, we’ll demonstrate a different
solution that still uses the object-oriented design pattern but is structured
in a way that might look less familiar to programmers with object-oriented
experience. We’ll compare the two solutions to experience the trade-offs of
designing Rust code differently than code in other languages.
Listing 18-11 shows this workflow in code form: This is an example usage of the
API we’ll implement in a library crate named `blog`. This won’t compile yet
because we haven’t implemented the `blog` crate.
Listing 18-11: Code that demonstrates the desired behavior we want our `blog` crate to have (src/main.rs)
```rust,ignore,does_not_compile
use blog::Post;

fn main() {
    let mut post = Post::new();

    post.add_text("I ate a salad for lunch today");
    assert_eq!("", post.content());

    post.request_review();
    assert_eq!("", post.content());

    post.approve();
    assert_eq!("I ate a salad for lunch today", post.content());
}
```
We want to allow the user to create a new draft blog post with `Post::new`. We
want to allow text to be added to the blog post. If we try to get the post’s
content immediately, before approval, we shouldn’t get any text because the
post is still a draft. We’ve added `assert_eq!` in the code for demonstration
purposes. An excellent unit test for this would be to assert that a draft blog
post returns an empty string from the `content` method, but we’re not going to
write tests for this example.


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Attempting Traditional Object-Oriented Style › Defining `Post` and Creating a New Instance

Next, we want to enable a request for a review of the post, and we want
`content` to return an empty string while waiting for the review. When the post
receives approval, it should get published, meaning the text of the post will
be returned when `content` is called.
Notice that the only type we’re interacting with from the crate is the `Post`
type. This type will use the state pattern and will hold a value that will be
one of three state objects representing the various states a post can be
in—draft, review, or published. Changing from one state to another will be
managed internally within the `Post` type. The states change in response to the
methods called by our library’s users on the `Post` instance, but they don’t
have to manage the state changes directly. Also, users can’t make a mistake
with the states, such as publishing a post before it’s reviewed.
Let’s get started on the implementation of the library! We know we need a
public `Post` struct that holds some content, so we’ll start with the
definition of the struct and an associated public `new` function to create an
instance of `Post`, as shown in Listing 18-12. We’ll also make a private
`State` trait that will define the behavior that all state objects for a `Post`
must have.
Then, `Post` will hold a trait object of `Box<dyn State>` inside an `Option<T>`
in a private field named `state` to hold the state object. You’ll see why the
`Option<T>` is necessary in a bit.
Listing 18-12: Definition of a `Post` struct and a `new` function that creates a new `Post` instance, a `State` trait, and a `Draft` struct (src/lib.rs)


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Attempting Traditional Object-Oriented Style › Storing the Text of the Post Content

```rust,noplayground
pub struct Post {
    state: Option<Box<dyn State>>,
    content: String,
}

impl Post {
    pub fn new() -> Post {
        Post {
            state: Some(Box::new(Draft {})),
            content: String::new(),
        }
    }
}

trait State {}

struct Draft {}

impl State for Draft {}
```
The `State` trait defines the behavior shared by different post states. The
state objects are `Draft`, `PendingReview`, and `Published`, and they will all
implement the `State` trait. For now, the trait doesn’t have any methods, and
we’ll start by defining just the `Draft` state because that is the state we
want a post to start in.
When we create a new `Post`, we set its `state` field to a `Some` value that
holds a `Box`. This `Box` points to a new instance of the `Draft` struct. This
ensures that whenever we create a new instance of `Post`, it will start out as
a draft. Because the `state` field of `Post` is private, there is no way to
create a `Post` in any other state! In the `Post::new` function, we set the
`content` field to a new, empty `String`.
We saw in Listing 18-11 that we want to be able to call a method named
`add_text` and pass it a `&str` that is then added as the text content of the
blog post. We implement this as a method, rather than exposing the `content`
field as `pub`, so that later we can implement a method that will control how
the `content` field’s data is read. The `add_text` method is pretty
straightforward, so let’s add the implementation in Listing 18-13 to the `impl
Post` block.


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Attempting Traditional Object-Oriented Style › Ensuring That the Content of a Draft Post Is Empty

Listing 18-13: Implementing the `add_text` method to add text to a post’s `content` (src/lib.rs)
```rust,noplayground
impl Post {
    // --snip--
    pub fn add_text(&mut self, text: &str) {
        self.content.push_str(text);
    }
}
```
The `add_text` method takes a mutable reference to `self` because we’re
changing the `Post` instance that we’re calling `add_text` on. We then call
`push_str` on the `String` in `content` and pass the `text` argument to add to
the saved `content`. This behavior doesn’t depend on the state the post is in,
so it’s not part of the state pattern. The `add_text` method doesn’t interact
with the `state` field at all, but it is part of the behavior we want to
support.
Even after we’ve called `add_text` and added some content to our post, we still
want the `content` method to return an empty string slice because the post is
still in the draft state, as shown by the first `assert_eq!` in Listing 18-11.
For now, let’s implement the `content` method with the simplest thing that will
fulfill this requirement: always returning an empty string slice. We’ll change
this later once we implement the ability to change a post’s state so that it
can be published. So far, posts can only be in the draft state, so the post
content should always be empty. Listing 18-14 shows this placeholder
implementation.
Listing 18-14: Adding a placeholder implementation for the `content` method on `Post` that always returns an empty string slice (src/lib.rs)
```rust,noplayground
impl Post {
    // --snip--
    pub fn content(&self) -> &str {
        ""
    }
}
```


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Attempting Traditional Object-Oriented Style › Requesting a Review, Which Changes the Post’s State

With this added `content` method, everything in Listing 18-11 through the first
`assert_eq!` works as intended.
Next, we need to add functionality to request a review of a post, which should
change its state from `Draft` to `PendingReview`. Listing 18-15 shows this code.
Listing 18-15: Implementing `request_review` methods on `Post` and the `State` trait (src/lib.rs)
```rust,noplayground
impl Post {
    // --snip--
    pub fn request_review(&mut self) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.request_review())
        }
    }
}

trait State {
    fn request_review(self: Box<Self>) -> Box<dyn State>;
}

struct Draft {}

impl State for Draft {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        Box::new(PendingReview {})
    }
}

struct PendingReview {}

impl State for PendingReview {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }
}
```
We give `Post` a public method named `request_review` that will take a mutable
reference to `self`. Then, we call an internal `request_review` method on the
current state of `Post`, and this second `request_review` method consumes the
current state and returns a new state.


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Attempting Traditional Object-Oriented Style › Requesting a Review, Which Changes the Post’s State

We add the `request_review` method to the `State` trait; all types that
implement the trait will now need to implement the `request_review` method.
Note that rather than having `self`, `&self`, or `&mut self` as the first
parameter of the method, we have `self: Box<Self>`. This syntax means the
method is only valid when called on a `Box` holding the type. This syntax takes
ownership of `Box<Self>`, invalidating the old state so that the state value of
the `Post` can transform into a new state.
To consume the old state, the `request_review` method needs to take ownership
of the state value. This is where the `Option` in the `state` field of `Post`
comes in: We call the `take` method to take the `Some` value out of the `state`
field and leave a `None` in its place because Rust doesn’t let us have
unpopulated fields in structs. This lets us move the `state` value out of
`Post` rather than borrowing it. Then, we’ll set the post’s `state` value to
the result of this operation.
We need to set `state` to `None` temporarily rather than setting it directly
with code like `self.state = self.state.request_review();` to get ownership of
the `state` value. This ensures that `Post` can’t use the old `state` value
after we’ve transformed it into a new state.
The `request_review` method on `Draft` returns a new, boxed instance of a new
`PendingReview` struct, which represents the state when a post is waiting for a
review. The `PendingReview` struct also implements the `request_review` method
but doesn’t do any transformations. Rather, it returns itself because when we
request a review on a post already in the `PendingReview` state, it should stay
in the `PendingReview` state.


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Attempting Traditional Object-Oriented Style › Adding `approve` to Change `content`'s Behavior

Now we can start seeing the advantages of the state pattern: The
`request_review` method on `Post` is the same no matter its `state` value. Each
state is responsible for its own rules.
We’ll leave the `content` method on `Post` as is, returning an empty string
slice. We can now have a `Post` in the `PendingReview` state as well as in the
`Draft` state, but we want the same behavior in the `PendingReview` state.
Listing 18-11 now works up to the second `assert_eq!` call!
The `approve` method will be similar to the `request_review` method: It will
set `state` to the value that the current state says it should have when that
state is approved, as shown in Listing 18-16.
Listing 18-16: Implementing the `approve` method on `Post` and the `State` trait (src/lib.rs)


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Attempting Traditional Object-Oriented Style › Adding `approve` to Change `content`'s Behavior

```rust,noplayground
impl Post {
    // --snip--
    pub fn approve(&mut self) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.approve())
        }
    }
}

trait State {
    fn request_review(self: Box<Self>) -> Box<dyn State>;
    fn approve(self: Box<Self>) -> Box<dyn State>;
}

struct Draft {}

impl State for Draft {
    // --snip--
    fn approve(self: Box<Self>) -> Box<dyn State> {
        self
    }
}

struct PendingReview {}

impl State for PendingReview {
    // --snip--
    fn approve(self: Box<Self>) -> Box<dyn State> {
        Box::new(Published {})
    }
}

struct Published {}

impl State for Published {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }

    fn approve(self: Box<Self>) -> Box<dyn State> {
        self
    }
}
```
We add the `approve` method to the `State` trait and add a new struct that
implements `State`, the `Published` state.
Similar to the way `request_review` on `PendingReview` works, if we call the
`approve` method on a `Draft`, it will have no effect because `approve` will
return `self`. When we call `approve` on `PendingReview`, it returns a new,
boxed instance of the `Published` struct. The `Published` struct implements the
`State` trait, and for both the `request_review` method and the `approve`
method, it returns itself because the post should stay in the `Published` state
in those cases.


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Attempting Traditional Object-Oriented Style › Adding `approve` to Change `content`'s Behavior

Now we need to update the `content` method on `Post`. We want the value
returned from `content` to depend on the current state of the `Post`, so we’re
going to have the `Post` delegate to a `content` method defined on its `state`,
as shown in Listing 18-17.
Listing 18-17: Updating the `content` method on `Post` to delegate to a `content` method on `State` (src/lib.rs)
```rust,ignore,does_not_compile
impl Post {
    // --snip--
    pub fn content(&self) -> &str {
        self.state.as_ref().unwrap().content(self)
    }
    // --snip--
}
```
Because the goal is to keep all of these rules inside the structs that
implement `State`, we call a `content` method on the value in `state` and pass
the post instance (that is, `self`) as an argument. Then, we return the value
that’s returned from using the `content` method on the `state` value.
We call the `as_ref` method on the `Option` because we want a reference to the
value inside the `Option` rather than ownership of the value. Because `state` is
an `Option<Box<dyn State>>`, when we call `as_ref`, an `Option<&Box<dyn
State>>` is returned. If we didn’t call `as_ref`, we would get an error because
we can’t move `state` out of the borrowed `&self` of the function parameter.


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Attempting Traditional Object-Oriented Style › Adding `approve` to Change `content`'s Behavior

We then call the `unwrap` method, which we know will never panic because we
know the methods on `Post` ensure that `state` will always contain a `Some`
value when those methods are done. This is one of the cases we talked about in
the “When You Have More Information Than the
Compiler” section of Chapter 9 when we
know that a `None` value is never possible, even though the compiler isn’t able
to understand that.
At this point, when we call `content` on the `&Box<dyn State>`, deref coercion
will take effect on the `&` and the `Box` so that the `content` method will
ultimately be called on the type that implements the `State` trait. That means
we need to add `content` to the `State` trait definition, and that is where
we’ll put the logic for what content to return depending on which state we
have, as shown in Listing 18-18.
Listing 18-18: Adding the `content` method to the `State` trait (src/lib.rs)
```rust,noplayground
trait State {
    // --snip--
    fn content<'a>(&self, post: &'a Post) -> &'a str {
        ""
    }
}

// --snip--
struct Published {}

impl State for Published {
    // --snip--
    fn content<'a>(&self, post: &'a Post) -> &'a str {
        &post.content
    }
}
```


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Attempting Traditional Object-Oriented Style › Adding `approve` to Change `content`'s Behavior

We add a default implementation for the `content` method that returns an empty
string slice. That means we don’t need to implement `content` on the `Draft`
and `PendingReview` structs. The `Published` struct will override the `content`
method and return the value in `post.content`. While convenient, having the
`content` method on `State` determine the content of the `Post` is blurring
the lines between the responsibility of `State` and the responsibility of
`Post`.
Note that we need lifetime annotations on this method, as we discussed in
Chapter 10. We’re taking a reference to a `post` as an argument and returning a
reference to part of that `post`, so the lifetime of the returned reference is
related to the lifetime of the `post` argument.
And we’re done—all of Listing 18-11 now works! We’ve implemented the state
pattern with the rules of the blog post workflow. The logic related to the
rules lives in the state objects rather than being scattered throughout `Post`.


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Why Not An Enum? › Evaluating the State Pattern

You may have been wondering why we didn’t use an enum with the different
possible post states as variants. That’s certainly a possible solution; try it
and compare the end results to see which you prefer! One disadvantage of using
an enum is that every place that checks the value of the enum will need a
`match` expression or similar to handle every possible variant. This could get
more repetitive than this trait object solution.
We’ve shown that Rust is capable of implementing the object-oriented state
pattern to encapsulate the different kinds of behavior a post should have in
each state. The methods on `Post` know nothing about the various behaviors.
Because of the way we organized the code, we have to look in only one place to
know the different ways a published post can behave: the implementation of the
`State` trait on the `Published` struct.
If we were to create an alternative implementation that didn’t use the state
pattern, we might instead use `match` expressions in the methods on `Post` or
even in the `main` code that checks the state of the post and changes behavior
in those places. That would mean we would have to look in several places to
understand all the implications of a post being in the published state.
With the state pattern, the `Post` methods and the places we use `Post` don’t
need `match` expressions, and to add a new state, we would only need to add a
new struct and implement the trait methods on that one struct in one location.
The implementation using the state pattern is easy to extend to add more
functionality. To see the simplicity of maintaining code that uses the state
pattern, try a few of these suggestions:


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Why Not An Enum? › Evaluating the State Pattern

- Add a `reject` method that changes the post’s state from `PendingReview` back
  to `Draft`.
- Require two calls to `approve` before the state can be changed to `Published`.
- Allow users to add text content only when a post is in the `Draft` state.
  Hint: have the state object responsible for what might change about the
  content but not responsible for modifying the `Post`.
One downside of the state pattern is that, because the states implement the
transitions between states, some of the states are coupled to each other. If we
add another state between `PendingReview` and `Published`, such as `Scheduled`,
we would have to change the code in `PendingReview` to transition to
`Scheduled` instead. It would be less work if `PendingReview` didn’t need to
change with the addition of a new state, but that would mean switching to
another design pattern.
Another downside is that we’ve duplicated some logic. To eliminate some of the
duplication, we might try to make default implementations for the
`request_review` and `approve` methods on the `State` trait that return `self`.
However, this wouldn’t work: When using `State` as a trait object, the trait
doesn’t know what the concrete `self` will be exactly, so the return type isn’t
known at compile time. (This is one of the dyn compatibility rules mentioned
earlier.)


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Why Not An Enum? › Evaluating the State Pattern

Other duplication includes the similar implementations of the `request_review`
and `approve` methods on `Post`. Both methods use `Option::take` with the
`state` field of `Post`, and if `state` is `Some`, they delegate to the wrapped
value’s implementation of the same method and set the new value of the `state`
field to the result. If we had a lot of methods on `Post` that followed this
pattern, we might consider defining a macro to eliminate the repetition (see
the “Macros” section in Chapter 20).
By implementing the state pattern exactly as it’s defined for object-oriented
languages, we’re not taking as full advantage of Rust’s strengths as we could.
Let’s look at some changes we can make to the `blog` crate that can make
invalid states and transitions into compile-time errors.


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Encoding States and Behavior as Types

We’ll show you how to rethink the state pattern to get a different set of
trade-offs. Rather than encapsulating the states and transitions completely so
that outside code has no knowledge of them, we’ll encode the states into
different types. Consequently, Rust’s type-checking system will prevent
attempts to use draft posts where only published posts are allowed by issuing a
compiler error.
Let’s consider the first part of `main` in Listing 18-11:
Listing (src/main.rs)
```rust,ignore
fn main() {
    let mut post = Post::new();

    post.add_text("I ate a salad for lunch today");
    assert_eq!("", post.content());
}
```
We still enable the creation of new posts in the draft state using `Post::new`
and the ability to add text to the post’s content. But instead of having a
`content` method on a draft post that returns an empty string, we’ll make it so
that draft posts don’t have the `content` method at all. That way, if we try to
get a draft post’s content, we’ll get a compiler error telling us the method
doesn’t exist. As a result, it will be impossible for us to accidentally
display draft post content in production because that code won’t even compile.
Listing 18-19 shows the definition of a `Post` struct and a `DraftPost` struct,
as well as methods on each.
Listing 18-19: A `Post` with a `content` method and a `DraftPost` without a `content` method (src/lib.rs)


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Encoding States and Behavior as Types

```rust,noplayground
pub struct Post {
    content: String,
}

pub struct DraftPost {
    content: String,
}

impl Post {
    pub fn new() -> DraftPost {
        DraftPost {
            content: String::new(),
        }
    }

    pub fn content(&self) -> &str {
        &self.content
    }
}

impl DraftPost {
    pub fn add_text(&mut self, text: &str) {
        self.content.push_str(text);
    }
}
```
Both the `Post` and `DraftPost` structs have a private `content` field that
stores the blog post text. The structs no longer have the `state` field because
we’re moving the encoding of the state to the types of the structs. The `Post`
struct will represent a published post, and it has a `content` method that
returns the `content`.
We still have a `Post::new` function, but instead of returning an instance of
`Post`, it returns an instance of `DraftPost`. Because `content` is private and
there aren’t any functions that return `Post`, it’s not possible to create an
instance of `Post` right now.
The `DraftPost` struct has an `add_text` method, so we can add text to
`content` as before, but note that `DraftPost` does not have a `content` method
defined! So now the program ensures that all posts start as draft posts, and
draft posts don’t have their content available for display. Any attempt to get
around these constraints will result in a compiler error.


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Encoding States and Behavior as Types

So, how do we get a published post? We want to enforce the rule that a draft
post has to be reviewed and approved before it can be published. A post in the
pending review state should still not display any content. Let’s implement
these constraints by adding another struct, `PendingReviewPost`, defining the
`request_review` method on `DraftPost` to return a `PendingReviewPost` and
defining an `approve` method on `PendingReviewPost` to return a `Post`, as
shown in Listing 18-20.
Listing 18-20: A `PendingReviewPost` that gets created by calling `request_review` on `DraftPost` and an `approve` method that turns a `PendingReviewPost` into a published `Post` (src/lib.rs)
```rust,noplayground
impl DraftPost {
    // --snip--
    pub fn request_review(self) -> PendingReviewPost {
        PendingReviewPost {
            content: self.content,
        }
    }
}

pub struct PendingReviewPost {
    content: String,
}

impl PendingReviewPost {
    pub fn approve(self) -> Post {
        Post {
            content: self.content,
        }
    }
}
```


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Encoding States and Behavior as Types

The `request_review` and `approve` methods take ownership of `self`, thus
consuming the `DraftPost` and `PendingReviewPost` instances and transforming
them into a `PendingReviewPost` and a published `Post`, respectively. This way,
we won’t have any lingering `DraftPost` instances after we’ve called
`request_review` on them, and so forth. The `PendingReviewPost` struct doesn’t
have a `content` method defined on it, so attempting to read its content
results in a compiler error, as with `DraftPost`. Because the only way to get a
published `Post` instance that does have a `content` method defined is to call
the `approve` method on a `PendingReviewPost`, and the only way to get a
`PendingReviewPost` is to call the `request_review` method on a `DraftPost`,
we’ve now encoded the blog post workflow into the type system.
But we also have to make some small changes to `main`. The `request_review` and
`approve` methods return new instances rather than modifying the struct they’re
called on, so we need to add more `let post =` shadowing assignments to save
the returned instances. We also can’t have the assertions about the draft and
pending review posts’ contents be empty strings, nor do we need them: We can’t
compile code that tries to use the content of posts in those states any longer.
The updated code in `main` is shown in Listing 18-21.
Listing 18-21: Modifications to `main` to use the new implementation of the blog post workflow (src/main.rs)


The Rust Programming Language › Implementing an Object-Oriented Design Pattern › Encoding States and Behavior as Types

```rust,ignore
use blog::Post;

fn main() {
    let mut post = Post::new();

    post.add_text("I ate a salad for lunch today");

    let post = post.request_review();

    let post = post.approve();

    assert_eq!("I ate a salad for lunch today", post.content());
}
```
The changes we needed to make to `main` to reassign `post` mean that this
implementation doesn’t quite follow the object-oriented state pattern anymore:
The transformations between the states are no longer encapsulated entirely
within the `Post` implementation. However, our gain is that invalid states are
now impossible because of the type system and the type checking that happens at
compile time! This ensures that certain bugs, such as display of the content of
an unpublished post, will be discovered before they make it to production.
Try the tasks suggested at the start of this section on the `blog` crate as it
is after Listing 18-21 to see what you think about the design of this version
of the code. Note that some of the tasks might be completed already in this
design.
We’ve seen that even though Rust is capable of implementing object-oriented
design patterns, other patterns, such as encoding state into the type system,
are also available in Rust. These patterns have different trade-offs. Although
you might be very familiar with object-oriented patterns, rethinking the
problem to take advantage of Rust’s features can provide benefits, such as
preventing some bugs at compile time. Object-oriented patterns won’t always be
the best solution in Rust due to certain features, like ownership, that
object-oriented languages don’t have.


The Rust Programming Language › Summary

Regardless of whether you think Rust is an object-oriented language after
reading this chapter, you now know that you can use trait objects to get some
object-oriented features in Rust. Dynamic dispatch can give your code some
flexibility in exchange for a bit of runtime performance. You can use this
flexibility to implement object-oriented patterns that can help your code’s
maintainability. Rust also has other features, like ownership, that
object-oriented languages don’t have. An object-oriented pattern won’t always
be the best way to take advantage of Rust’s strengths, but it is an available
option.
Next, we’ll look at patterns, which are another of Rust’s features that enable
lots of flexibility. We’ve looked at them briefly throughout the book but
haven’t seen their full capability yet. Let’s go!


The Rust Programming Language › Patterns and Matching

Patterns are a special syntax in Rust for matching against the structure of
types, both complex and simple. Using patterns in conjunction with `match`
expressions and other constructs gives you more control over a program’s
control flow. A pattern consists of some combination of the following:
- Literals
- Destructured arrays, enums, structs, or tuples
- Variables
- Wildcards
- Placeholders
Some example patterns include `x`, `(a, 3)`, and `Some(Color::Red)`. In the
contexts in which patterns are valid, these components describe the shape of
data. Our program then matches values against the patterns to determine whether
it has the correct shape of data to continue running a particular piece of code.
To use a pattern, we compare it to some value. If the pattern matches the
value, we use the value parts in our code. Recall the `match` expressions in
Chapter 6 that used patterns, such as the coin-sorting machine example. If the
value fits the shape of the pattern, we can use the named pieces. If it
doesn’t, the code associated with the pattern won’t run.
This chapter is a reference on all things related to patterns. We’ll cover the
valid places to use patterns, the difference between refutable and irrefutable
patterns, and the different kinds of pattern syntax that you might see. By the
end of the chapter, you’ll know how to use patterns to express many concepts in
a clear way.


The Rust Programming Language › All the Places Patterns Can Be Used

Patterns pop up in a number of places in Rust, and you’ve been using them a lot
without realizing it! This section discusses all the places where patterns are
valid.


The Rust Programming Language › All the Places Patterns Can Be Used › `match` Arms

As discussed in Chapter 6, we use patterns in the arms of `match` expressions.
Formally, `match` expressions are defined as the keyword `match`, a value to
match on, and one or more match arms that consist of a pattern and an
expression to run if the value matches that arm’s pattern, like this:

match VALUE {
    PATTERN => EXPRESSION,
    PATTERN => EXPRESSION,
    PATTERN => EXPRESSION,
}

For example, here’s the `match` expression from Listing 6-5 that matches on an
`Option<i32>` value in the variable `x`:
```rust,ignore
match x {
    None => None,
    Some(i) => Some(i + 1),
}
```
The patterns in this `match` expression are the `None` and `Some(i)` to the
left of each arrow.
One requirement for `match` expressions is that they need to be exhaustive in
the sense that all possibilities for the value in the `match` expression must
be accounted for. One way to ensure that you’ve covered every possibility is to
have a catch-all pattern for the last arm: For example, a variable name
matching any value can never fail and thus covers every remaining case.
The particular pattern `_` will match anything, but it never binds to a
variable, so it’s often used in the last match arm. The `_` pattern can be
useful when you want to ignore any value not specified, for example. We’ll
cover the `_` pattern in more detail in “Ignoring Values in a
Pattern” later in this chapter.

All the Places Patterns Can Be Used
`match` Arms


The Rust Programming Language › All the Places Patterns Can Be Used › `let` Statements

Prior to this chapter, we had only explicitly discussed using patterns with
`match` and `if let`, but in fact, we’ve used patterns in other places as well,
including in `let` statements. For example, consider this straightforward
variable assignment with `let`:
```rust
let x = 5;
```
Every time you’ve used a `let` statement like this you’ve been using patterns,
although you might not have realized it! More formally, a `let` statement looks
like this:

let PATTERN = EXPRESSION;

In statements like `let x = 5;` with a variable name in the PATTERN slot, the
variable name is just a particularly simple form of a pattern. Rust compares
the expression against the pattern and assigns any names it finds. So, in the
`let x = 5;` example, `x` is a pattern that means “bind what matches here to
the variable `x`.” Because the name `x` is the whole pattern, this pattern
effectively means “bind everything to the variable `x`, whatever the value is.”
To see the pattern-matching aspect of `let` more clearly, consider Listing
19-1, which uses a pattern with `let` to destructure a tuple.
Listing 19-1: Using a pattern to destructure a tuple and create three variables at once
```rust
    let (x, y, z) = (1, 2, 3);
```

All the Places Patterns Can Be Used
`let` Statements


The Rust Programming Language › All the Places Patterns Can Be Used › `let` Statements

Here, we match a tuple against a pattern. Rust compares the value `(1, 2, 3)`
to the pattern `(x, y, z)` and sees that the value matches the pattern—that is,
it sees that the number of elements is the same in both—so Rust binds `1` to
`x`, `2` to `y`, and `3` to `z`. You can think of this tuple pattern as nesting
three individual variable patterns inside it.
If the number of elements in the pattern doesn’t match the number of elements
in the tuple, the overall type won’t match and we’ll get a compiler error. For
example, Listing 19-2 shows an attempt to destructure a tuple with three
elements into two variables, which won’t work.
Listing 19-2: Incorrectly constructing a pattern whose variables don’t match the number of elements in the tuple
```rust,ignore,does_not_compile
    let (x, y) = (1, 2, 3);
```
Attempting to compile this code results in this type error:
```console
$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
error[E0308]: mismatched types
 --> src/main.rs:2:9
  |
2 |     let (x, y) = (1, 2, 3);
  |         ^^^^^^   --------- this expression has type `({integer}, {integer}, {integer})`
  |         |
  |         expected a tuple with 3 elements, found one with 2 elements
  |
  = note: expected tuple `({integer}, {integer}, {integer})`
             found tuple `(_, _)`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `patterns` (bin "patterns") due to 1 previous error
```


The Rust Programming Language › All the Places Patterns Can Be Used › `let` Statements

To fix the error, we could ignore one or more of the values in the tuple using
`_` or `..`, as you’ll see in the “Ignoring Values in a
Pattern” section. If the problem
is that we have too many variables in the pattern, the solution is to make the
types match by removing variables so that the number of variables equals the
number of elements in the tuple.


The Rust Programming Language › All the Places Patterns Can Be Used › Conditional `if let` Expressions

In Chapter 6, we discussed how to use `if let` expressions mainly as a shorter
way to write the equivalent of a `match` that only matches one case.
Optionally, `if let` can have a corresponding `else` containing code to run if
the pattern in the `if let` doesn’t match.
Listing 19-3 shows that it’s also possible to mix and match `if let`, `else
if`, and `else if let` expressions. Doing so gives us more flexibility than a
`match` expression in which we can express only one value to compare with the
patterns. Also, Rust doesn’t require that the conditions in a series of `if
let`, `else if`, and `else if let` arms relate to each other.
The code in Listing 19-3 determines what color to make your background based on
a series of checks for several conditions. For this example, we’ve created
variables with hardcoded values that a real program might receive from user
input.
Listing 19-3: Mixing `if let`, `else if`, `else if let`, and `else` (src/main.rs)
```rust
fn main() {
    let favorite_color: Option<&str> = None;
    let is_tuesday = false;
    let age: Result<u8, _> = "34".parse();

    if let Some(color) = favorite_color {
        println!("Using your favorite color, {color}, as the background");
    } else if is_tuesday {
        println!("Tuesday is green day!");
    } else if let Ok(age) = age {
        if age > 30 {
            println!("Using purple as the background color");
        } else {
            println!("Using orange as the background color");
        }
    } else {
        println!("Using blue as the background color");
    }
}
```

All the Places Patterns Can Be Used
Conditional `if let` Expressions


The Rust Programming Language › All the Places Patterns Can Be Used › Conditional `if let` Expressions

If the user specifies a favorite color, that color is used as the background.
If no favorite color is specified and today is Tuesday, the background color is
green. Otherwise, if the user specifies their age as a string and we can parse
it as a number successfully, the color is either purple or orange depending on
the value of the number. If none of these conditions apply, the background
color is blue.
This conditional structure lets us support complex requirements. With the
hardcoded values we have here, this example will print `Using purple as the
background color`.
You can see that `if let` can also introduce new variables that shadow existing
variables in the same way that `match` arms can: The line `if let Ok(age) = age`
introduces a new `age` variable that contains the value inside the `Ok` variant,
shadowing the existing `age` variable. This means we need to place the `if age >
30` condition within that block: We can’t combine these two conditions into `if
let Ok(age) = age && age > 30`. The new `age` we want to compare to 30 isn’t
valid until the new scope starts with the curly bracket.
The downside of using `if let` expressions is that the compiler doesn’t check
for exhaustiveness, whereas with `match` expressions it does. If we omitted the
last `else` block and therefore missed handling some cases, the compiler would
not alert us to the possible logic bug.


The Rust Programming Language › All the Places Patterns Can Be Used › `while let` Conditional Loops

Similar in construction to `if let`, the `while let` conditional loop allows a
`while` loop to run for as long as a pattern continues to match. In Listing
19-4, we show a `while let` loop that waits on messages sent between threads,
but in this case checking a `Result` instead of an `Option`.
Listing 19-4: Using a `while let` loop to print values for as long as `rx.recv()` returns `Ok`
```rust
    let (tx, rx) = std::sync::mpsc::channel();
    std::thread::spawn(move || {
        for val in [1, 2, 3] {
            tx.send(val).unwrap();
        }
    });

    while let Ok(value) = rx.recv() {
        println!("{value}");
    }
```
This example prints `1`, `2`, and then `3`. The `recv` method takes the first
message out of the receiver side of the channel and returns an `Ok(value)`. When
we first saw `recv` back in Chapter 16, we unwrapped the error directly, or
we interacted with it as an iterator using a `for` loop. As Listing 19-4 shows,
though, we can also use `while let`, because the `recv` method returns an `Ok`
each time a message arrives, as long as the sender exists, and then produces an
`Err` once the sender side disconnects.

All the Places Patterns Can Be Used
`while let` Conditional Loops


The Rust Programming Language › All the Places Patterns Can Be Used › `for` Loops

In a `for` loop, the value that directly follows the keyword `for` is a
pattern. For example, in `for x in y`, the `x` is the pattern. Listing 19-5
demonstrates how to use a pattern in a `for` loop to destructure, or break
apart, a tuple as part of the `for` loop.
Listing 19-5: Using a pattern in a `for` loop to destructure a tuple
```rust
    let v = vec!['a', 'b', 'c'];

    for (index, value) in v.iter().enumerate() {
        println!("{value} is at index {index}");
    }
```
The code in Listing 19-5 will print the following:
```console
$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.52s
     Running `target/debug/patterns`
a is at index 0
b is at index 1
c is at index 2
```
We adapt an iterator using the `enumerate` method so that it produces a value
and the index for that value, placed into a tuple. The first value produced is
the tuple `(0, 'a')`. When this value is matched to the pattern `(index,
value)`, index will be `0` and value will be `'a'`, printing the first line of
the output.

All the Places Patterns Can Be Used
`for` Loops


The Rust Programming Language › All the Places Patterns Can Be Used › Function Parameters

Function parameters can also be patterns. The code in Listing 19-6, which
declares a function named `foo` that takes one parameter named `x` of type
`i32`, should by now look familiar.
Listing 19-6: A function signature using patterns in the parameters
```rust
fn foo(x: i32) {
    // code goes here
}
```
The `x` part is a pattern! As we did with `let`, we could match a tuple in a
function’s arguments to the pattern. Listing 19-7 splits the values in a tuple
as we pass it to a function.
Listing 19-7: A function with parameters that destructure a tuple (src/main.rs)
```rust
fn print_coordinates(&(x, y): &(i32, i32)) {
    println!("Current location: ({x}, {y})");
}

fn main() {
    let point = (3, 5);
    print_coordinates(&point);
}
```
This code prints `Current location: (3, 5)`. The values `&(3, 5)` match the
pattern `&(x, y)`, so `x` is the value `3` and `y` is the value `5`.
We can also use patterns in closure parameter lists in the same way as in
function parameter lists because closures are similar to functions, as
discussed in Chapter 13.
At this point, you’ve seen several ways to use patterns, but patterns don’t
work the same in every place we can use them. In some places, the patterns must
be irrefutable; in other circumstances, they can be refutable. We’ll discuss
these two concepts next.

All the Places Patterns Can Be Used
Function Parameters


The Rust Programming Language › Refutability: Whether a Pattern Might Fail to Match

Patterns come in two forms: refutable and irrefutable. Patterns that will match
for any possible value passed are _irrefutable_. An example would be `x` in the
statement `let x = 5;` because `x` matches anything and therefore cannot fail
to match. Patterns that can fail to match for some possible value are
_refutable_. An example would be `Some(x)` in the expression `if let Some(x) =
a_value` because if the value in the `a_value` variable is `None` rather than
`Some`, the `Some(x)` pattern will not match.
Function parameters, `let` statements, and `for` loops can only accept
irrefutable patterns because the program cannot do anything meaningful when
values don’t match. The `if let` and `while let` expressions and the
`let...else` statement accept refutable and irrefutable patterns, but the
compiler warns against irrefutable patterns because, by definition, they’re
intended to handle possible failure: The functionality of a conditional is in
its ability to perform differently depending on success or failure.
In general, you shouldn’t have to worry about the distinction between refutable
and irrefutable patterns; however, you do need to be familiar with the concept
of refutability so that you can respond when you see it in an error message. In
those cases, you’ll need to change either the pattern or the construct you’re
using the pattern with, depending on the intended behavior of the code.
Let’s look at an example of what happens when we try to use a refutable pattern
where Rust requires an irrefutable pattern and vice versa. Listing 19-8 shows a
`let` statement, but for the pattern, we’ve specified `Some(x)`, a refutable
pattern. As you might expect, this code will not compile.
Listing 19-8: Attempting to use a refutable pattern with `let`


The Rust Programming Language › Refutability: Whether a Pattern Might Fail to Match

```rust,ignore,does_not_compile
    let Some(x) = some_option_value;
```
If `some_option_value` were a `None` value, it would fail to match the pattern
`Some(x)`, meaning the pattern is refutable. However, the `let` statement can
only accept an irrefutable pattern because there is nothing valid the code can
do with a `None` value. At compile time, Rust will complain that we’ve tried to
use a refutable pattern where an irrefutable pattern is required:
```console
$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
error[E0005]: refutable pattern in local binding
 --> src/main.rs:3:9
  |
3 |     let Some(x) = some_option_value;
  |         ^^^^^^^ pattern `None` not covered
  |
  = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
  = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
  = note: the matched value is of type `Option<i32>`
help: you might want to use `let...else` to handle the variant that isn't matched
  |
3 |     let Some(x) = some_option_value else { todo!() };
  |                                     ++++++++++++++++

For more information about this error, try `rustc --explain E0005`.
error: could not compile `patterns` (bin "patterns") due to 1 previous error
```
Because we didn’t cover (and couldn’t cover!) every valid value with the
pattern `Some(x)`, Rust rightfully produces a compiler error.


The Rust Programming Language › Refutability: Whether a Pattern Might Fail to Match

If we have a refutable pattern where an irrefutable pattern is needed, we can
fix it by changing the code that uses the pattern: Instead of using `let`, we
can use `let...else`. Then, if the pattern doesn’t match, the code in the curly
brackets will handle the value. Listing 19-9 shows how to fix the code in
Listing 19-8.
Listing 19-9: Using `let...else` and a block with refutable patterns instead of `let`
```rust
    let Some(x) = some_option_value else {
        return;
    };
```
We’ve given the code an out! This code is perfectly valid, although it means we
cannot use an irrefutable pattern without receiving a warning. If we give
`let...else` a pattern that will always match, such as `x`, as shown in Listing
19-10, the compiler will give a warning.
Listing 19-10: Attempting to use an irrefutable pattern with `let...else`
```rust
    let x = 5 else {
        return;
    };
```
Rust complains that it doesn’t make sense to use `let...else` with an
irrefutable pattern because the `else` will never be reached:


The Rust Programming Language › Refutability: Whether a Pattern Might Fail to Match

```console
$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
warning: unreachable `else` clause
 --> src/main.rs:2:15
  |
2 |     let x = 5 else {
  |     --------- ^^^^
  |     |
  |     assigning to binding pattern will always succeed
  |
  = note: this pattern always matches, so the else clause is unreachable
  = note: `#[warn(irrefutable_let_patterns)]` on by default

warning: `patterns` (bin "patterns") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.39s
     Running `target/debug/patterns`
```
For this reason, match arms must use refutable patterns, except for the last
arm, which should match any remaining values with an irrefutable pattern. Rust
allows us to use an irrefutable pattern in a `match` with only one arm, but
this syntax isn’t particularly useful and could be replaced with a simpler
`let` statement.
Now that you know where to use patterns and the difference between refutable
and irrefutable patterns, let’s cover all the syntax we can use to create
patterns.


The Rust Programming Language › Pattern Syntax

In this section, we gather all the syntax that is valid in patterns and discuss
why and when you might want to use each one.


The Rust Programming Language › Pattern Syntax › Matching Literals

As you saw in Chapter 6, you can match patterns against literals directly. The
following code gives some examples:
```rust
    let x = 1;

    match x {
        1 => println!("one"),
        2 => println!("two"),
        3 => println!("three"),
        _ => println!("anything"),
    }
```
This code prints `one` because the value in `x` is `1`. This syntax is useful
when you want your code to take an action if it gets a particular concrete
value.


The Rust Programming Language › Pattern Syntax › Matching Named Variables

Named variables are irrefutable patterns that match any value, and we’ve used
them many times in this book. However, there is a complication when you use
named variables in `match`, `if let`, or `while let` expressions. Because each
of these kinds of expressions starts a new scope, variables declared as part of
a pattern inside these expressions will shadow those with the same name outside
the constructs, as is the case with all variables. In Listing 19-11, we declare
a variable named `x` with the value `Some(5)` and a variable `y` with the value
`10`. We then create a `match` expression on the value `x`. Look at the
patterns in the match arms and `println!` at the end, and try to figure out
what the code will print before running this code or reading further.
Listing 19-11: A `match` expression with an arm that introduces a new variable which shadows an existing variable `y` (src/main.rs)
```rust
    let x = Some(5);
    let y = 10;

    match x {
        Some(50) => println!("Got 50"),
        Some(y) => println!("Matched, y = {y}"),
        _ => println!("Default case, x = {x:?}"),
    }

    println!("at the end: x = {x:?}, y = {y}");
```
Let’s walk through what happens when the `match` expression runs. The pattern
in the first match arm doesn’t match the defined value of `x`, so the code
continues.


The Rust Programming Language › Pattern Syntax › Matching Named Variables

The pattern in the second match arm introduces a new variable named `y` that
will match any value inside a `Some` value. Because we’re in a new scope inside
the `match` expression, this is a new `y` variable, not the `y` we declared at
the beginning with the value `10`. This new `y` binding will match any value
inside a `Some`, which is what we have in `x`. Therefore, this new `y` binds to
the inner value of the `Some` in `x`. That value is `5`, so the expression for
that arm executes and prints `Matched, y = 5`.
If `x` had been a `None` value instead of `Some(5)`, the patterns in the first
two arms wouldn’t have matched, so the value would have matched to the
underscore. We didn’t introduce the `x` variable in the pattern of the
underscore arm, so the `x` in the expression is still the outer `x` that hasn’t
been shadowed. In this hypothetical case, the `match` would print `Default case,
x = None`.
When the `match` expression is done, its scope ends, and so does the scope of
the inner `y`. The last `println!` produces `at the end: x = Some(5), y = 10`.
To create a `match` expression that compares the values of the outer `x` and
`y`, rather than introducing a new variable that shadows the existing `y`
variable, we would need to use a match guard conditional instead. We’ll talk
about match guards later in the “Adding Conditionals with Match
Guards” section.


The Rust Programming Language › Pattern Syntax › Matching Multiple Patterns

In `match` expressions, you can match multiple patterns using the `|` syntax,
which is the pattern _or_ operator. For example, in the following code, we match
the value of `x` against the match arms, the first of which has an _or_ option,
meaning if the value of `x` matches either of the values in that arm, that
arm’s code will run:
```rust
    let x = 1;

    match x {
        1 | 2 => println!("one or two"),
        3 => println!("three"),
        _ => println!("anything"),
    }
```
This code prints `one or two`.

Pattern Syntax
Matching Multiple Patterns


The Rust Programming Language › Pattern Syntax › Matching Ranges of Values with `..=`

The `..=` syntax allows us to match to an inclusive range of values. In the
following code, when a pattern matches any of the values within the given
range, that arm will execute:
```rust
    let x = 5;

    match x {
        1..=5 => println!("one through five"),
        _ => println!("something else"),
    }
```
If `x` is `1`, `2`, `3`, `4`, or `5`, the first arm will match. This syntax is
more convenient for multiple match values than using the `|` operator to
express the same idea; if we were to use `|`, we would have to specify `1 | 2 |
3 | 4 | 5`. Specifying a range is much shorter, especially if we want to match,
say, any number between 1 and 1,000!
The compiler checks that the range isn’t empty at compile time, and because the
only types for which Rust can tell if a range is empty or not are `char` and
numeric values, ranges are only allowed with numeric or `char` values.
Here is an example using ranges of `char` values:
```rust
    let x = 'c';

    match x {
        'a'..='j' => println!("early ASCII letter"),
        'k'..='z' => println!("late ASCII letter"),
        _ => println!("something else"),
    }
```
Rust can tell that `'c'` is within the first pattern’s range and prints `early
ASCII letter`.

Pattern Syntax
Matching Ranges of Values with `..=`


The Rust Programming Language › Pattern Syntax › Destructuring to Break Apart Values › Structs

We can also use patterns to destructure structs, enums, and tuples to use
different parts of these values. Let’s walk through each value.
Listing 19-12 shows a `Point` struct with two fields, `x` and `y`, that we can
break apart using a pattern with a `let` statement.
Listing 19-12: Destructuring a struct’s fields into separate variables (src/main.rs)
```rust
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p = Point { x: 0, y: 7 };

    let Point { x: a, y: b } = p;
    assert_eq!(0, a);
    assert_eq!(7, b);
}
```
This code creates the variables `a` and `b` that match the values of the `x`
and `y` fields of the `p` struct. This example shows that the names of the
variables in the pattern don’t have to match the field names of the struct.
However, it’s common to match the variable names to the field names to make it
easier to remember which variables came from which fields. Because of this
common usage, and because writing `let Point { x: x, y: y } = p;` contains a
lot of duplication, Rust has a shorthand for patterns that match struct fields:
You only need to list the name of the struct field, and the variables created
from the pattern will have the same names. Listing 19-13 behaves in the same
way as the code in Listing 19-12, but the variables created in the `let`
pattern are `x` and `y` instead of `a` and `b`.
Listing 19-13: Destructuring struct fields using struct field shorthand (src/main.rs)

Pattern Syntax
Destructuring to Break Apart Values
Structs


The Rust Programming Language › Pattern Syntax › Destructuring to Break Apart Values › Structs

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

fn main() {
    let p = Point { x: 0, y: 7 };

    let Point { x, y } = p;
    assert_eq!(0, x);
    assert_eq!(7, y);
}
```
This code creates the variables `x` and `y` that match the `x` and `y` fields
of the `p` variable. The outcome is that the variables `x` and `y` contain the
values from the `p` struct.
We can also destructure with literal values as part of the struct pattern
rather than creating variables for all the fields. Doing so allows us to test
some of the fields for particular values while creating variables to
destructure the other fields.
In Listing 19-14, we have a `match` expression that separates `Point` values
into three cases: points that lie directly on the `x` axis (which is true when
`y = 0`), on the `y` axis (`x = 0`), or on neither axis.
Listing 19-14: Destructuring and matching literal values in one pattern (src/main.rs)
```rust
fn main() {
    let p = Point { x: 0, y: 7 };

    match p {
        Point { x, y: 0 } => println!("On the x axis at {x}"),
        Point { x: 0, y } => println!("On the y axis at {y}"),
        Point { x, y } => {
            println!("On neither axis: ({x}, {y})");
        }
    }
}
```


The Rust Programming Language › Pattern Syntax › Destructuring to Break Apart Values › Enums

The first arm will match any point that lies on the `x` axis by specifying that
the `y` field matches if its value matches the literal `0`. The pattern still
creates an `x` variable that we can use in the code for this arm.
Similarly, the second arm matches any point on the `y` axis by specifying that
the `x` field matches if its value is `0` and creates a variable `y` for the
value of the `y` field. The third arm doesn’t specify any literals, so it
matches any other `Point` and creates variables for both the `x` and `y` fields.
In this example, the value `p` matches the second arm by virtue of `x`
containing a `0`, so this code will print `On the y axis at 7`.
Remember that a `match` expression stops checking arms once it has found the
first matching pattern, so even though `Point { x: 0, y: 0 }` is on the `x` axis
and the `y` axis, this code would only print `On the x axis at 0`.
We’ve destructured enums in this book (for example, Listing 6-5 in Chapter 6),
but we haven’t yet explicitly discussed that the pattern to destructure an enum
corresponds to the way the data stored within the enum is defined. As an
example, in Listing 19-15, we use the `Message` enum from Listing 6-2 and write
a `match` with patterns that will destructure each inner value.
Listing 19-15: Destructuring enum variants that hold different kinds of values (src/main.rs)

Pattern Syntax
Destructuring to Break Apart Values
Enums


The Rust Programming Language › Pattern Syntax › Destructuring to Break Apart Values › Enums

```rust
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

fn main() {
    let msg = Message::ChangeColor(0, 160, 255);

    match msg {
        Message::Quit => {
            println!("The Quit variant has no data to destructure.");
        }
        Message::Move { x, y } => {
            println!("Move in the x direction {x} and in the y direction {y}");
        }
        Message::Write(text) => {
            println!("Text message: {text}");
        }
        Message::ChangeColor(r, g, b) => {
            println!("Change color to red {r}, green {g}, and blue {b}");
        }
    }
}
```
This code will print `Change color to red 0, green 160, and blue 255`. Try
changing the value of `msg` to see the code from the other arms run.
For enum variants without any data, like `Message::Quit`, we can’t destructure
the value any further. We can only match on the literal `Message::Quit` value,
and no variables are in that pattern.
For struct-like enum variants, such as `Message::Move`, we can use a pattern
similar to the pattern we specify to match structs. After the variant name, we
place curly brackets and then list the fields with variables so that we break
apart the pieces to use in the code for this arm. Here we use the shorthand
form as we did in Listing 19-13.


The Rust Programming Language › Pattern Syntax › Destructuring to Break Apart Values › Nested Structs and Enums

For tuple-like enum variants, like `Message::Write` that holds a tuple with one
element and `Message::ChangeColor` that holds a tuple with three elements, the
pattern is similar to the pattern we specify to match tuples. The number of
variables in the pattern must match the number of elements in the variant we’re
matching.
So far, our examples have all been matching structs or enums one level deep,
but matching can work on nested items too! For example, we can refactor the
code in Listing 19-15 to support RGB and HSV colors in the `ChangeColor`
message, as shown in Listing 19-16.
Listing 19-16: Matching on nested enums
```rust
enum Color {
    Rgb(i32, i32, i32),
    Hsv(i32, i32, i32),
}

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(Color),
}

fn main() {
    let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));

    match msg {
        Message::ChangeColor(Color::Rgb(r, g, b)) => {
            println!("Change color to red {r}, green {g}, and blue {b}");
        }
        Message::ChangeColor(Color::Hsv(h, s, v)) => {
            println!("Change color to hue {h}, saturation {s}, value {v}");
        }
        _ => (),
    }
}
```

Pattern Syntax
Destructuring to Break Apart Values
Nested Structs and Enums


The Rust Programming Language › Pattern Syntax › Destructuring to Break Apart Values › Structs and Tuples

The pattern of the first arm in the `match` expression matches a
`Message::ChangeColor` enum variant that contains a `Color::Rgb` variant; then,
the pattern binds to the three inner `i32` values. The pattern of the second
arm also matches a `Message::ChangeColor` enum variant, but the inner enum
matches `Color::Hsv` instead. We can specify these complex conditions in one
`match` expression, even though two enums are involved.
We can mix, match, and nest destructuring patterns in even more complex ways.
The following example shows a complicated destructure where we nest structs and
tuples inside a tuple and destructure all the primitive values out:
```rust
    let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 });
```
This code lets us break complex types into their component parts so that we can
use the values we’re interested in separately.
Destructuring with patterns is a convenient way to use pieces of values, such
as the value from each field in a struct, separately from each other.

Pattern Syntax
Destructuring to Break Apart Values
Structs and Tuples


The Rust Programming Language › Pattern Syntax › Ignoring Values in a Pattern › Parts of a Value with a Nested `_`

You’ve seen that it’s sometimes useful to ignore values in a pattern, such as
in the last arm of a `match`, to get a catch-all that doesn’t actually do
anything but does account for all remaining possible values. There are a few
ways to ignore entire values or parts of values in a pattern: using the `_`
pattern (which you’ve seen), using the `_` pattern within another pattern,
using a name that starts with an underscore, or using `..` to ignore remaining
parts of a value. Let’s explore how and why to use each of these patterns.
We’ve used the underscore as a wildcard pattern that will match any value but
not bind to the value. This is especially useful as the last arm in a `match`
expression, but we can also use it in any pattern, including function
parameters, as shown in Listing 19-17.
Listing 19-17: Using `_` in a function signature (src/main.rs)
```rust
fn foo(_: i32, y: i32) {
    println!("This code only uses the y parameter: {y}");
}

fn main() {
    foo(3, 4);
}
```
This code will completely ignore the value `3` passed as the first argument,
and will print `This code only uses the y parameter: 4`.
In most cases when you no longer need a particular function parameter, you
would change the signature so that it doesn’t include the unused parameter.
Ignoring a function parameter can be especially useful in cases when, for
example, you’re implementing a trait when you need a certain type signature but
the function body in your implementation doesn’t need one of the parameters.
You then avoid getting a compiler warning about unused function parameters, as
you would if you used a name instead.

Pattern Syntax
Ignoring Values in a Pattern
Parts of a Value with a Nested `_`


The Rust Programming Language › Pattern Syntax › Ignoring Values in a Pattern › Parts of a Value with a Nested `_`

We can also use `_` inside another pattern to ignore just part of a value, for
example, when we want to test for only part of a value but have no use for the
other parts in the corresponding code we want to run. Listing 19-18 shows code
responsible for managing a setting’s value. The business requirements are that
the user should not be allowed to overwrite an existing customization of a
setting but can unset the setting and give it a value if it is currently unset.
Listing 19-18: Using an underscore within patterns that match `Some` variants when we don’t need to use the value inside the `Some`
```rust
    let mut setting_value = Some(5);
    let new_setting_value = Some(10);

    match (setting_value, new_setting_value) {
        (Some(_), Some(_)) => {
            println!("Can't overwrite an existing customized value");
        }
        _ => {
            setting_value = new_setting_value;
        }
    }

    println!("setting is {setting_value:?}");
```
This code will print `Can't overwrite an existing customized value` and then
`setting is Some(5)`. In the first match arm, we don’t need to match on or use
the values inside either `Some` variant, but we do need to test for the case
when `setting_value` and `new_setting_value` are the `Some` variant. In that
case, we print the reason for not changing `setting_value`, and it doesn’t get
changed.
In all other cases (if either `setting_value` or `new_setting_value` is `None`)
expressed by the `_` pattern in the second arm, we want to allow
`new_setting_value` to become `setting_value`.


The Rust Programming Language › Pattern Syntax › Ignoring Values in a Pattern › An Unused Variable by Starting Its Name with `_`

We can also use underscores in multiple places within one pattern to ignore
particular values. Listing 19-19 shows an example of ignoring the second and
fourth values in a tuple of five items.
Listing 19-19: Ignoring multiple parts of a tuple
```rust
    let numbers = (2, 4, 8, 16, 32);

    match numbers {
        (first, _, third, _, fifth) => {
            println!("Some numbers: {first}, {third}, {fifth}");
        }
    }
```
This code will print `Some numbers: 2, 8, 32`, and the values `4` and `16` will
be ignored.
If you create a variable but don’t use it anywhere, Rust will usually issue a
warning because an unused variable could be a bug. However, sometimes it’s
useful to be able to create a variable you won’t use yet, such as when you’re
prototyping or just starting a project. In this situation, you can tell Rust
not to warn you about the unused variable by starting the name of the variable
with an underscore. In Listing 19-20, we create two unused variables, but when
we compile this code, we should only get a warning about one of them.
Listing 19-20: Starting a variable name with an underscore to avoid getting unused variable warnings (src/main.rs)
```rust
fn main() {
    let _x = 5;
    let y = 10;
}
```
Here, we get a warning about not using the variable `y`, but we don’t get a
warning about not using `_x`.


The Rust Programming Language › Pattern Syntax › Ignoring Values in a Pattern › Remaining Parts of a Value with `..`

Note that there is a subtle difference between using only `_` and using a name
that starts with an underscore. The syntax `_x` still binds the value to the
variable, whereas `_` doesn’t bind at all. To show a case where this
distinction matters, Listing 19-21 will provide us with an error.
Listing 19-21: An unused variable starting with an underscore still binds the value, which might take ownership of the value.
```rust,ignore,does_not_compile
    let s = Some(String::from("Hello!"));

    if let Some(_s) = s {
        println!("found a string");
    }

    println!("{s:?}");
```
We’ll receive an error because the `s` value will still be moved into `_s`,
which prevents us from using `s` again. However, using the underscore by itself
doesn’t ever bind to the value. Listing 19-22 will compile without any errors
because `s` doesn’t get moved into `_`.
Listing 19-22: Using an underscore does not bind the value.
```rust
    let s = Some(String::from("Hello!"));

    if let Some(_) = s {
        println!("found a string");
    }

    println!("{s:?}");
```
This code works just fine because we never bind `s` to anything; it isn’t moved.

Pattern Syntax
Ignoring Values in a Pattern
Remaining Parts of a Value with `..`


The Rust Programming Language › Pattern Syntax › Ignoring Values in a Pattern › Remaining Parts of a Value with `..`

With values that have many parts, we can use the `..` syntax to use specific
parts and ignore the rest, avoiding the need to list underscores for each
ignored value. The `..` pattern ignores any parts of a value that we haven’t
explicitly matched in the rest of the pattern. In Listing 19-23, we have a
`Point` struct that holds a coordinate in three-dimensional space. In the
`match` expression, we want to operate only on the `x` coordinate and ignore
the values in the `y` and `z` fields.
Listing 19-23: Ignoring all fields of a `Point` except for `x` by using `..`
```rust
    struct Point {
        x: i32,
        y: i32,
        z: i32,
    }

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

    match origin {
        Point { x, .. } => println!("x is {x}"),
    }
```
We list the `x` value and then just include the `..` pattern. This is quicker
than having to list `y: _` and `z: _`, particularly when we’re working with
structs that have lots of fields in situations where only one or two fields are
relevant.
The syntax `..` will expand to as many values as it needs to be. Listing 19-24
shows how to use `..` with a tuple.
Listing 19-24: Matching only the first and last values in a tuple and ignoring all other values (src/main.rs)
```rust
fn main() {
    let numbers = (2, 4, 8, 16, 32);

    match numbers {
        (first, .., last) => {
            println!("Some numbers: {first}, {last}");
        }
    }
}
```


The Rust Programming Language › Pattern Syntax › Ignoring Values in a Pattern › Remaining Parts of a Value with `..`

In this code, the first and last values are matched with `first` and `last`.
The `..` will match and ignore everything in the middle.
However, using `..` must be unambiguous. If it is unclear which values are
intended for matching and which should be ignored, Rust will give us an error.
Listing 19-25 shows an example of using `..` ambiguously, so it will not
compile.
Listing 19-25: An attempt to use `..` in an ambiguous way (src/main.rs)
```rust,ignore,does_not_compile
fn main() {
    let numbers = (2, 4, 8, 16, 32);

    match numbers {
        (.., second, ..) => {
            println!("Some numbers: {second}")
        },
    }
}
```
When we compile this example, we get this error:
```console
$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
error: `..` can only be used once per tuple pattern
 --> src/main.rs:5:22
  |
5 |         (.., second, ..) => {
  |          --          ^^ can only be used once per tuple pattern
  |          |
  |          previously used here

error: could not compile `patterns` (bin "patterns") due to 1 previous error
```


The Rust Programming Language › Pattern Syntax › Ignoring Values in a Pattern › Remaining Parts of a Value with `..`

It’s impossible for Rust to determine how many values in the tuple to ignore
before matching a value with `second` and then how many further values to
ignore thereafter. This code could mean that we want to ignore `2`, bind
`second` to `4`, and then ignore `8`, `16`, and `32`; or that we want to ignore
`2` and `4`, bind `second` to `8`, and then ignore `16` and `32`; and so forth.
The variable name `second` doesn’t mean anything special to Rust, so we get a
compiler error because using `..` in two places like this is ambiguous.


The Rust Programming Language › Pattern Syntax › Adding Conditionals with Match Guards

A _match guard_ is an additional `if` condition, specified after the pattern in
a `match` arm, that must also match for that arm to be chosen. Match guards are
useful for expressing more complex ideas than a pattern alone allows. Note,
however, that they are only available in `match` expressions, not `if let` or
`while let` expressions.
The condition can use variables created in the pattern. Listing 19-26 shows a
`match` where the first arm has the pattern `Some(x)` and also has a match
guard of `if x % 2 == 0` (which will be `true` if the number is even).
Listing 19-26: Adding a match guard to a pattern
```rust
    let num = Some(4);

    match num {
        Some(x) if x % 2 == 0 => println!("The number {x} is even"),
        Some(x) => println!("The number {x} is odd"),
        None => (),
    }
```
This example will print `The number 4 is even`. When `num` is compared to the
pattern in the first arm, it matches because `Some(4)` matches `Some(x)`. Then,
the match guard checks whether the remainder of dividing `x` by 2 is equal to
0, and because it is, the first arm is selected.
If `num` had been `Some(5)` instead, the match guard in the first arm would
have been `false` because the remainder of 5 divided by 2 is 1, which is not
equal to 0. Rust would then go to the second arm, which would match because the
second arm doesn’t have a match guard and therefore matches any `Some` variant.

Pattern Syntax
Adding Conditionals with Match Guards


The Rust Programming Language › Pattern Syntax › Adding Conditionals with Match Guards

There is no way to express the `if x % 2 == 0` condition within a pattern, so
the match guard gives us the ability to express this logic. The downside of
this additional expressiveness is that the compiler doesn’t try to check for
exhaustiveness when match guard expressions are involved.
When discussing Listing 19-11, we mentioned that we could use match guards to
solve our pattern-shadowing problem. Recall that we created a new variable
inside the pattern in the `match` expression instead of using the variable
outside the `match`. That new variable meant we couldn’t test against the value
of the outer variable. Listing 19-27 shows how we can use a match guard to fix
this problem.
Listing 19-27: Using a match guard to test for equality with an outer variable (src/main.rs)
```rust
fn main() {
    let x = Some(5);
    let y = 10;

    match x {
        Some(50) => println!("Got 50"),
        Some(n) if n == y => println!("Matched, n = {n}"),
        _ => println!("Default case, x = {x:?}"),
    }

    println!("at the end: x = {x:?}, y = {y}");
}
```
This code will now print `Default case, x = Some(5)`. The pattern in the second
match arm doesn’t introduce a new variable `y` that would shadow the outer `y`,
meaning we can use the outer `y` in the match guard. Instead of specifying the
pattern as `Some(y)`, which would have shadowed the outer `y`, we specify
`Some(n)`. This creates a new variable `n` that doesn’t shadow anything because
there is no `n` variable outside the `match`.


The Rust Programming Language › Pattern Syntax › Adding Conditionals with Match Guards

The match guard `if n == y` is not a pattern and therefore doesn’t introduce new
variables. This `y` _is_ the outer `y` rather than a new `y` shadowing it, and
we can look for a value that has the same value as the outer `y` by comparing
`n` to `y`.
You can also use the _or_ operator `|` in a match guard to specify multiple
patterns; the match guard condition will apply to all the patterns. Listing
19-28 shows the precedence when combining a pattern that uses `|` with a match
guard. The important part of this example is that the `if y` match guard
applies to `4`, `5`, _and_ `6`, even though it might look like `if y` only
applies to `6`.
Listing 19-28: Combining multiple patterns with a match guard
```rust
    let x = 4;
    let y = false;

    match x {
        4 | 5 | 6 if y => println!("yes"),
        _ => println!("no"),
    }
```
The match condition states that the arm only matches if the value of `x` is
equal to `4`, `5`, or `6` _and_ if `y` is `true`. When this code runs, the
pattern of the first arm matches because `x` is `4`, but the match guard `if y`
is `false`, so the first arm is not chosen. The code moves on to the second
arm, which does match, and this program prints `no`. The reason is that the
`if` condition applies to the whole pattern `4 | 5 | 6`, not just to the last
value `6`. In other words, the precedence of a match guard in relation to a
pattern behaves like this:


The Rust Programming Language › Pattern Syntax › Adding Conditionals with Match Guards

```text
(4 | 5 | 6) if y => ...
```
rather than this:
```text
4 | 5 | (6 if y) => ...
```
After running the code, the precedence behavior is evident: If the match guard
were applied only to the final value in the list of values specified using the
`|` operator, the arm would have matched, and the program would have printed
`yes`.


The Rust Programming Language › Pattern Syntax › Using `@` Bindings

The _at_ operator `@` lets us create a variable that holds a value at the same
time we’re testing that value for a pattern match. In Listing 19-29, we want to
test that a `Message::Hello` `id` field is within the range `3..=7`. We also
want to bind the value to the variable `id` so that we can use it in the code
associated with the arm.
Listing 19-29: Using `@` to bind to a value in a pattern while also testing it
```rust
    enum Message {
        Hello { id: i32 },
    }

    let msg = Message::Hello { id: 5 };

    match msg {
        Message::Hello { id: id @ 3..=7 } => {
            println!("Found an id in range: {id}")
        }
        Message::Hello { id: 10..=12 } => {
            println!("Found an id in another range")
        }
        Message::Hello { id } => println!("Found some other id: {id}"),
    }
```
This example will print `Found an id in range: 5`. By specifying `id @` before
the range `3..=7`, we’re capturing whatever value matched the range in a
variable named `id` while also testing that the value matched the range pattern.
In the second arm, where we only have a range specified in the pattern, the code
associated with the arm doesn’t have a variable that contains the actual value
of the `id` field. The `id` field’s value could have been 10, 11, or 12, but
the code that goes with that pattern doesn’t know which it is. The pattern code
isn’t able to use the value from the `id` field because we haven’t saved the
`id` value in a variable.


The Rust Programming Language › Pattern Syntax › Using `@` Bindings

In the last arm, where we’ve specified a variable without a range, we do have
the value available to use in the arm’s code in a variable named `id`. The
reason is that we’ve used the struct field shorthand syntax. But we haven’t
applied any test to the value in the `id` field in this arm, as we did with the
first two arms: Any value would match this pattern.
Using `@` lets us test a value and save it in a variable within one pattern.


The Rust Programming Language › Summary

Rust’s patterns are very useful in distinguishing between different kinds of
data. When used in `match` expressions, Rust ensures that your patterns cover
every possible value, or your program won’t compile. Patterns in `let`
statements and function parameters make those constructs more useful, enabling
the destructuring of values into smaller parts and assigning those parts to
variables. We can create simple or complex patterns to suit our needs.
Next, for the penultimate chapter of the book, we’ll look at some advanced
aspects of a variety of Rust’s features.


The Rust Programming Language › Advanced Features

By now, you’ve learned the most commonly used parts of the Rust programming
language. Before we do one more project, in Chapter 21, we’ll look at a few
aspects of the language you might run into every once in a while but may not
use every day. You can use this chapter as a reference for when you encounter
any unknowns. The features covered here are useful in very specific situations.
Although you might not reach for them often, we want to make sure you have a
grasp of all the features Rust has to offer.
In this chapter, we’ll cover:
- Unsafe Rust: How to opt out of some of Rust’s guarantees and take
  responsibility for manually upholding those guarantees
- Advanced traits: Associated types, default type parameters, fully qualified
  syntax, supertraits, and the newtype pattern in relation to traits
- Advanced types: More about the newtype pattern, type aliases, the never type,
  and dynamically sized types
- Advanced functions and closures: Function pointers and returning closures
- Macros: Ways to define code that defines more code at compile time
It’s a panoply of Rust features with something for everyone! Let’s dive in!


The Rust Programming Language › Unsafe Rust

All the code we’ve discussed so far has had Rust’s memory safety guarantees
enforced at compile time. However, Rust has a second language hidden inside it
that doesn’t enforce these memory safety guarantees: It’s called _unsafe Rust_
and works just like regular Rust but gives us extra superpowers.
Unsafe Rust exists because, by nature, static analysis is conservative. When
the compiler tries to determine whether or not code upholds the guarantees,
it’s better for it to reject some valid programs than to accept some invalid
programs. Although the code _might_ be okay, if the Rust compiler doesn’t have
enough information to be confident, it will reject the code. In these cases,
you can use unsafe code to tell the compiler, “Trust me, I know what I’m
doing.” Be warned, however, that you use unsafe Rust at your own risk: If you
use unsafe code incorrectly, problems can occur due to memory unsafety, such as
null pointer dereferencing.
Another reason Rust has an unsafe alter ego is that the underlying computer
hardware is inherently unsafe. If Rust didn’t let you do unsafe operations, you
couldn’t do certain tasks. Rust needs to allow you to do low-level systems
programming, such as directly interacting with the operating system or even
writing your own operating system. Working with low-level systems programming
is one of the goals of the language. Let’s explore what we can do with unsafe
Rust and how to do it.