2016-12-26 11 views
7

関連するタイプを使用しているため、Rust 1.14で生涯エラーが発生しました。次の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 
} 

なぜ反復が直接インスタンシエーションと異なるのか分かりません。

+0

私はまだこれを解決しようとしています。しかし、私はあなたが 'into_iter() 'の代わりに' iter() 'を使うことができて、それがうまくいくことを発見しました。 –

答えて

4

use_alphaには、Alphaとその有効期間パラメータの参照に同じ有効期間が使用されています。その寿命パラメータは、ImplTrait::Tの寿命になります。このノートでは、値が削除される順序についてのヒントが表示されています。Implの前にはImplの定義が含まれているため、Alphaの一部が既に削除されていることを意味します。

あなたはuse_alpha中2つの寿命パラメータを使用してこの問題を解決することができます。これは、コンパイラは、タイプごとに異なる寿命を推測することができます

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

+0

それが尋ねられてから4時間後、あなたは数分で答えに私を打ち負かす... – Shepmaster

+2

@Shepmasterようやく! :P –

+0

また、あなたもあなたの投稿や私の編集をお気軽にしてください。私は自分の説明に完全に満足していません - 私はそれを自分自身で100%理解しているかどうか分からないからです。 –