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:
fn inspect_boxed_data_ref(data: &Data) { match data { Data::Value(n) => println!("Inspecting direct value: {}", n), // Match through the reference, then `ref` borrows the Box itself. Data::Pointer(ref boxed_ptr) => { // `boxed_ptr` is `&Box<i32>`. Dereference to get the value. 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.)