为什么从特征对象的 impl 中的方法返回的引用需要静态生命周期?
Why is 'static lifetime required for references returned from methods in an impl for a trait object?
当我不在此代码中包含 + 'static
时,rustc
会抱怨。为什么?
// adapted from rust-analyzer https://github.com/rust-analyzer/rust-analyzer
trait Upcast<T: ?Sized> {
fn upcast(&self) -> &T;
}
trait DefDatabase {}
trait HirDatabase: Upcast<dyn DefDatabase> {}
struct RootDatabase{}
impl Upcast<dyn DefDatabase> for RootDatabase {
fn upcast(&self) -> &(dyn DefDatabase + 'static) {
&*self
}
}
`impl` item signature doesn't match `trait` item signature
expected `fn(&RootDatabase) -> &(dyn DefDatabase + 'static)`
found `fn(&RootDatabase) -> &dyn DefDatabase`
the lifetime requirements from the `impl` do not correspond to the
requirements in the `trait`
verify the lifetime relationships in the `trait` and `impl` between the
`self` argument, the other inputs and its output
为什么需要 'static
生命周期?
看来 dyn
对这个例子来说是必不可少的。 rustc
没有抱怨这个 impl,它没有提到 'static
:
impl Upcast<RootDatabase> for RootDatabase {
fn upcast(&self) -> &Self {
self
}
}
您需要明确说明 Trait 对象 &'dyn DefDatabase
的生命周期,以便借用检查器知道后面的结构持有的任何引用的生命周期指针是。 'static
是默认的,如果你没有定义它,或者它不能从上下文中确定。有关详细信息,请参阅 Rust 语言参考中的 default trait object lifetimes。
为您的 Upcast
特征定义添加生命周期允许您删除 'static
。
trait Upcast<'a, T: ?Sized + 'a> {
fn upcast(&self) -> &T; // 'a is not necessary here because the generic `T` may or may not be a trait object
}
trait DefDatabase {}
struct RootDatabase{}
impl DefDatabase for RootDatabase {}
impl<'a> Upcast<'a, dyn DefDatabase> for RootDatabase {
fn upcast(&self) -> &(dyn DefDatabase + 'a) { // now we can replace 'static with 'a
&*self
}
}
impl<'a> Upcast<'a, RootDatabase> for RootDatabase {
fn upcast(&self) -> &Self { // &Self is not a trait object, so no trait object lifetime is necessary
self
}
}
编辑:
需要注意的是这个生命周期是不是引用到trait对象的生命周期,可以单独声明和是为什么生命周期必须用括号来消除歧义的原因。
impl<'a> Upcast<'a, dyn DefDatabase> for RootDatabase {
fn upcast<'b>(&'b self) -> &'b (dyn DefDatabase + 'a) { // 'b is elided
&*self
}
}
当我不在此代码中包含 + 'static
时,rustc
会抱怨。为什么?
// adapted from rust-analyzer https://github.com/rust-analyzer/rust-analyzer
trait Upcast<T: ?Sized> {
fn upcast(&self) -> &T;
}
trait DefDatabase {}
trait HirDatabase: Upcast<dyn DefDatabase> {}
struct RootDatabase{}
impl Upcast<dyn DefDatabase> for RootDatabase {
fn upcast(&self) -> &(dyn DefDatabase + 'static) {
&*self
}
}
`impl` item signature doesn't match `trait` item signature
expected `fn(&RootDatabase) -> &(dyn DefDatabase + 'static)`
found `fn(&RootDatabase) -> &dyn DefDatabase`
the lifetime requirements from the `impl` do not correspond to the
requirements in the `trait`
verify the lifetime relationships in the `trait` and `impl` between the
`self` argument, the other inputs and its output
为什么需要 'static
生命周期?
看来 dyn
对这个例子来说是必不可少的。 rustc
没有抱怨这个 impl,它没有提到 'static
:
impl Upcast<RootDatabase> for RootDatabase {
fn upcast(&self) -> &Self {
self
}
}
您需要明确说明 Trait 对象 &'dyn DefDatabase
的生命周期,以便借用检查器知道后面的结构持有的任何引用的生命周期指针是。 'static
是默认的,如果你没有定义它,或者它不能从上下文中确定。有关详细信息,请参阅 Rust 语言参考中的 default trait object lifetimes。
为您的 Upcast
特征定义添加生命周期允许您删除 'static
。
trait Upcast<'a, T: ?Sized + 'a> {
fn upcast(&self) -> &T; // 'a is not necessary here because the generic `T` may or may not be a trait object
}
trait DefDatabase {}
struct RootDatabase{}
impl DefDatabase for RootDatabase {}
impl<'a> Upcast<'a, dyn DefDatabase> for RootDatabase {
fn upcast(&self) -> &(dyn DefDatabase + 'a) { // now we can replace 'static with 'a
&*self
}
}
impl<'a> Upcast<'a, RootDatabase> for RootDatabase {
fn upcast(&self) -> &Self { // &Self is not a trait object, so no trait object lifetime is necessary
self
}
}
编辑:
需要注意的是这个生命周期是不是引用到trait对象的生命周期,可以单独声明和是为什么生命周期必须用括号来消除歧义的原因。
impl<'a> Upcast<'a, dyn DefDatabase> for RootDatabase {
fn upcast<'b>(&'b self) -> &'b (dyn DefDatabase + 'a) { // 'b is elided
&*self
}
}