An alternative way to choose `future.await()`

Thank you for this response, I have reread my comments and the latter is probably how it reads, which doesn't make a whole lot of sense. I messed up. Maybe it really should be only a special abi on the function Await::await_fn to lead to less confusion around this. The clarification of terminology by @withoutboats was helpful, thank you for taking your time to get this correct in detail.

Rephrasing what I had in mind, it seems to me that it is yielding which makes a function subject to the new way of unwinding, not await or polling specifically and therefore I would associate it with the async fn on our own function bound more than the .await operator itself. This holding especially with regards to potential future extension to async generators.

Edit: In other thoughts, if the other yielding operations would get similar functions to implement their interface within the type system, then the way to unwinding could also be presented as special to one specific extern "abi" that is chosen for them all? This being somewhat similar to special handling of unwinding through other extern functions.

2 Likes

@eddyb shared some interesting thoughts (on Reddit) from the compiler internal side which I think should be repeated here as well so that it is possible to follow.

Please don't copy extern "rust-call" - we've been trying to come up with a non-hacky way to enable it since before the hack was ever considered. IMO a better hack would've been a perma-unstable attribute.

I mostly consider this a detail for now since declarations and definitions of equivalent attributes should be inaccessible to users in any case, but neverthelesss interesting in that it could also address the point of having other yielding operations with a similar visible interface. Thus, an updated version of the trait would reuse a reserved keyword as a function attribute, instead of using an abi, which is also closer to the meaning and use of unsafe fn as compared in the blog post.

#[lang = "await"]
trait Await {
    type Output;
    yield fn await_fn(self) -> Self::Output;
}

The meaning of yield fn would then be that it is allowed to yield for the caller. Exact details wouldn't need to be stabilized for the moment but in practice, restricted to not be recursive and thus inlinable. I think this is also interesting insofar as it opens up a much more familiar syntax and semantical discussion for exposing this in the future. This relates to a previous possible future direction for await:

But also it could be useful to not have the complete definition of a generator necessarily appear in a single function unit. For both these scenarios, a more precise definition of these semantic could be useful should we ever want to stabilize its meaning.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.