我正在经历传说中的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
的函数,我相信这已经足以保证x
比y
,但我还在y
中放置了对x
的引用,只是为了确定。
现在,f
中的约束使得此函数的调用不可能有效。我的意思是,它可以,当且仅当 'x == 'y
时,但它看起来完全像 x
比 y
活得更久>,因为它是在外部范围中定义的。
然而,此代码会进行类型检查和编译。这怎么可能?
最佳答案
一生有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/