7

由于使用了关联类型,我在 Rust 1.14 中遇到了生命周期错误,以下两个类似的程序证明了这一点,第一个编译没有错误,第二个有生命周期错误。

程序 #1 — 编译没有错误

trait Trait<'a> {
    type T;
}

struct Impl;

impl<'a> Trait<'a> for Impl {
    type T = std::marker::PhantomData<&'a ()>;
}

struct Alpha<'a, T: Trait<'a>> {
    _dummy: std::marker::PhantomData<(&'a (), T)>,
}

fn use_alpha<'a>(_: &'a Alpha<'a, Impl>) {}

fn main() {
    for x in Vec::<Alpha<Impl>>::new().into_iter() {
        use_alpha(&x); // <-- ok
    }
}

程序 #2 — 存在生命周期错误

trait Trait<'a> {
    type T;
}

struct Impl;

impl<'a> Trait<'a> for Impl {
    type T = std::marker::PhantomData<&'a ()>;
}

struct Alpha<'a, T: Trait<'a>> {
    _dummy: std::marker::PhantomData<(&'a (), T::T)>,
}

fn use_alpha<'a>(_: &'a Alpha<'a, Impl>) {}

fn main() {
    for x in Vec::<Alpha<Impl>>::new().into_iter() {
        use_alpha(&x); // <-- !error!
    }
}

这是第二个程序的编译时错误:

error: `x` does not live long enough
  --> src/main.rs:20:5
   |
19 |         use_alpha(&x); // <-- !error!
   |                    - borrow occurs here
20 |     }
   |     ^ `x` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

这是两个程序的差异:

 #[derive(Clone)]
 struct Alpha<'a, T: Trait<'a>> {
-    _dummy: std::marker::PhantomData<(&'a (), T)>,
+    _dummy: std::marker::PhantomData<(&'a (), T::T)>,
 }

唯一的区别是通过将第一个程序更改为使用关联类型而不是struct定义中的类型参数,会发生生命周期错误。我不知道为什么会这样。据我所知,关联类型不应该产生任何额外的生命周期限制——这都是 just 'a,但显然 Rust 编译器不同意。

如果我用简单的实例化替换第二个程序main函数中的迭代,那么生命周期错误就会消失。那是:

fn main() {
    let x = Alpha::<Impl> { _dummy: std::marker::PhantomData };
    use_alpha(&x); // <-- ok in both programs
}

我不明白为什么迭代与直接实例化有什么不同。

4

1 回答 1

4

use_alpha中,您对引用Alpha及其生命周期参数使用了相同的生命周期。然后它的生命周期参数变成Impl's的生命周期Trait::T。注释给出了关于值被删除的顺序的提示:因为它是 ' 定义的一部分而Impl::T在之前被删除,但这意味着它的某些部分在它仍然存在时已经被删除。ImplImplAlpha

您可以通过使用以下两个生命周期参数来解决此问题use_alpha

fn use_alpha<'a, 'b>(_: &'a Alpha<'b, Impl>) {}

这将允许编译器为每种类型推断不同的生命周期。

于 2016-12-27T02:55:50.110 回答