fn main() {
// block1: fails
{
let mut m = 10;
let n = {
let b = &&mut m;
&**b // just returning b fails
};
println!("{:?}", n);
}
// block2: passes
{
let mut m = 10;
let n = {
let b = &&m;
&**b // just returning b fails here too
};
println!("{:?}", n);
}
}
block1 fails with the error:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:7:22
|
7 | let b = &&mut m;
| ^^^^^^ temporary value does not live long enough
8 | &**b // just returning b fails
9 | };
| - temporary value dropped here while still borrowed
...
12 | }
| - temporary value needs to live until here
Am I correct in assuming that the inner immutable reference is extended beyond the block2 scope, whereas in block1, the inner mutable reference is always dropped even if there is an outer reference to it?
Back to Rust. A mutable reference is a borrow to any type mut T , allowing mutation of T through that reference. The below code illustrates the example of a mutable variable and then mutating its value through a mutable reference ref_i .
First, we change s to be mut . Then we create a mutable reference with &mut s where we call the change function, and update the function signature to accept a mutable reference with some_string: &mut String . This makes it very clear that the change function will mutate the value it borrows.
What is Borrowing? When a function transfers its control over a variable/value to another function temporarily, for a while, it is called borrowing. This is achieved by passing a reference to the variable (& var_name) rather than passing the variable/value itself to the function.
A reference represents a borrow of some owned value. You can get one by using the & or &mut operators on a value, or by using a ref or ref mut pattern.
It is sufficient here to think of a mutable borrow as a non-Copy
struct (S
in the snippets below) which takes ownership of the referenced value. This model represents the exclusive nature of a mutable borrow.
Reasoning based on this model: In block2 n
is a reference to the original m
, while in block1 n
would end up being a reference to a copy of m
owned by the mutable borrow. In both blocks the inner reference is dropped at the end of the let-block, but only in block1 this causes a problem, because in block1 the target of the reference for n
is still owned by the inner reference when this inner reference is dropped.
struct S { m: i32 }
let mut m = 10;
let n = {
let s = S { m };
let b = &s;
&(*b).m
}; // s is dropped
println!("{:?}", n);
In the snippet above s
takes ownership of a copy of m
. The reference n
would point to that copy of n
which is dropped when s
is dropped - not allowed. If m
was non-Copy, m
would be moved into s
, which would have the same implications.
In block2 the original m
is borrowed directly without copying it. If you force a copy, you will get the same error as for block1:
let mut m = 10;
let n = {
let m2 = m;
let mut a = &m2;
let b = &a;
&**b
};
println!("{:?}", n);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With