1
let mut x = 1;
let a = &mut x;
let b = &mut *a;
*a = 2; // error. b borrows a
*b = 3; // it works! (only without " *a = 2 ")
let mut x = 1;
let b;
{
    let a = &mut x;
    b = &mut *a;
} // a drops here
*b = 2; // it works!

I'm having hard time getting what &*a means, in the point of lifetime. I don't know how *operator is related to lifetimes of variables.

It seems like b is borrowing x and also a, so that not only x(which is *a) cannot be moved or modified but also a cannot be used.

The error message of compiler is : b borrowing a.

So, I ran the second code. In my understanding, borrowed data cannot be reassigned or moved, or dropped. I deliberately made a to drop before b, to make sure that a's lifetime should be longer than b's.

However, second code still works.

So, how can I understand undergoing lifetimes associated with &mut *a?

vallentin
  • 23,478
  • 6
  • 59
  • 81
kwonryul
  • 481
  • 3
  • 10

2 Answers2

0

The important misconception is in your first line of code. The error is not that b borrows a, it's that b borrows *a, meaning it borrows x. Since Rust downgrades and drops references as early as possible, this "double" mutable reference is allowed as long as you don't ever try to use a. However, when using a, the compiler will now warn you that you have a double mutable reference: one borrowing *a (basically x) in the variable a, and one borrowing *a in the variable b.

With that cleared up, your second piece of code makes sense. a can be dropped, because b is just using *a to borrow x, and x has a long enough lifetime to be accessed.

Aplet123
  • 33,825
  • 1
  • 29
  • 55
  • If I change the order of last two lines of first code, it works without an error. If this was just about multiple mutable reference, it wouldn't act like that. – kwonryul Dec 28 '20 at 13:07
  • @kwonryul The key part is the line "Rust downgrades and drops references as early as possible". When you swap the order of the lines, `b` is no longer used after the `*b = 3`, so Rust drops it, leaving only one mutable reference, `a`, allowing it to be used. (Note that this only works because in addition to being able to drop references early, Rust can also shift the starting lifetime of references later if possible, which it is in this case) – Aplet123 Dec 28 '20 at 13:10
  • Same code with ```let b = &mut *a``` changed into ```let b = &mut x``` throws an error. – kwonryul Dec 28 '20 at 13:14
  • @kwonryul Obtaining a second `&mut x` causes multiple mutable borrows, which is not allowed of course. However `&mut *a` causes a reborrow of `x` _through_ `a`, which causes `a` to get borrowed, while allowing `x` to be indirectly mutated through `b`. – vallentin Dec 28 '20 at 17:19
0
let mut x = 1;
let a = &mut x; // now a is the mutable owner of x
let b = &mut *a; // *a -> x so, now b is the mutable owner of x

*a = 2; // it will not work as a is not the current mutable owner of x
*b = 3; // it will work as a is the current mutable owner of x
let mut x = 1;
let b;
{
    let a = &mut x; // now a is the mutable owner of x
    b = &mut *a; // *a -> x so, b is the mutable owner of x
} // a dropped but not x
*b = 2; // it will work because b is the current mutable owner of x and x is still in scope.
vallentin
  • 23,478
  • 6
  • 59
  • 81
  • This runs into the pitfall of my (now deleted) answer, which is that it doesn't explain why [this compiles](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9ff61c254dcc5c5e06602bc6ccb05acd) but [this does not](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=969c460f7d8c2c738368ec50e5821d37). – Aplet123 Dec 28 '20 at 14:11
  • @Aplet123 I've read your answer a few times. Why do you think it doesn't explain why [this compiles](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9ff61c254dcc5c5e06602bc6ccb05acd)? I think it does. – vallentin Dec 28 '20 at 16:51
  • @vallentin It's not necessarily about that code compiling, but about how changing `&mut *a` to `&mut x` magically changes the behavior of the code and stops it from compiling. – Aplet123 Dec 28 '20 at 16:55
  • @Aplet123 Yeah, but I think your answer explained that. The second `&mut x` causes multiple mutable borrows. However `&mut *a` causes a reborrow of `x` _through_ `a`. – vallentin Dec 28 '20 at 17:01