我应该如何描述泛型类型的生命周期关系?

Sho*_*ada 2 rust

假设有一个典型的 GAT 示例,引用迭代器:

#![feature(generic_associated_types)]
use std::ops::Deref;

trait MyIterator {
    type Item<'a>
    where
        Self: 'a;
    fn next(&mut self) -> Self::Item<'_>;
}
Run Code Online (Sandbox Code Playgroud)

例如,我可以将其实现为Box<T>.

// This is OK
impl<U> MyIterator for Box<U> {
    type Item<'a> = &'a U
    where
        Self: 'a;
    fn next(&mut self) -> Self::Item<'_> {
        <Box<T> as Deref>::deref(self)
    }
}
Run Code Online (Sandbox Code Playgroud)

但当我用Deref特质概括它时却不是:

// error[E0309]: the parameter type `U` may not live long enough
impl<T, U> MyIterator for T
where
    T: Deref<Target = U>,
{
    type Item<'a> = &'a U
    where
        Self: 'a;
    fn next(&mut self) -> Self::Item<'_> {
        <T as Deref>::deref(self)
    }
}
Run Code Online (Sandbox Code Playgroud)

根据我的理解,在这种Box<T>情况下,编译器以某种方式知道该类型U的所有者Box<U>,因此U可以保证其寿命比Box<U>. 所以如果Box<U>: 'a那么编译器可以说U: 'a.

Deref<Target=U>但即使Deref有方法,这种逻辑也不适用于这种情况deref(&self) -> &Self::Target,这意味着对于任何生命周期T: 'athen U: 'a

我如何告诉编译器后一种情况实际上是安全的?

Pet*_*all 6

问题是您将 TU设置为独立的类型参数,但实际上U始终由 唯一确定T

使用Deref::Target类型T代替才是您真正的意思,并且也使类型检查器更容易推断生命周期。

impl<T> MyIterator for T
where
    T: Deref,
{
    type Item<'a> = &'a <T as Deref>::Target
    where
        Self: 'a;
    fn next(&mut self) -> Self::Item<'_> {
        <T as Deref>::deref(self)
    }
}
Run Code Online (Sandbox Code Playgroud)