Search code examples
iosswiftswift-protocolsswift-extensions

Why does swift hide default implementation for restricted protocols?


I have a protocol which declaration looks like this:

protocol RefreshableView where Self: UIView {
    func reload()
}

And it has default implementation which looks as follows:

extension RefreshableView {
    func reload() {
        print("Default implementation")
    }
}

Then if I declare another (empty) extension of UIView conforming to this protocol I get compile-time error stating that UIView does not conform to the protocol.

extension UIView: RefreshableView {}

It should not be a case from my point of view, as default implementation is provided. However if I remove where statement (restriction to the classes which can conform to the protocol) from declaration of the protocol, everything works as expected. Another option to silence this error is to give the same where statement next to default extension declaration, but it feels redundant as I already let compiler know the protocol is supposed for narrow audience. Is there an explanation to this behavior?


Solution

  • What you're saying is that this doesn't compile:

    protocol RefreshableView where Self: UIView {
        func reload()
    }
    extension RefreshableView {
        func reload() {
            print("Default implementation")
        }
    }
    extension UIView: RefreshableView {
    }
    

    As Rob Napier points out in a comment, that's a very odd thing to say, because if UIView itself is going to adopt RefreshableView, then what's the protocol for? The original declaration of the protocol means that only a UIView subclass can adopt RefreshableView, so what the compiler expects is that that's what will happen:

    protocol RefreshableView where Self: UIView {
        func reload()
    }
    extension RefreshableView {
        func reload() {
            print("Default implementation")
        }
    }
    class MyView: UIView {}
    extension MyView: RefreshableView {
    }
    

    That is a useful real-world case, and it compiles just fine.

    So you could file a bug against your original code, but you have to admit it is a very peculiar edge case to start with; you are saying something that no one would in fact ever say.