与方差相关时如何分析泛型寿命

How to analyze generic lifetime when it is relevant to variance

 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

上面的 code snippnet 1 不同于 Rust for Rustacean Ch1 清单 1-11,其中我使用 'a 来替换两个生命周期 'a'b,而这个代码无法编译,而我也说不出原因:(

我可以分析一些简单的代码,例如以下代码(来自 Programming Rust Verson 2 第 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

我分别用 'x'y'r 表示 xyr 的生命周期:

'x 'y 'r
line: from 8 to 18 line: from 11 to 16 line: from 9 to 17

13 行中实例化 s 时,我们需要 'x:'a ('x outlives 'a) 'y:'a ,并且在 14 行中发生赋值 r = s.x ,我们需要 'a:'r 。然而,这是不可能的,因为 'y:'a'a:'r 冲突(参见上面的 table,'y'r 短),因此 rustc 无法找到满足这些冲突条件的通用生命周期 'a 的确定性生命周期。

更新:期待code snippet 1的分析过程和上面类似,或者遇到生命周期问题时的通用推理方法:)

我读过 this article ,知道一些关于 variance 的基本概念,例如 covariance invariancecontravariance 。我觉得我的问题与此有关,但不知道如何使用它来分析 code snippet 1

对了,我还在疑惑掌握lifetime在rust中什么位置才是正确的。如果你知道,请告诉我:),我很感激。

If you find my question irregular, feel free to point it out:)

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.

你走在正确的轨道上,不同之处在于生命周期的差异。 Rust Reference 10.5 Subtyping and Variance里面有个table我觉得有帮助:

Type Variance in 'a Variance in T
&'a T covariant covariant
&'a mut T covariant invariant

在您的第二个代码段中,您的引用是 immutable,这意味着可以根据需要缩短与它们关联的生命周期。对变量 y 的引用不能延长其生命周期,因此必须缩短对 x 的引用。因此,绑定到 r 的引用与 y 的生命周期相关联,因此当您在 y 超出范围后尝试使用 r 时会出现错误。

然而,在第一个片段中,您有一个 mutable 引用 &'a str。如果您查看上面的 table,您会发现 mutable 引用所引用的类型是不变的,并且由于类型本身是 &'a str,这意味着 'a 是不变的。这意味着,与第二个片段不同,编译器 根本无法 缩短 'a 的生命周期。因此,当您尝试使用 s 生成 MutStr 时,编译器会发现您传递的是无法缩短的 &'static str,因此 'a 必须是 'static.但随后它试图调和 'a 也链接到变量 s 而不是 'static,所以你得到错误。