2

我正在尝试在 Rust 中构建一个非常基本的异步回调函数示例

extern crate tokio;
extern crate tokio_core;
extern crate tokio_io;

use std::error::Error;
use tokio::prelude::future::ok;
use tokio::prelude::Future;

fn async_op() -> impl Future<Item = i32, Error = Box<Error>> {
    ok(12)
}

fn main() {
    let fut = async_op().and_then(|result| {
        println!("result: {:?}", result);
    });
    tokio::run(fut);
}

这总是会导致编译器错误:

error[E0106]: missing lifetime specifier
 --> src/main.rs:9:54
  |
9 | fn async_op() -> impl Future<Item = i32, Error = Box<Error>> {
  |                                                      ^^^^^ expected lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
  = help: consider giving it a 'static lifetime

为什么首先会出现终身错误?为什么它只适用于Error而不适用于Item

我也不确定“帮助:考虑给它一个“静态生命周期”——AFAICT 这将导致整个程序执行过程中返回值的生命周期,这绝对不是我在更复杂的示例中想要的。

4

1 回答 1

3

Rust 中的一切都有一个生命周期。如果它包含引用,则为生命周期最短的引用的生命周期,否则为'static,应解释为“不依赖于任何可能具有更短生命周期的事物”。

因此 的寿命i32是已知的。是'static,因为它不包含任何引用。

但是Error,这是std::error::Error一种特性,并且不需要任何终身约束。这意味着您可以将其实现为引用,或包含具有生命周期的引用的类型。而且由于代码应该对您可能在下游任何地方进行的任何替换都是有效的,因此编译器坚持要给它一个生命周期,该生命周期是返回值可用性的下限。

在这里给它'static生命是明智的。这并不意味着返回值在整个程序执行期间都有效,它仅意味着返回值不限于任何较短的生命周期(这基本上意味着它不依赖于Box除了可能的静态事物之外的任何东西)并且将只要有东西保留它就保持有效。

我相信正确的语法是:

fn async_op() -> impl Future<Item = i32, Error = Box<Error + 'static>>

请注意,它实际上只是限制Box 的内容。这是编译器唯一没有看到的,并且担心它可能在某个时候不再有效。因此,您向它保证,在删除 Box 之前,Box内容不会变得无效。

于 2018-08-19T20:14:45.933 回答