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.)