Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cannot assign to `*x` because it is borrowed

My erroneous code snippet and compiler error info:

// code snippet 1:

0 fn main() {
1     let mut x: Box<i32> = Box::new(4);
2     let r: &Box<i32> = &x;
3     *x = 8;
4     println!("{}", r);
5 }
// compiler error info: 

error[E0506]: cannot assign to `*x` because it is borrowed
 --> src/main.rs:3:4
  |
2 |     let r = &x;
  |             -- borrow of `*x` occurs here
3 |     *x = 8;
  |     ^^^^^^ assignment to borrowed `*x` occurs here
4 |     println!("{}", r);
  |                    - borrow later used here

For more information about this error, try `rustc --explain E0506`.

The following code won't compile, which makes quite senses to me cause we cannot invalidate the reference r .

// code snippet 2:

0 fn main() {
1     let mut x: i32 = 0;
2     let r: &i32 = &x;
3     x = 1;
4     println!("{}", r);
5 }

But the compiler error info of code snippet1 doesn't make too much sense to me.

x is a pointer on the stack pointing to a heap memory segment whose contents is 4 , reference r only borrows x (the pointer not the heap memory segment) , and in line 3 *x = 8; , what we did here is to alter the memory on the heap (not the pointer on the stack) . Change happens on the heap , while reference is only relevant to the stack, they do not interrelate.

This question is kind of picking a quarrel, but I do not mean to argue for the sake of argument.

If you found my question irregular, feel free to point it out :)

like image 962
Steve Lau Avatar asked Dec 04 '25 06:12

Steve Lau


1 Answers

Change happens on the heap , while reference is only relevant to the stack, they do not interrelate.

That does not matter, because the type system doesn't work with that "depth" of information.

As far as it's concerned, borrowing x is borrowing the entirety of x up to any depth, and so any change anywhere inside x is forbidden.

For type checking purposes, this is no different than if x were a Box<Vec<_>>, and r were be actively used for iteration, leading any update to the inner vector to possibly invalidate the iterator.

(also type-wise *x = 8 does require first taking a unique reference to the box itself, before "upgrading" it to a unique reference to the box' content, as you can see from the trait implementation)

like image 198
Masklinn Avatar answered Dec 07 '25 03:12

Masklinn