2

我正在尝试使用在中创建的结构main()并将其传递给返回 boxed 的函数Future。但是,我遇到了生命周期和借贷问题,似乎无法干净地解决这个问题。

这是我的结构和功能:

extern crate futures; // 0.1.21
extern crate tokio_core; // 0.1.17

use futures::{future::ok, Future};

pub struct SomeStruct {
    some_val: u32,
}

impl SomeStruct {
    pub fn do_something(&self, value: u32) -> u32 {
        // Do some work
        return self.some_val + value;
    }
}

fn main() {
    let core = tokio_core::reactor::Core::new().unwrap();
    let my_struct = SomeStruct { some_val: 10 };

    let future = get_future(&my_struct);
    core.run(future);

    let future2 = get_future(&my_struct);
    core.run(future2);
}

fn get_future(some_struct: &SomeStruct) -> Box<Future<Item = u32, Error = ()>> {
    let fut = ok(20).and_then(|val| {
        let result = some_struct.do_something(val);
        ok(result)
    });
    Box::new(fut)
}

编译时出现以下错误:

error[E0621]: explicit lifetime required in the type of `some_struct`
  --> src/main.rs:33:5
   |
28 | fn get_future(some_struct: &SomeStruct) -> Box<Future<Item = u32, Error = ()>> {
   |               ----------- consider changing the type of `some_struct` to `&'static SomeStruct`
...
33 |     Box::new(fut)
   |     ^^^^^^^^^^^^^ lifetime `'static` required

我想发生错误是因为SomeStruct在s 范围内Future使用并且可能在main()s 范围之外使用,因此编译器要求我将生存期更改为'static. 这是我到目前为止尝试的(不成功):

  • 将生命周期更改'static为编译器建议的,这会在main().
  • val按照编译器的建议添加移动ok(20).and_then(move |val| {,这会在第二次调用get_future().
  • 使用lazy_static板条箱显式初始化SomeStruct为静态(如此处所建议),但是我在尝试时遇到了宏错误。

整个例子可以在这里找到。我省略了一些细节来创建一个最小的例子。使用tokio-core和会出现问题futures = "0.1"。不幸的是,由于依赖另一个库,迁移到版本"0.2"不是一种选择。

4

1 回答 1

3

默认情况下,返回一个装箱的 trait 对象有一个'static边界。按照编译器的建议执行并提供明确的生命周期,但不是'static

fn get_future<'a>(some_struct: &'a SomeStruct) -> Box<dyn Future<Item = u32, Error = ()> + 'a> {
    let fut = future::ok(20).and_then(move |val| {
        let result = some_struct.do_something(val);
        future::ok(result)
    });
    Box::new(fut)
}

您还必须使用move将所有权转移some_struct到闭包并更改core为可变的。您还应该处理由core.run.

对于提供的示例,您还可以返回impl Future

fn get_future<'a>(some_struct: &'a SomeStruct) -> impl Future<Item = u32, Error = ()> +'a {
    future::ok(20).and_then(move |val| {
        let result = some_struct.do_something(val);
        future::ok(result)
    })
}

也可以看看:

于 2018-06-18T18:59:22.373 回答