Expand description

This pass constructs a second coroutine body sufficient for return from FnOnce/AsyncFnOnce implementations for coroutine-closures (e.g. async closures).

Consider an async closure like:

#![feature(async_closure)]

let x = vec![1, 2, 3];

let closure = async move || {
    println!("{x:#?}");
};

This desugars to something like:

let x = vec![1, 2, 3];

let closure = move || {
    async {
        println!("{x:#?}");
    }
};

Important to note here is that while the outer closure moves x: Vec<i32> into its upvars, the inner async coroutine simply captures a ref of x. This is the “magic” of async closures – the futures that they return are allowed to borrow from their parent closure’s upvars.

However, what happens when we call closure with AsyncFnOnce (or FnOnce, since all async closures implement that too)? Well, recall the signature:

use std::future::Future;
pub trait AsyncFnOnce<Args>
{
    type CallOnceFuture: Future<Output = Self::Output>;
    type Output;
    fn async_call_once(
        self,
        args: Args
    ) -> Self::CallOnceFuture;
}

This signature consumes the async closure (self) and returns a CallOnceFuture. How do we deal with the fact that the coroutine is supposed to take a reference to the captured x from the parent closure, when that parent closure has been destroyed?

This is the second piece of magic of async closures. We can simply create a second async coroutine body where that x that was previously captured by reference is now captured by value. This means that we consume the outer closure and return a new coroutine that will hold onto all of these captures, and drop them when it is finished (i.e. after it has been .awaited).

We do this with the analysis below, which detects the captures that come from borrowing from the outer closure, and we simply peel off a deref projection from them. This second body is stored alongside the first body, and optimized with it in lockstep. When we need to resolve a body for FnOnce or AsyncFnOnce, we use this “by move” body instead.

Structs§