Run the following code:
struct B<'a> {
data: &'a mut &'a str,
}
pub fn test_1() {
let mut s = "hello";
*B {
data: &mut s,
}.data = "world";
println!("s: {}", s);
}
I got the following error:
error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
--> src\test_ref.rs:14:23
|
12 | data: &mut s,
| ------ mutable borrow occurs here
13 | }.data = "world";
14 | println!("s: {}", s);
| ^
| |
| immutable borrow occurs here
| mutable borrow later used here
The same goes for the following:
pub fn test_1() {
let mut s = "hello";
{
*B {
data: &mut s,
}.data = "world";
}
println!("s: {}", s);
}
error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
--> src\test_ref.rs:28:23
|
25 | data: &mut s,
| ------ mutable borrow occurs here
...
28 | println!("s: {}", s);
| ^
| |
| immutable borrow occurs here
| mutable borrow later used here
But when I use two lifetime, the compilation passed.
struct A<'a, 'b> {
data: &'a mut &'b str,
}
pub fn test() {
let mut s = "hello";
let a = A {
data: &mut s,
};
*a.data = "world";
println!("s: {}", s);
}
Now I want to know why the first piece of code has not been compiled and the second piece of code has passed. In the second piece of code, there is only one more lifetime annotation?
I think in the first test, only one of the lifetime is 'a
, according to &'a mut T
in 'a
is covariant, and T
is invariant, so in finally data: &'a mut &'a str
lifetime 'a
is 'static
, 'static
means that at all times.
In the last test, 'a
in data: &'a mut &'b str
due to 'a
covariance Corresponds to a lifetime less than s
, so eventually s
can be referenced again.
Variance of types is automatically determined as follows:
Type
Variance in 'a
Variance in T
&'a T
covariant
covariant
&'a mut T
covariant
invariant
https://doc.rust-lang.org/reference/subtyping.html#variance
The following code can also be compiled (I removed the mut
) :
struct B<'a> {
data: &'a &'a str,
}
pub fn test_1() {
let mut s = "hello";
{
let x = B {
data: &s,
} ;//.data = "world";
}
println!("s: {}", s);
}
In this example 'a
is covariant, because [&'a T
covariant
covariant
], So 'a
is no longer 'static
: 'static
covariant to 'a
.