Search code examples
swiftgenericstype-inferencexcode9-betaswift4

Swift 4: Implementation of a generic protocol with protocol as an associated type


I've experienced a problem during Swift 3.1 to Swift 4 codebase migration.

The problem arrises when you try to implement a generic protocol method that takes a closure with a generic parameter with a protocol as an associated type. It's easier than it sounds :)

The following code works fine in Swift 3.1:

protocol FooType {
    associatedtype BarType

    func foo(bar: BarType)
    func foo(action: (BarType) -> Void)
}

protocol Bar {}

class Foo: FooType {
    typealias BarType = Bar

    // Compiles in both 3.1 and 4
    func foo(bar: Bar) {
    }

    // ERROR: Candidate has non-matching type (Bar) -> Void
    func foo(action: (Bar) -> Void) {     
    }
}

However in Swift 4 compiler gives me an error about class Foo not conforming to protocol FooType with foo(action:) method implementation missing.

By the way Xcode 9 "fix-it" generates the same implementation I have.

The code compiles if I use BarType as a parameter type, but it's not good to loose concrete type information.


Solution

  • Turns out that removing the line

    typealias BarType = Bar
    

    resolves the issue. Which is fair - type inference does its job.

    Nevertheless, it should be a legal code and seems like a bug in compiler.

    Reported accordingly.