Why is derefering not required when accessing referred data when destructuring

How Does the following destructuring work without using a de-referencing operator on city variable in process_city_values function? (Absolute noob here. Going through easy rust github tutorial)

struct City {
    name: String,
    name_before: String,
    population: u32,
    date_founded: u32,
}

impl City {
    fn new(name: String, name_before: String, population: u32, date_founded: u32) -> Self {
        Self {
            name,
            name_before,
            population,
            date_founded,
        }
    }
}

fn process_city_values(city: &City) {
    let City {
        name,
        name_before,
        population,
        date_founded,
    } = city; // <- *city throws error
        // now we have the values to use separately
    let two_names = vec![name, name_before];
    println!("The city's two names are {:?}", two_names);
}

fn main() {
    let tallinn = City::new("Tallinn".to_string(), "Reval".to_string(), 426_538, 1219);
    process_city_values(&tallinn);
}

It's a general principle that if you use a pattern on a reference to a struct/enum, then it is destructured according to the struct/enum's structure, but all the fields become references.

This applies both to matching, if let and to irrefutable patterns like in your example.

The reason it doesn't work with * is that this would use the value directly, so the fields are not available as references, but their actual type, but this requires taking ownership, which you can only do with a dereference for Copy types.

2 Likes

If you'd like more details on how this works and why, see RFC 2005: Match Ergonomics using Default Binding Modes.

1 Like

Thanks a lot @alice and @mbrubeck.

I got what I was looking for: An explanation and the source of the behaviour.

FWIW, I come from C background & Python background.

Just to help you play with compiler, here is a version that works using *value. The explanations provided are spot-on. But, just for fun, see how this code works.

Playground

1 Like

There is an ongoing discussion about this in IRLO.

TL;DR: There is an opt-in Clippy lint that tells you when you have mismatched types in patterns that happen to work together because of match ergonomics.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.