Await 表达式

语法
Await表达式 :
   表达式 . await

await 表达式是语法结构,用于暂停由实现了 std::future::IntoFuture 的计算,直到给定的 future 准备好产生值。 await 表达式的语法是一个实现了 IntoFuture trait 的表达式,称为 future 操作数 ,后跟 .await 关键字。 await 表达式只能在 async 上下文 中使用,比如 async fnasync 。更具体来说,await 表达式具有以下效果。

  1. 通过在 future 操作数上调用 IntoFuture::into_future 创建 future。
  2. 将 future 求解为 future tmp
  3. 使用 Pin::new_unchecked 固定 tmp
  4. 然后通过调用 Future::poll 方法并传递当前的 任务上下文 来对这个固定的 future 进行轮询;
  5. 如果对 poll 的调用返回 Poll::Pending ,那么 future 返回 Poll::Pending ,暂停它的状态,以便当包围的 async 上下文重新被轮询时,执行返回到步骤 3 ;
  6. 否则对 poll 的调用必须返回 Poll::Ready ,在这种情况下, Poll::Ready 变体中包含的值将被用作 await 表达式本身的结果。

版本差异: await 表达式只从 Rust 2018 开始可用。

任务上下文

任务上下文指的是在当前 async 上下文 被轮询时提供给它的 Context。 因为 await 表达式只能在 async 上下文中合法使用,所以必须有一些任务上下文可用。

近似解糖

实际上,一个 await 表达式大致相当于以下非规范的解糖:

match operand.into_future() {
    mut pinned => loop {
        let mut pin = unsafe { Pin::new_unchecked(&mut pinned) };
        match Pin::future::poll(Pin::borrow(&mut pin), &mut current_context) {
            Poll::Ready(r) => break r,
            Poll::Pending => yield Poll::Pending,
        }
    }
}

其中 yield 伪代码返回 Poll::Pending,并在重新调用时从该点恢复执行。 变量 current_context 指的是从异步环境中获取的上下文。