7

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?

Ted Klein Bergman
  • 9,146
  • 4
  • 29
  • 50
yslking
  • 73
  • 4
  • 1
    `()` and `{}` are different themselves, the first just modifies the order of operations, while the second creates a new nested scope. – Netwave Mar 15 '21 at 09:31
  • 1
    @Netwave thanks for your comment. I know `()` and `{}` are conceptually different, but a more precise description (e.g. a list of language constructs that transfer the ownership) will make things more clear. I am sorry that I have tried and did not found such materials existing on the Internet. The language reference definitely describe such stuff but it is too hard for a beginner to read the language reference. – yslking Mar 15 '21 at 09:35
  • [Block Expressions](https://doc.rust-lang.org/stable/reference/expressions/block-expr.html), last paragraph (before the last code snippet). – Masklinn Mar 15 '21 at 10:08
  • [Stuff the Identity Function Does (in Rust)](https://bluss.github.io/rust/fun/2015/10/11/stuff-the-identity-function-does/) – trent Mar 15 '21 at 13:05

1 Answers1

6

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:

Netwave
  • 40,134
  • 6
  • 50
  • 93
  • Thanks for @Netwave 's answer. The following links might be helpful for people with similary confusion with me: 1. https://stackoverflow.com/questions/56807445/what-does-do-in-rust; 2. https://stackoverflow.com/questions/61605289/whats-the-difference-between-mut-unsafe-and-unsafe-mut – yslking Mar 15 '21 at 13:14