为什么一个程序在明显的生命周期不匹配的情况下仍能编译?
Why does a program compile despite an apparent lifetime mismatch?
给定以下 Rust 程序:
struct Value<'v>(&'v ());
struct Container {}
impl Container {
fn get<'v>(&'v self) -> Value<'v> {
todo!()
}
fn set<'v>(&'v self, x: Value<'v>) {
todo!()
}
}
fn convert<'v1, 'v2>(x: &'v1 Container, env: &'v2 Container) {
let root: Value<'v2> = env.get();
x.set(root);
}
我希望 convert
是一个编译时错误,因为 Value<'v2>
被传递给 x.set()
,它需要类型 Value<'v1>
的值 - 但它编译成功。 'v1
和 'v2
之间没有子类型关系。 Rust 如何推断出令人满意的生命周期?
总是允许编译器以更短的生命周期重新借用。
在这种情况下,会发生什么:
fn convert<'v1, 'v2>(x: &'v1 Container, env: &'v2 Container) {
let root: Value<'v2> = env.get();
x.set(root);
}
编译器是否重新借用 x
(又名 (&*x)
),其生命周期为 'v3
,短于 'v2
,由于(推断的)方差,这是允许的Value<'v>
(匹配 &'v T
)。
可以通过更改内部值来更改 Value<'v>
的推断方差:
&'v ()
(当前)是协变的。
Cell<&'v ()>
是 不变的。
fn (&'v ()) -> ()
是逆变,协变. 的逆
使用不变量 Value<'v>
会阻止将生命周期与新生命周期统一,而使用逆变 Value<'v>
只允许使用 更大的 统一生命周期。
给定以下 Rust 程序:
struct Value<'v>(&'v ());
struct Container {}
impl Container {
fn get<'v>(&'v self) -> Value<'v> {
todo!()
}
fn set<'v>(&'v self, x: Value<'v>) {
todo!()
}
}
fn convert<'v1, 'v2>(x: &'v1 Container, env: &'v2 Container) {
let root: Value<'v2> = env.get();
x.set(root);
}
我希望 convert
是一个编译时错误,因为 Value<'v2>
被传递给 x.set()
,它需要类型 Value<'v1>
的值 - 但它编译成功。 'v1
和 'v2
之间没有子类型关系。 Rust 如何推断出令人满意的生命周期?
总是允许编译器以更短的生命周期重新借用。
在这种情况下,会发生什么:
fn convert<'v1, 'v2>(x: &'v1 Container, env: &'v2 Container) {
let root: Value<'v2> = env.get();
x.set(root);
}
编译器是否重新借用 x
(又名 (&*x)
),其生命周期为 'v3
,短于 'v2
,由于(推断的)方差,这是允许的Value<'v>
(匹配 &'v T
)。
可以通过更改内部值来更改 Value<'v>
的推断方差:
&'v ()
(当前)是协变的。Cell<&'v ()>
是 不变的。fn (&'v ()) -> ()
是逆变,协变. 的逆
使用不变量 Value<'v>
会阻止将生命周期与新生命周期统一,而使用逆变 Value<'v>
只允许使用 更大的 统一生命周期。