7

関連付けられた型を使用しているため、Rust 1.14 でライフタイム エラーが発生します。これは、次の 2 つの同様のプログラムによって示されます。最初のプログラムはエラーなしでコンパイルされ、2 つ目はライフタイム エラーがあります。

プログラム #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!
    }
}

2 番目のプログラムのコンパイル時エラーは次のとおりです。

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

2 つのプログラムの差分は次のとおりです。

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

唯一の違いは、最初のプログラムを変更して、定義内の型パラメーターの代わりに関連付けられた型を使用するとstruct、有効期間エラーが発生することです。なぜこれが起こるのか分かりません。私が知る限り、関連付けられた型に追加の有効期間制限が発生することはありません。これはすべて単なる'aですが、明らかに Rust コンパイラは同意しません。

2 番目のプログラムの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ますTrait::T。注は、値が削除される順序についてのヒントを提供します。 はの定義の一部であるため、Impl::T前に削除されますが、これは、 の一部がまだ存在している間に既に削除されていることを意味します。ImplImplAlpha

これは、次の 2 つのライフタイム パラメータを使用して修正できますuse_alpha

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

これにより、コンパイラは型ごとに異なる有効期間を推測できます。

于 2016-12-27T02:55:50.110 に答える