2017-10-24 4 views
3

futuresを使用して非同期操作を試していましたが、tokioクレートは問題ありませんでした。今私は非同期にデータをロードし、次にいくつかの変換を実行するストレージを実装していますが、私のインターフェイスには理解できない生涯の問題があるようです。動作時にライフタイムコンパイラエラーが発生しました。<Future>

これは、同じ症状を示している縮小されたテストコードです。実際の関数本体は常に返すエラーよりも、より合理的なアクションを実行します。私はhyperまたはtokio-postgresは一見持っていたと書かれている

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements 
    --> src/main.rs:36:9 
    | 
36 |   Box::new(result) 
    |   ^^^^^^^^^^^^^^^^ 
    | 
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 34:5... 
    --> src/main.rs:34:5 
    | 
34 |/ fn resolve(&self, key: String) -> Box<Future<Item = Self::ValueType, Error = MyError>> { 
35 | |   let result = self.load(key).and_then(|bytes| self.deserialize(bytes)); 
36 | |   Box::new(result) 
37 | |  } 
    | |_____^ 
note: ...so that the type `futures::AndThen<std::boxed::Box<futures::Future<Error=MyError, Item=std::vec::Vec<u8>>>, std::result::Result<Obj, MyError>, [[email protected]/main.rs:35:46: 35:77 self:&&Storage<Obj>]>` will meet its required lifetime bounds 
    --> src/main.rs:36:9 
    | 
36 |   Box::new(result) 
    |   ^^^^^^^^^^^^^^^^ 
    = note: but, the lifetime must be valid for the static lifetime... 
note: ...so that expression is assignable (expected std::boxed::Box<futures::Future<Error=MyError, Item=Obj> + 'static>, found std::boxed::Box<futures::Future<Error=MyError, Item=Obj>>) 
    --> src/main.rs:36:9 
    | 
36 |   Box::new(result) 
    |   ^^^^^^^^^^^^^^^^ 

前のコード:

extern crate futures; 

use futures::prelude::*; 
use futures::future; 

pub enum MyError { 
    SomeError, 
} 

pub trait KeyValueStore { 
    type ValueType; 

    fn load(&self, key: String) -> Box<Future<Item = Vec<u8>, Error = MyError>>; 
    fn deserialize(&self, serialized_obj: Vec<u8>) -> Result<Self::ValueType, MyError>; 

    fn resolve(&self, key: String) -> Box<Future<Item = Self::ValueType, Error = MyError>>; 
} 

pub struct Storage<Obj> { 
    _unused: std::marker::PhantomData<Obj>, 
} 

impl<Obj: 'static> KeyValueStore for Storage<Obj> { 
    type ValueType = Obj; 

    fn deserialize(&self, serialized_obj: Vec<u8>) -> Result<Self::ValueType, MyError> { 
     Err(MyError::SomeError) 
    } 

    fn load(&self, key: String) -> Box<Future<Item = Vec<u8>, Error = MyError>> { 
     Box::new(future::err(MyError::SomeError)) 
    } 

    fn resolve(&self, key: String) -> Box<Future<Item = Self::ValueType, Error = MyError>> { 
     let result = self.load(key).and_then(|bytes| self.deserialize(bytes)); 
     Box::new(result) 
    } 
} 

コンパイラは、次の寿命の問題で、このサンプルコードを拒否します同じロジックですが、このようなエラーは発生しませんでした。私はどこで生涯が参照なしでここで間違っていたか見ることさえできません。私の腸の感覚は、何となく一般的なObjパラメータに関係していると言います。静的寿命の制限は正しく感じません。

コンパイルエラーの原因は何ですか?

答えて

2

self.deserializeは、&selfパラメータからresolveまでの有効期間が必要です。ボックス化されたFutureの場合は'staticの有効期間が必要です。結果はBox<Future<..>>となります。

あなたはBox<Future<..> + 'a>と箱入りの将来のための生涯の要件オーバーライドすることができます('aselfパラメータの寿命であり、あなたが特性におよび実装にresolve署名を変更する必要があると思います)。通常のFutureベースのイベントループでは、実行する必要があるFutureの寿命が'staticになるため、結果はあまりありません。

代わりにdeserializeを「静的メソッド」、つまり&self引数を削除し、代わりにSelf::deserializeを呼び出して解決できます。

特性を型として使用する場合のデフォルトの有効期間要件(この場合は'static)は、参考文献のTrait objectsに記載されています。

+0

あなたはそうです、私は多少の生涯を見過ごしました。私もこのアイデアを持っていましたが、私の元の文脈ははるかに複雑で、おそらくまだいくつかのエラーが残っています。私は問題のあることは、コンパイラのメッセージでは何もこのエラーの原因として自己を参照していないと思うので、問題がどこにあるかを推測することしかできません。 それを指摘してくれてありがとう! –

+1

「ボックス化できません」私はtokioについては何も知りませんが、 'Box <'a + Future <...>>'仕事はできませんか? – trentcl

+0

あなたはおそらく正しいですが、生涯制限された未来はあまり役に立たないでしょう。もう一度見ようとします。 – Stefan

関連する問題