swiftgenericsswift3protocolsprotocol-extension

Extending custom type where associated type is equal to Void


I'm in a situation where I have a custom type that contains an associatedtype. In the case where this is equal to Void, I would like to have some default behaviour (to make the call-site more convenient). I tried to boil the example down to:

protocol FooType {
    associatedtype T: Any
    var bar: (String) -> T { get }
}

struct Foo<T>: FooType {
    let bar: (String) -> T
}

extension Foo where T == Void { // Compile error: "Same-type requirement makes generic parameter 'T' non-generic".
    init() {
        self.bar = { _ in return }
    }
}

The idea is that, in the cases where the generic type is Void, it doesn't make sense (in my scenario) to pass in a function (named bar in the example). Therefore, I just want a default implementation for this function in this specific context.

When trying to do the above I get the Same-type requirement makes generic parameter 'T' non-generic which sounds very similar to what happens when one tries to restrict e.g. the Array type when containing specific types. A workaround for this is to introduce a protocol, but I cannot do that for Void. Is it possible to do what I want or is this currently a limitation in Swift 3?


Solution

  • As of Swift 3.1, the code posted in the question now works. That is, the following now works as wanted:

    protocol FooType {
        associatedtype T: Any
        var bar: (String) -> T { get }
    }
    
    struct Foo<T>: FooType {
        let bar: (String) -> T
    }
    
    extension Foo where T == Void { 
        init() {
            self.bar = { _ in return }
        }
    }
    
    let foo = Foo<String>(bar: { (t: String) in return "" })
    let zoo = Foo<Void>()