最小期货回调示例中的“预期寿命参数”错误?

时间:2018-08-19 19:21:01

标签: rust rust-tokio

我正在尝试构建very basic example of an asynchronous callback function in 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这将导致整个程序执行过程中返回值的生命周期,这绝对不是我想要的更复杂的示例

1 个答案:

答案 0 :(得分:3)

Rust中的所有内容都有终身限制。如果包含引用,则为最短引用的生存期,否则为'static,应将其解释为“不依赖任何可能具有较短生存期的内容”。

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

但是Error(即std::error::Error)是特征,并且不需要任何生命周期约束。这意味着您可以将其实现为参考,也可以实现为包含寿命的参考的类型。而且由于该代码对于 any 替换有效,因此您可以在下游的任何地方进行替换,因此编译器坚持认为,您应为其赋予一个生存期,该生存期对于返回值的可用性而言是较低的。

赋予'static一生是明智的。这并不意味着返回值在整个程序执行过程中都是有效的,仅意味着返回值不限于任何较短的生存期(这基本上意味着它不依赖于Box之外的任何内容,除非可能静态事物),只要有东西坚持下去,它就会一直有效。

我相信正确的语法是:

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

请注意,这实际上仅是限制Box的内容。那是编译器唯一看不到的,并且担心它可能在某个时候不再有效。因此,您向它保证Box的内容不会变成无效,直到它放下Box