On why await shouldn't be a method

This duality of await, behaving like a function call from the semantic outer perspective but not actually representing a call to an await function, prompted me to prefer syntaxes that logically bound the await to the call itself. The best syntax would be call-based and clearly associate the appearance of the async keyword with the call itself, and none of its arguments (neither the future, nor any argument position in the call to allow for extensions to generator arguments later). I don’t think the macro variant does a good job of staying true to the function call aspect as a macro invocation is associated with a compile-time effect in my head and not a runtime one. My own proposal of future(await) did a very bad job of the second aspect.

But, ultimately, there are different types of functions already: unsafe and extern "C" are not the same function types as normal ones. This makes it somewhat easier for me to accept await as new function type, maybe surprisingly an inherent one, but still aligned to other features that exist in the language already. The parallel with unsafe fn even goes as far as being callable within unsafe code, whereas async is callable in async code! It’s not far from a new (imaginary) trait in the prelude:

trait Await {
    type Output;
    /// Implemented by compiler magic.
    extern "await-call" fn r#await(self) -> Self::Output;
}

impl<F: Future> Await for F { type Output = F::Output; }
8 Likes