Promoting synchronous closure to async closure

Why does the following code not compile?

protocol A {
    var a: ()async->() { get }
}
struct X: A { // Error: Type 'X' does not conform to protocol 'A'
    var a: ()->()
}

When I click "fix" it fills in a property var a: ()async->(). Why is the synchronous closure not promotable to an async closure where that's what's requested?

Specifically what I want is to start by writing these protocols:

///
protocol AsynchronousThrowingGetterProtocol <Value> {
    
    ///
    associatedtype Value
    
    ///
    var execute: ()async throws->Value { get }
}

///
protocol MainActorSynchronousThrowingGetterProtocol <Value>:
    AsynchronousThrowingGetterProtocol {
    
    ///
    var execute: @MainActor()throws->Value { get }
}

///
protocol SynchronousThrowingGetterProtocol <Value>:
    MainActorSynchronousThrowingGetterProtocol {
    
    ///
    var execute: ()throws->Value { get }
}

///
protocol AsynchronousGetterProtocol <Value>:
    AsynchronousThrowingGetterProtocol {
    
    ///
    var execute: ()async->Value { get }
}

///
protocol MainActorSynchronousGetterProtocol <Value>:
    AsynchronousGetterProtocol,
    MainActorSynchronousThrowingGetterProtocol {
    
    ///
    var execute: @MainActor ()->Value { get }
}

///
protocol SynchronousGetterProtocol <Value>:
    MainActorSynchronousGetterProtocol,
    SynchronousThrowingGetterProtocol {
    
    ///
    var execute: ()->Value { get }
}

and then be able to apply them to these structs (which is where the problems begin):

///
struct AsynchronousThrowingGetter <Value>:
    AsynchronousThrowingGetterProtocol {
    
    ///
    var execute: ()async throws->Value
}

///
public struct MainActorSynchronousThrowingGetter <Value>:
    MainActorSynchronousThrowingGetterProtocol {

    ///
    public var execute: @MainActor()throws->Value
}

///
struct SynchronousThrowingGetter <Value>:
    SynchronousThrowingGetterProtocol {
    
    ///
    var execute: ()throws->Value
}

///
struct AsynchronousGetter <Value>:
    AsynchronousGetterProtocol {
    
    ///
    var execute: ()async->Value
}

///
struct MainActorSynchronousGetter <Value>:
    MainActorSynchronousGetterProtocol {
    
    ///
    var execute: @MainActor ()->Value
}

///
struct SynchronousGetter <Value>:
    SynchronousGetterProtocol {
    
    ///
    var execute: ()->Value
}

In general it’s not possible to fulfill a protocol requirement of type A with a witness of (static) type B even if B is a subtype of and/or convertible to A. But it’s been suggested at various times in the past to lift this restriction since it’s allowed for, e.g., subclass overrides.

2 Likes