I read this Unifying borrow and reborrow (conceptually) via access tutorial, and I think it is very useful to understand the rule about general borrowing(including reborrowing). It introduced two principles with that:
- Access of values may be bororwed, according to the diagram above
- When a value is moved, assigned or is dropping out of scope, it must take back all of its access.
It seems an oversight that the rule didn't talk about borrowing/reborrowing, even though the topic mentioned them in the comments of the examples.
I think for borrowing/reborrowing, we may say
- When a value is borrowed/reborrowed immutably, it must take back its write access if it ever had.
- When a value is borrowed/reborrowed mutably, it must take back all of its access.
- No requirement is imposed if the access is to a static value.
let mut i = 0;
let mrf = & mut i;
let rf = &i; // i should take back its write access since it ever had, hence mrf should drop here
println!("{mrf}"); // error
let mut i = 0;
let mrf = & mut i;
let reborrow = & mut *mrf;
let im_rf = &*reborrow;
let m_rf = & mut *reborrow; // mutably reborrowed here, so `reborrow` should take back all of its access(including read access), hence `im_rf` should drop here
println!("{im_rf}"); // error
Finally, if a value didn't ever have the write access and it is borrowed/reborrowed immutable, no requirement will be imposed.
I think this augment should complete the "Unifying borrow and reborrow (conceptually) via access" principle. The exception is access the static value seems not to be governed by these rules.
static mut i:i32 = 0;
let mrf = unsafe {
& mut i
};
let rf = unsafe {
&i
};
println!("{mrf}"); //Ok
The example would have been an error if i
had declared a non-static.
Update
Accesses are categorized to
1. move access
2. deallocation access
- owner access
- write access
- read access
Only read and write access can be (re)borrowed and the borrowee shall have the access it borrows. Borrowing read access borrows the copied one. Borrowing the write access transfers the access from borrowee to the borrower.
For any operation, the following rules are required:
- For the
move
(semantically) ordestruction
operation, the operated value must at least have{move, deallocation}
{ owner }
accesses.- For the assignment operation, the (LHS)assigned value must at least have
{ write }
access.- For a read operation, the value must at least have
{read}
access.
For a value, they have the accesses as the following:
- The owner value has
{owner, write, read}
accesses to the value.- The mutable borrowing value has
{ write, read }
accesses to the referent.- The immutable borrowing has only
{ read }
accesses to the referent.
- When a value is moved(semantically), assigned, or is dropping out of scope, it must take back all of the accesses for which it, its fields(if any), and the value of which it is a field(if any) have borrowed
- When a value is borrowed/reborrowed immutably, it must take back the write access if it and its fields(if any) ever had(i.e. has been borrowed).
- When a value is borrowed/reborrowed mutably, it must take back all of the access it and its fields(if any) has borrowed.
All accesses mentioned in the above list refer to:
When the value is borrowed, the accesses to the valueWhen the value is reborrowed, the accesses to the referent of the valueWhen the borrowee tasks back the access, the borrower that borrows the access from the borrowee gives back that access. [Note: "borrowee" means the lender or the value from which the borrower borrows the access].
Reborrow occurs when we want to acquire access from a borrowing value
B
to access the referent ofB
.