0 // code snippet 1
1
2 struct MutStr<'a >{
3 s: &'a mut &'a str,
4 }
5
6 fn main() {
7 let mut s: &'static str = "hello";
8 *MutStr{
9 s: &mut s,
10 }.s = "world";
11 println!("{}", s);
12 }
Rust Playground link of
code snippet 1
The code snippnet 1
above varies from Rust for Rustacean Ch1 listing 1-11 where I use 'a
to replace two lifetimes 'a
and 'b
, and this code can not compile, whereas I can not tell the reason:(
I can analyze some simple code such as the following one (from Programming Rust Verson 2 page 120):
0 // code snippet 2
1
2 struct S<'a> {
3 x: &'a i32,
4 y: &'a i32
5 }
6
7 fn main() {
8 let x = 10;
9 let r;
10 {
11 let y = 20;
12 {
13 let s = S {x: &x, y: &y};
14 r = s.x;
15 }
16 }
17 println!("{}", r);
18 }
Rust Playground link of
code snippet 2
I denote lifetime of x
, y
and r
with 'x
, 'y
and 'r
respectively:
'x | 'y | 'r |
---|---|---|
line: from 8 to 18 | line: from 11 to 16 | line: from 9 to 17 |
When instantiating s
in line 13
, we are requiring 'x:'a ('x outlives 'a)
'y:'a
, and when assignment r = s.x
happens in line 14
, we are requiring 'a:'r
. Nevertheless, this is impossible for the reason that 'y:'a
conflicts with 'a:'r
(see table above, 'y
is shorter than 'r
) so that rustc can not find a deterministic lifetime for generic lifetime 'a
satisfying those conflicting conditions.
Update: I am expecting a analyze process for code snippet 1
similar to the above one, or a general inference method when encountering lifetime problems:)
I have read this article , knowing some basic concepts about variance
, such as covariance
invariance
and contravariance
. And I kind of think my question relate to that, but don't know how to use that to analyze code snippet 1
.
I have read this article, knowing some basic concepts about variance, such as covariance invariance and contravariance. And I kind of think my question relate to that, but don't know how to use that to analyze code snippet 1.
You are on the right track, the difference does lie with lifetime variance. There is a table in the Rust Reference 10.5 Subtyping and Variance that I think is helpful:
Type | Variance in 'a |
Variance in T |
---|---|---|
&'a T |
covariant | covariant |
&'a mut T |
covariant | invariant |
In your second snippet, your references are immutable meaning the lifetime associated with them can be shortened as necessary. A reference to the variable y
cannot lengthen its lifetime so the reference to x
must be shortened. An thus the reference bound to r
is tied to the lifetime of y
and therefore you get an error when you try to use r
after y
has gone out of scope.
In the first snippet however, you have a mutable reference to a &'a str
. If you look at the table above, you'll see that types referenced by a mutable reference are invariant and since the type is itself a &'a str
, that means that 'a
is invariant. This means, unlike in the second snippet, the compiler can not shorten the lifetime of 'a
at all. So when you try to use s
to make a MutStr
, the compiler sees that you're passing a &'static str
that it cannot shorten, so 'a
must be 'static
. But then it tries to reconcile that 'a
is also linked to the variable s
which is not 'static
, so you get the error.