Function parameters, let
statements, and 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 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 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 18-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.
If some_option_value
was 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 value. At compile time, Rust will complain that we’ve tried to use a refutable pattern where an irrefutable pattern is required:
Because we didn’t cover (and couldn’t cover!) every valid value with the pattern Some(x)
, Rust rightfully produces a compiler error.
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 if let
. Then if the pattern doesn’t match, the code will just skip the code in the curly brackets, giving it a way to continue validly. Listing 18-9 shows how to fix the code in Listing 18-8.
We’ve given the code an out! This code is perfectly valid, although it means we cannot use an irrefutable pattern without receiving an error. If we give if let
a pattern that will always match, such as x
, as shown in Listing 18-10, the compiler will give a warning.
Listing 18-10: Attempting to use an irrefutable pattern with if let
Rust complains that it doesn’t make sense to use if let
with an irrefutable pattern:
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.