An async function is really just a regular function that returns a Future. Because Future is a trait, what that really means is that it returns some type that implements Future.
Every async function returns a different "custom made" type specific to that function and there's no way to name it, but we can use the impl Trait syntax to say "some type that implements this trait". Another way to write async_add is
// returns something that implements a Future that resolves to an i32
fn async_add(x: i32, y: i32) -> impl Future<Output = i32> {
async move {
x + y
}
}
Which is what you see in cuviper's code. Unfortunately, as you can see from the error, you can't just write impl Fn(i32) -> impl Future<Output = i32> (at least not yet)... So you need either the Pin<Box<...>> from semicoleon's post or nightly features like in cuviper's post.