Await 表达式

语法
AwaitExpression :
   Expression . await

await 表达式是一种语法结构,用于挂起由 std::future::IntoFuture 的实现提供的计算,直到给定的 future 准备好生成一个值。 await 表达式的语法是一个表达式,其类型实现了 IntoFuture trait(称为future operand),然后是 token .,然后是 await 关键字。Await 表达式仅在 async context 中合法,例如 async fnasync closureasync block

更具体地说,await 表达式具有以下效果。

  1. 通过在 future operand 上调用 IntoFuture::into_future 来创建一个 future。
  2. 将 future 求值为一个 future tmp
  3. 使用 Pin::new_unchecked Pin tmp
  4. 然后,通过调用 Future::poll 方法并将当前的 task context 传递给它,来轮询这个 pinned future;
  5. 如果对 poll 的调用返回 Poll::Pending,则 future 返回 Poll::Pending,挂起其状态,以便在重新轮询周围的 async context 时,执行返回到步骤 3;
  6. 否则,对 poll 的调用必须返回 Poll::Ready,在这种情况下,Poll::Ready variant 中包含的值将用作 await 表达式本身的结果。

Edition differences:Await 表达式仅从 Rust 2018 开始可用。

Task context

Task context 指的是在轮询 async context 本身时提供给当前 async contextContext。因为 await 表达式仅在 async context 中合法,所以必须存在一些 task context。

近似脱糖

实际上,一个 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 指的是从 async 环境中获取的 context。