"寿命"关系和实际范围

kir*_*gin 2 lifetime rust

我正在经历传奇的RFC 1214,似乎我错过了一些至关重要的东西.

struct Foo;

struct Bar<'a> {
   foo: &'a Foo
}


fn f<'x, 'y>(_: &'x Foo, _: &'y Bar<'x>)
     where 'y: 'x, 'x: 'y {
}

fn g<'x>(x: &'x Foo) {
   let y = Bar {foo : x};
   f(x, &y);  // ?
}


fn main(){
   let x = Foo;
   g(&x);
}
Run Code Online (Sandbox Code Playgroud)

在这段代码中,我竭尽全力确保'x : 'y不是 'y : 'x.定义x的函数调用定义的函数y,我相信这已经足以保证xoutlives y,但我也在x内部引用y,只是为了确定.

现在,约束条件f是调用此函数可能无效.我的意思是,它可以,当且仅当'x == 'y它,但它完全看起来像x生命严格地长y,因为它在外部范围中定义.

不过,这段代码可以检查和编译.这怎么可能?

huo*_*uon 7

生命周期有变化,也就是说,编译器可以选择缩短a &'a Foo到some 的生命周期&'b Foo.像这样的参考的生命周期意味着Foo至少持续时间'a:更短的寿命仍然满足这种保证.这就是这里发生的事情:'x缩短生命周期以使其具有与&y参考相同的生命周期.

您可以使用不变性来停止此编译:如果'x无法缩短生命周期,则代码将按预期停止编译.

use std::cell::Cell;

struct Foo;

struct Bar<'a> {
   foo: Cell<&'a Foo>
}


fn f<'x, 'y>(_: Cell<&'x Foo>, _: &'y Bar<'x>)
     where 'y: 'x, 'x: 'y {
}

fn g<'x>(x: Cell<&'x Foo>) {
   let y = Bar {foo : x.clone()};
   f(x, &y);  // ?
}


fn main(){
   let x = Foo;
   g(Cell::new(&x));
}
Run Code Online (Sandbox Code Playgroud)
<anon>:16:10: 16:11 error: `y` does not live long enough
<anon>:16    f(x, &y);  // ?
                   ^
<anon>:14:28: 17:2 note: reference must be valid for the lifetime 'x as defined on the block at 14:27...
<anon>:14 fn g<'x>(x: Cell<&'x Foo>) {
<anon>:15    let y = Bar {foo : x.clone()};
<anon>:16    f(x, &y);  // ?
<anon>:17 }
<anon>:15:34: 17:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 15:33
<anon>:15    let y = Bar {foo : x.clone()};
<anon>:16    f(x, &y);  // ?
<anon>:17 }
Run Code Online (Sandbox Code Playgroud)

这里发生的事情Cell<T>是不变的T,因为它是可读写的.这尤其意味着Cell<&'x Foo>不能缩短为Cell<&'y Foo>:用&'y Foo真正的参考'y(即仅持续'y)填充它将意味着一旦细胞离开'y(但仍然在'x),参考是悬空的.


小智 5

以下是结合您解释行为的三件事:

  • 'xf是从一个完全不同的,独立的寿命参数'xg.编译器可以选择不同的具体生命周期来代替每个生命周期.
  • 'x : 'y, 'y: 'x意味着'x == 'y(这不是真正的语法).
  • 如果您有引用,则可以隐式创建另一个具有较短生命周期的引用.考虑例如功能fn mangle_a_string<'a>(_s: &'a str) -> &'a str { "a static string" }

所以发生的事情f(x, &y)是第一个参数被强制转换为具有较短生存期的引用,匹配第二个参数的lifetim,以满足where子句中的边界.