21.12 Matching Smart Pointers like Box<T>
Patterns work naturally with smart pointers like Box<T>. The pointer is often implicitly dereferenced during matching.
enum Data {
Value(i32),
Pointer(Box<i32>),
}
fn process_boxed_data(data: Data) {
match data {
Data::Value(n) => {
println!("Got direct value: {}", n);
}
// `Box` is implicitly dereferenced to match the inner `i32`.
// `boxed_val` here binds the `i32` value *inside* the Box.
// This pattern takes ownership of the Box and thus the value.
Data::Pointer(boxed_val) => {
println!("Got value from Box: {}", *boxed_val);
// `boxed_val` is the `Box<i32>` itself. We can use it here.
}
}
}
fn main() {
let d1 = Data::Value(10);
let d2 = Data::Pointer(Box::new(20));
process_boxed_data(d1); // Output: Got direct value: 10
process_boxed_data(d2); // Output: Got value from Box: 20
// d2 is moved into the function call and consumed by the matching arm.
}
If you need to match a Box<T> without taking ownership, match a reference to the Data enum and use ref or ref mut on the inner value if needed:
enum Data {
Value(i32),
Pointer(Box<i32>),
}
fn inspect_boxed_data_ref(data: &Data) {
match data { // `data` is a reference `&Data`
// For `Data::Value(n)`, `n` automatically becomes `&i32` due to
// match ergonomics.
Data::Value(n) => println!("Inspecting direct value: {}", n),
// When matching on `data: &Data`, patterns like `Data::Pointer(field_name)`
// automatically cause `field_name` to bind as a reference.
// Here, `boxed_ptr` naturally becomes `&Box<i32>`.
// The explicit `ref` keyword is therefore unnecessary
// and disallowed by the compiler.
Data::Pointer(boxed_ptr) => { // `ref` keyword removed
// `boxed_ptr` is of type `&Box<i32>`.
// The first `*` dereferences `&Box<i32>` to `Box<i32>`.
// The second `*` dereferences `Box<i32>` to `i32`.
println!("Inspecting value in Box: {}", **boxed_ptr);
}
}
}
fn main() {
let d_box = Data::Pointer(Box::new(30));
inspect_boxed_data_ref(&d_box); // Output: Inspecting value in Box: 30
// d_box is still owned here as we passed a reference.
}
(Note: The box keyword for matching directly on heap allocation (box pattern) is still an unstable feature and not recommended for general use.)