我正在使用futures和tokio机箱进行异步操作的实验,没有问题。现在,我正在实现一个存储,它异步加载数据,然后执行一些转换,但我的接口似乎存在一些无法理解的终身问题。
这是一个显示相同症状的简化测试代码;真正的功能体执行比总是返回错误更合理的操作:
extern crate futures; // v0.1 (old)
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)
}
}编译器拒绝包含以下生存期问题的示例代码:
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>, [closure@src/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)
| ^^^^^^^^^^^^^^^^我以前用hyper或tokio-postgres编写的代码似乎具有相同的逻辑,但从未产生过这样的错误。如果没有推荐信,我甚至都看不出这里的生活会出什么问题。我的直觉是,它在某种程度上与通用的Obj参数有关,静态生存期限制感觉不正确。
是什么情况导致编译错误?
发布于 2017-10-24 19:42:02
self in self.deserialize需要从&self参数到resolve的生存期;不能将结果装箱为Box<Future<..>>,这需要为装箱Future设置'static生存期。
您可以用Box<Future<..> + 'a>覆盖装箱未来的生存期要求(其中'a是self参数的生存期;您需要在特征和实现中更改resolve签名);但是对结果没有什么可做的,因为通常的Future-based事件循环需要运行Future的'static生存期。
相反,您可以通过使deserialize成为一个“静态方法”来解决这个问题,即删除&self参数并通过Self::deserialize调用它。
当使用特征作为类型时,默认的生存期要求(在本例中为'static)在引用中特征对象中记录。
https://stackoverflow.com/questions/46917486
复制相似问题