Rust模板参数的生命周期不能在trait闭包内移动

y4ekin9u  于 2023-03-23  发布在  其他
关注(0)|答案(1)|浏览(130)

我在一些博客文章中发现了以下特质定义。

trait HasIter<'a, _Dummy=&'a Self, _Item = &'a <Self as IntoIterator>::Item>: IntoIterator 
{
    type Iter: Iterator<Item = _Item>;
}

我尝试了一下,并决定在Iter的声明中替换_type,如下所示:

trait HasIter<'a, _Dummy=&'a Self>: IntoIterator 
{
    type Iter: Iterator<Item = &'a <Self as IntoIterator>::Item>;
}

我一这么做,编译器就会抱怨

the associated type `<Self as IntoIterator>::Item` may not live long enough

我想我错过了Rust中的一些生命周期概念。这里到底有什么区别呢?既然我们在两种情况下都附加了相同的生命周期'a,为什么我们不大声地这样做呢?

os8fio9y

os8fio9y1#

在第二个例子中,你有&'a <Self as IntoIterator>::Item,但是如果<Self as IntoIterator>::Item引用的类型包含的引用没有'a那么长怎么办?引用的有效期不能超过它指向的数据。编译器告诉你如何解决这个问题:

= help: consider adding an explicit lifetime bound `<Self as IntoIterator>::Item: 'a`...
  = note: ...so that the reference type `&'a <Self as IntoIterator>::Item` does not outlive the data it points at

果然,这编译:

trait HasIter<'a, _Dummy=&'a Self>: IntoIterator
where <Self as IntoIterator>::Item: 'a
{
    type Iter: Iterator<Item = &'a <Self as IntoIterator>::Item>;
}

在第一个例子中没有得到相同错误的原因是因为_Item = &'a <Self as IntoIterator>::Item指定了一个泛型类型,并将提供的类型 * 作为默认值。* 默认值并不一定在所有情况下都有意义,因为如果<Self as IntoIterator>::Item: 'a不为true,它可以在实现HasIter的站点被拒绝。相反,第二个例子中的Iter上的界限必须对trait的 * 所有可能的实现 * 保持。

相关问题