[Concurrency] Asynchronous functions

We should probably reject "try await" to be consistent, yes.

To clarify, it is not the presence of await that changes overloading. When you are within an asynchronous function, we prefer async functions. When you are within a synchronous function, we prefer synchronous functions.

If you're talking about the implementation of the type checker, no, it does not make it more complicated. The implementation was straightforward and aside one bug we've found in the initial implementation, it hasn't surprised us yet.

For one thing, overloading allows us to avoid having to suffix "Async" or "Asynchronously" onto names that might collide with synchronous functions.

I don't think the issue is limited to Objective-C interoperability, although it does show up there. Extisting synchronous, blocking APIs are likely to get augmented with asynchronous APIs, and we want the asynchronous code to prefer to use those new asynchronous APIs.

It works with throws, and async does exactly the same thing.

As just confirmed above, if you're passing a closure that is fully synchronous (has no await in it anywhere) to a function that takes an async closure, you can use async in. I understand that you'd prefer to trade overloading for subtyping (and it's worth investigating that), but this particular example is a tiny syntactic optimization of the kind that a Fix-It could introduce when it comes up.

The throws one keeps the error parameter but changes its type to (), so your call looks like:

try object.callThrowingThing(a, error: ())

It's quite baroque, and I wish we hadn't done that. The corollary for async would be async: (), which I wouldn't want to do. If we dropped overloading of async and non-async, I'd lean toward appending an Async or Asynchronously suffix to the base name.

Doug

2 Likes