DEV Community

Cover image for [Rust Guide] 18.2. Refutability - Whether a Pattern Can Fail to Match
SomeB1oody
SomeB1oody

Posted on

[Rust Guide] 18.2. Refutability - Whether a Pattern Can Fail to Match

18.2.1 Two Forms of Patterns

Patterns come in two forms:

  • refutable, meaning they can fail to match
  • irrefutable, meaning they cannot fail; you can think of them as patterns that always succeed no matter how they are written

A pattern that can match any value that may be passed in is irrefutable. For example:

let x = 5;
Enter fullscreen mode Exit fullscreen mode

This statement cannot fail because x can match any possible value on the right-hand side of the expression.

A pattern that cannot match some possible values is refutable. For example:

if let Some(x) = a_value
Enter fullscreen mode Exit fullscreen mode

If the value on the right-hand side is None, the pattern fails to match.

Function parameters, let statements, and for loops only accept irrefutable patterns. For example:

let a: Option<i32> = Some(5);
let Some(x) = a;
Enter fullscreen mode Exit fullscreen mode

Some(x) = a is refutable because None is also possible, but let statements accept only irrefutable patterns, so the compiler reports an error. How do we fix this? Use if let:

let a: Option<i32> = Some(5);
if let Some(x) = a {
    // ...
}
Enter fullscreen mode Exit fullscreen mode

if let and while let support both refutable and irrefutable patterns. In fact, if you use an irrefutable pattern in if let or while let, the compiler warns you because the possibility of failure exists conceptually. For example:

if let x = 5 {
    println!("{x}");
};
Enter fullscreen mode Exit fullscreen mode

Output:

$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
warning: irrefutable `if let` pattern
 --> src/main.rs:2:8
  |
2 |     if let x = 5 {
  |        ^^^^^^^^^
  |
  = note: this pattern will always match, so the `if let` is useless
  = help: consider replacing the `if let` with a `let`
  = 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`
5
Enter fullscreen mode Exit fullscreen mode

The compiler warns about an “irrefutable if let pattern.” That is because using an irrefutable pattern inside a context meant for refutable patterns is pointless.

Based on these concepts, think about the arms of a match expression: every arm except the last one should be refutable, and the last arm should be irrefutable because it needs to match all remaining cases.

Top comments (0)