Search code examples
rustownership

Why does `a` keeps the ownership after `let b = &*&a;` in Rust?


I found it confusing that &(*&a) and &{*&a} behave differently.

To be detailed, the following code failed to compile:

struct CanNotCopy;
fn main(){
    let a = CanNotCopy;
    &{*&a};
    let c = a;
}

And the following code compiled:

struct CanNotCopy;
fn main(){
    let a = CanNotCopy;
    &(*&a); // or &*&a;
    let c = a;
}

What is the semantical difference between the above codes?

Which are language constructs that lead to the transfer of ownership, precisely?


Solution

  • By using {} you are moving a into a new scope, which then you play referencing and dereferencing. It can also be simplified to:

    struct CanNotCopy;
    fn main(){
        let a = CanNotCopy;
        {a};
        let c = a;
    }
    

    You would be getting the same problem, now lets move to the other problem. Imagine you have a reference before the scope:

    struct CanNotCopy;
    fn main(){
        let a = CanNotCopy;
        let aa = &a;
        {aa};
        let c = a;
    }
    

    This works, because we just move the reference and not the original object itself.

    How about the operations with * and & then:

    struct CanNotCopy;
    fn main(){
        let a = CanNotCopy;
        let aa = &a;
        &{*aa};
        let c = a;
    }
    

    We got to a cannot move out of *aa which is behind a shared reference because of the same reasons above showed.

    We do not have that error with () because we are working within the same scope hence nothing is really moving there.

    EDIT (taken from comments), Some related questions: