The matches! macro is a built-in Rust utility that checks if a value matches a specific pattern, returning a boolean result without requiring the verbose syntax of a full match expression. It is the idiomatic way to perform simple pattern matching when you only care about the true/false outcome rather than extracting values or handling multiple branches.
Use matches! when you need to verify conditions like checking an Option for Some, testing an Enum variant, or validating a tuple structure. It is often more readable and less error-prone than writing if let or a multi-line match for single-condition checks.
Here is a practical example checking an Option and an Enum:
fn main() {
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
// Check if the option contains a value
assert!(matches!(some_value, Some(_)));
assert!(!matches!(none_value, Some(_)));
// Check specific enum variants
enum Status {
Active,
Inactive,
Pending { days: u32 },
}
let status = Status::Active;
let pending = Status::Pending { days: 5 };
// Matches the Active variant
assert!(matches!(status, Status::Active));
// Matches Pending with any days count
assert!(matches!(pending, Status::Pending { days: _ }));
// Matches Pending specifically with 5 days
assert!(matches!(pending, Status::Pending { days: 5 }));
}
You can also use it to guard against specific error types or complex tuple patterns. For instance, checking if a result is an error without needing to destructure the error payload:
use std::fs::File;
use std::io::ErrorKind;
fn check_file_error() -> bool {
let result = File::open("nonexistent.txt");
// Returns true if the result is an error with NotFound kind
matches!(result, Err(e) if e.kind() == ErrorKind::NotFound)
}
Avoid using matches! if you need to extract data from the pattern, as it discards the matched value. In those cases, use if let or a standard match block. Also, remember that matches! is a macro, not a function, so it evaluates its arguments at compile time and handles pattern matching logic directly. It is available in the standard library since Rust 1.42.0, so no external crates are required.