我正在尝试构建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这将导致整个程序执行过程中返回值的生命周期,这绝对不是我想要的更复杂的示例
答案 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 。