Vikash Balasubramanian
Vikash Balasubramanian

Reputation: 3233

Why does destructuring a borrowed Enum require dereferencing its fields?

Consider the following snippet:

use std::fmt;

enum TestEnum {
    StructMem {value: i32, is_valid: bool},
    RandoMem,
}

impl fmt::Display for TestEnum {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use TestEnum::*;
        match self {
            StructMem {value, is_valid} => {
                if *is_valid { // Why dereference is_valid ?
                    write!(f, "f")?
                }
                write!(f, "{:?}", value)
            }
            RandoMem => {
                f.write_str("Random")
            }
        }
    }
}

Why do I need to dereference is_valid in the if statement?

EDIT: This question What is the syntax to match on a reference to an enum? seems to be dealing with a similar situation, but the answers are all focused on solving the specific issue (which does not involve a struct) and are not explaining the ownership/binding semantics.

Upvotes: 0

Views: 603

Answers (2)

pretzelhammer
pretzelhammer

Reputation: 15115

When you pattern match a reference and de-structure it you can only get references of the inner members, otherwise you'd be moving the inner members out of an immutable reference which would violate Rust's ownership rules. Here's a simpler example:

struct Container(Vec<i32>);

fn get_inner_vec(c: &Container) -> &Vec<i32> {
    // v MUST BE a reference
    // otherwise this destructing would somehow be moving the Vec
    // outside of an immutable borrow of Container
    let Container(v) = c;
    v
}

Upvotes: 1

user2722968
user2722968

Reputation: 16475

This is not specific to the match or the enum but due to the signature of fmt(), which takes self as a reference (&self instead of self, if ownership was taken).

The match self, therefore, already refers to a borrowed instance of TestEnum and the match-arm StructMem {value, is_valid} binds via references (&i32, and &bool). This is why is_valid ends up being a &bool, not a bool.

Upvotes: 3

Related Questions