Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rust Destructuring struct reference vs Destructuring struct

Tags:

rust

The following code works

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32
}

fn area(shape: &Rectangle) -> u32 {
    let Rectangle{width, height} = shape;
    width * height
}

fn main() {
    let rec1 = Rectangle {width: 5, height: 10};
    println!("Area {}", area(&rec1));
    println!("Rec {:?}", rec1);
}

But replacing the reference to struct &Shape with dereference reference *&Shape also works (e.g let Rectangle{width, height} = shape; --> let Rectangle{width, height} = *shape;).

I have no idea why both work, is there some implicit dereferencing when destructing? I though &Shape reference only points to where Shape is in memory, whereas *&Shape is Shape itself. width and height are properties of struct Rectangle rather than the reference &Rectangle.

like image 335
I should change my Username Avatar asked Aug 29 '26 14:08

I should change my Username


2 Answers

I have no idea why both work, is there some implicit dereferencing when destructing?

This is a (convenient but confusing) consequence of Edition 2018's match ergonomics: when matching on reference types, the compiler will implicitly add references and deref so things are about right.

Here what happens in area is that width and height are &u32 not u32, the compiler effectively interprets your code as:

let &Rectangle{ ref width, ref height } = shape;

If you're not using something like rust-analyzer which can surface this information in your editor directly, a common trick is to write something like:

let x: () = var

the compilation error will tell you what the type of var is (unless it's ()).

I though &Shape reference only points to where Shape is in memory, whereas *&Shape is Shape itself.

That is true, however in the context of a pattern that doesn't necessarily mean the structure is moved. Here because the fields of Rectangle are both Copy the compiler can destructure the "owned" struct without needing to move it, it can just copy the fields. Which is essentially what a simple attribute access would do (shape.width is u32).

like image 82
Masklinn Avatar answered Aug 31 '26 23:08

Masklinn


Actually, I have tried this in rust 2021, rust-analyzer told me, I get two reference: wdith and height. So I look at width * height line, there are two reference to u32, and * operator, aka std::ops::Mul have implement multipy of two &u32.

like image 24
Elijah Song Avatar answered Aug 31 '26 22:08

Elijah Song



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!