Overloading async methods and multiple protocol conformance - unexpected behaviour

I'm implementing some kind of request manager, based on protocols conformance and I faced with unexpected behaviour:

import Foundation protocol Foosyncable: AnyObject { func request() } protocol Fooasyncable: AnyObject { func request() async } protocol Fooable: Foosyncable, Fooasyncable {} class Foo: Fooable { func request() { print("request") } func request() async { print("request async") } } class Fooooooo { let f: Fooable init() { f = Foo() } func boo() async throws { await f.request() } } let f = Fooooooo() Task { try await f.boo() } 

Output of code above is 'request', instead expected 'request async'. I try to figure out why async method isn't call in that case.

If I change let f: Fooable to let f: Foo, it works as expected.

In other hand, when I remove await from call of f.boo(), I got error: Expression is ‘async’ but is not marked with ‘await’, which is more weird.

1 Like

While I cannot say what causes this behaviour, and if it is intended or not (IMO there should be some warning at least), you can fix this using @_implements attribute:

protocol Foosyncable: AnyObject { func request() } protocol Fooasyncable: AnyObject { func request() async } protocol Fooable: Foosyncable, Fooasyncable {} class Foo: Fooable { @_implements(Foosyncable, request()) func request_sync() { print("request") } @_implements(Fooasyncable, request()) func request_async() async { print("request async") } } class Fooooooo { let f: Fooable init() { f = Foo() } func boo() async throws { await f.request() } } let f = Fooooooo() try await f.boo() // will call correct method