在盒装的未来使用引用变量时“需要明确的生命周期”

时间:2018-06-18 18:06:35

标签: rust future lifetime borrowing rust-tokio

我正在尝试使用在main()中创建的结构并将其传递给返回框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中使用Future并且可能在main()范围之外使用,因此编译器要求我将生命周期更改为{{1 }}。这是我到目前为止尝试过的(不成功):

  • 根据编译器的建议将生命周期更改为'static,这会在'static中产生借用问题。
  • 按照编译器的建议添加main()移动val,这会在ok(20).and_then(move |val| {的第二次调用中产生问题。
  • 使用lazy_static包来显式初始化get_future()为静态(如建议here),但尝试时会遇到宏错误。

可以找到整个示例here。我省略了一些细节来创建一个最小的例子。使用SomeStructtokio-core会出现问题。不幸的是,由于另一个库的依赖性,迁移到版本futures = "0.1"不是一个选项。

1 个答案:

答案 0 :(得分:2)

默认情况下,返回一个盒装特征对象绑定'static。按照编译器的建议并提供明确的生命周期,但不是'static

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

您还必须使用movesome_struct的所有权转移到关闭,并将core更改为可变。您还应该处理由core.run产生的潜在错误。

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

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

另见: