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.
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:
'aT&'a T&'a mut TIn your second snippet, your references are immutable meaning the lifetime associated with them can be shortened as necessary. A reference to the variable
ycannot lengthen its lifetime so the reference toxmust be shortened. An thus the reference bound toris tied to the lifetime ofyand therefore you get an error when you try to userafteryhas 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'ais invariant. This means, unlike in the second snippet, the compiler can not shorten the lifetime of'aat all. So when you try to usesto make aMutStr, the compiler sees that you're passing a&'static strthat it cannot shorten, so'amust be'static. But then it tries to reconcile that'ais also linked to the variableswhich is not'static, so you get the error.