This article is part number 7 of the Rust review series.


A commonly-acclaimed feature of Rust is its match keyword: a “conditional on steroids”. match lets you take the value of an expression and compare it against a bunch of values—or, more generally, patterns.

As you write and read Rust, you will notice that this keyword is used everywhere because it’s the way to access certain types, like Option values or error codes.

For example:

match node.get_parent() {  // node is an Option<Something>.
    Some(parent) => {
        // Do something with "parent", which we know points to a node.
    },
    None => {
        // There is no parent so do something else.
    }
}

In the snippet above, we have a match statement with two arms. One key detail to observe is how the parent variable, which was used as a pattern to peek inside the Some value, is only available in the first arm. The None arm has no access to the parent variable, which is obvious because there is no parent in this case.

OK so… I just said statement. But as we saw in the previous post, everything in Rust is an expression—and you guessed right, match is no exception. A match can be assigned to a variable:

let parent = match node.get_parent() {
    Some(parent) => parent,
    None => "ROOT",
};
// Do something with "parent", which we know points to a node.

The most attractive feature of match, however, and the primary reason I am writing about it in its own post, is that the arms are evaluated in order and must be exhaustive: any expression fed to match must have a case where it’s accepted. For example, this results in a build error:

enum Shape { Circle, Triangle, Square }

fn shape_name(shape: &Shape) -> &'static str {
  match shape {
    Shape::Circle => "circle",
    Shape::Triangle => "triangle",
    // ERROR: We forgot the Shape::Square case.
  }
}

This is an extremely useful feature to deliver safe and future-proof code: by using match, there is no way you can forget to handle a case even if the code later changes to cover more cases. E.g. if you ever decided to add a new shape to the enum above, the compiler would refuse to build your code, so you would be forced to add the missing arms. (Yes, I know, other languages like C++ will warn you if switch statements miss cases on enumerations… but will only do so under these specific circumstances; match is useful outside of enums.)

To conclude: the reason I find this interesting is because this feature aligns perfectly well with my Readability: Explicitly state complementary conditions post.