Async method overloads in the context of protocol conformance behave differently than the Async/await proposal and subsequent amendment Allow overloads that differ only in async suggest they do.
This overload works as expected; there are no compiler errors and calling context inference resolves as outlined in the proposal.
struct Foo {
func doSomething() -> String { "hello" }
func doSomething() async -> String { "world" }
}
However, things fall apart when a protocol is introduced.
protocol P { // ✅ this is fine
func doSomething() -> String
func doSomething() async -> String
}
struct Bar: P { // ❌ Type `Bar` does not conform to protocol `P`
func doSomething() -> String { "hello" } // ❌ candidate exactly matches
func doSomething() async -> String { "world" } // ❌ candidate exactly matches
}
This seems to be due to the fact that sync
methods can satisfy async
method conformance requirements, as outlined in the Protocol Conformance section of the Async/await proposal.
I don't believe this is expected behavior based on the acceptance reasoning of Allow overloads that differ only in async. Specifically, creating an exception to the async overloading rule for protocol conformance violates this idea:
Without overloading on
async
, the Swift ecosystem will end up with a nontrivial number of APIs with non-ideal names (e.g., anAsync
suffix) that won't be able to be fixed later.