Copy a variable which is immutable referenced is impossible in Move?

My move code is:

let a: u64;
let b: &u64;
let c: u64;

a = 1;
b = &a;
c = copy(a);

return;

and compiler complains that ‘Failed to verify program: [VMStatus { major_status: COPYLOC_EXISTS_BORROW_ERROR …’. But in my opinion, copy( indeed the CopyLoc instruction) just copies value of the variable to stack, so I guess it doesn’t matter that whether there are references to the variable or not. Could anyone tell me the meaning of this design in Move?

Thanks!

1 Like

Good find!

Could anyone tell me the meaning of this design in Move?

For the general design in Move, mutable borrows grant “ownership” to a degree over the location they are borrowing. For example

struct T { v: u64 }
...
t_ref : &mut T;
let v_ref = &mut t_ref.v;
let copy_t = *t_ref; // ERROR cannot modify 't_ref' as it is still being mutably borrowed

In short, you can only mutate/read from a mutable reference when it is not being borrowed. This is due to the fact that conceptually, any reference that is mutably borrowing “owns” that location until it is done updating. This is more of a design decision to keep code sane rather than being directly related to soundness.

However, you can read from a reference if it is only being immutably borrowed.
For example

t_ref : &mut T;
let v_ref = &t_ref.v;
let copy_t = *t_ref; // Valid! v_ref is immutable so the read is ok

so I guess it doesn’t matter that whether there are references to the variable or not

For local variables, this same concept of ownership persists. If there are mutable borrows outstanding on the local, it cannot be read from (i.e. it cannot be copy-ied)

However! This is a great example that you have found, since b is only immutably borrowing a. So it makes sense to allow a to be copied. We have been doing a lot of updates to borrow checking recently, and this case got overlooked. Thanks for the find! We will likely be relaxing this rule and allowing copy if all outstanding borrows are immutable

2 Likes