Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The wildcard pattern (_) is an irrefutable pattern that matches any value without binding it to an identifier. It instructs the compiler to explicitly discard the matched data, satisfying pattern exhaustiveness checks while preventing “unused variable” warnings. Binding, Ownership, and Drop Semantics Unlike named variables or variables prefixed with an underscore (e.g., _var), the standalone wildcard _ never creates a binding. Because no binding occurs, the wildcard pattern does not move, consume, or take ownership of the matched value.
let s = String::from("Rust");
let _ = s; // Matches 's' but does not bind or move it
println!("{}", s); // Valid: 's' is still accessible
Conversely, an identifier prefixed with an underscore acts as a standard binding and will trigger move semantics for non-Copy types:
let s = String::from("Rust");
let _s = s; // Binds and moves 's'
// println!("{}", s); // Compiler error: value borrowed here after move
A critical mechanical consequence of _ not creating a binding is its effect on the drop semantics of temporary values. When a temporary expression is assigned to a wildcard, the value is dropped immediately at the end of the statement. In contrast, assigning a temporary to a named binding (even one prefixed with an underscore) extends the value’s lifetime to the end of the enclosing scope. This distinction is a common footgun in RAII (Resource Acquisition Is Initialization) patterns, such as managing lock guards.
use std::sync::Mutex;

let m = Mutex::new(0);

// The temporary MutexGuard is dropped IMMEDIATELY at the semicolon.
// The mutex is unlocked before the next line executes.
let _ = m.lock().unwrap();

// The temporary MutexGuard is bound to `_guard` and lives until the end of the scope.
// The mutex remains locked for subsequent operations.
let _guard = m.lock().unwrap();
Structural Destructuring The wildcard pattern can be nested within compound patterns to selectively ignore specific elements of tuples, arrays, enums, or structs during destructuring. Tuples and Arrays:
let coordinate = (10, 20, 30);
let (x, _, z) = coordinate; // Ignores the second element
Enums:
let result: Result<i32, String> = Err(String::from("Error"));
match result {
    Ok(val) => println!("Value: {}", val),
    Err(_) => println!("Error ignored"), // Matches the Err variant but ignores the inner String
}
Structs:
struct Point { x: i32, y: i32, z: i32 }
let p = Point { x: 0, y: 1, z: 2 };
let Point { x, y: _, z } = p; // Ignores the 'y' field during destructuring
Exhaustiveness in match Expressions Because _ is irrefutable (it cannot fail to match), it functions as a universal catch-all. When placed as the final arm of a match expression, it guarantees that all possible variants of a type are accounted for, satisfying the compiler’s strict exhaustiveness requirements.
let value = 5u8;
match value {
    1 => println!("One"),
    2 => println!("Two"),
    _ => println!("Catch-all"), // Matches 0, and 3 through 255
}
Function and Closure Parameters The wildcard can replace parameter names in function, trait method, or closure signatures. This indicates that an argument is structurally required by the type signature but is intentionally ignored in the implementation scope.
fn process_data(data: i32, _: bool) {
    // The boolean argument must be passed by the caller, 
    // but it is not bound to an identifier in this scope.
}
Master Rust with Deep Grasping Methodology!Learn More