rust - “outlives” 关系和实际范围

标签 rust lifetime

我正在经历传说中的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);
}

在这段代码中,我竭尽全力确保 'x : 'y不是 'y : 'x。定义x的函数调用定义y的函数,我相信这已经足以保证xy,但我y 中放置了对x 的引用,只是为了确定。

现在,f 中的约束使得此函数的调用不可能有效。我的意思是,它可以,当且仅当 'x == 'y 时,但它看起来完全像 xy 活得更久>,因为它是在外部范围中定义的。

然而,此代码会进行类型检查和编译。这怎么可能?

最佳答案

一生有variance ,也就是说,编译器可以选择缩短 &'a Foo 的生命周期给一些&'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));
}
<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 }

这里发生的是Cell<T>T 中不变, 因为它是可读可写的。这特别意味着 Cell<&'x Foo>不能缩短为 Cell<&'y Foo> : 用引用填充它 &'y Foo那是真的'y (即只持续 'y )将意味着一旦单元格离开 'y 引用就会悬空(但仍在 'x 中)。

关于rust - “outlives” 关系和实际范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35050159/

相关文章:

rust - 当闭包包含复杂的生命周期关系时,无法为函数构建等效闭包

rust - 我如何在运行时解释或评估 Rust?

rust - 将特征实现从&T推广到AsRef <T>的生命周期

multithreading - 线程引用需要静态生命周期?

rust - 值在明确的生命周期内不会存在足够长的时间,但在省略时会存在足够长的时间

c - 堆变量是全局变量,什么是堆变量的范围和生命周期

rust - 如何引用可变切片

rust - 如何在 Serum Anchor 中签署代币交易

performance - 为什么计时器显示的内容如此违反直觉?

rust - 特征的生命周期作为返回值