Why are protocol conformance extensions not supported for protocols?

Hi all,

I was wondering why the following is not allowed, and if we could possible allow it in future versions of the language?

public protocol Example {
  ...
}

// Assume that the following are defined in a separate 
// module without the ability to modify `Example.`
public protocol Countable {
  ...
}

extension Example: Countable {
  ...
}

Thanks,
Anthony

3 Likes

What are you trying to do? Is it not possible to create a new protocol that conforms to both (and optionally add customization point)?

1 Like

If it were me I would be wanting to make all Example types conform to Countable. Is there a way to do that?

So far I don't think you can do that.

IMO that'd be a dangerous thing to do when the conforming type is not in your control, esp. in the presence of type inference.

Could you give an example where this could break something? And if it is dangerous, don’t we already have that danger when you extend someone else’s concrete type to conform to some protocol?

1 Like

You can do this


typealias MyProto = Example & Countable


extension Int: MyProto {}

But that’s not the same thing right, at least it doesn’t seem to achieve what I would want. I want Int (and all other types that are Countable) to automatically conform to Example just by virtue of being Countable.

Fun question. Good luck

public protocol Example {
}

// Assume that the following are defined in a separate 
// module without the ability to modify `Example.`
public protocol Countable {
}

///
protocol MyProto: Example & Countable {}

extension MyProto {
    func someDefault(){print("Hello")}
}

extension Int: MyProto {}

1.someDefault() // Hello

1 Like

Now that I think about it, it's pretty similar to class extension, though I'm not fond of extending other's class to begin with.
This is even more dangerous since you're adding conformance, not only to a single protocol, but also all classes that extend from it, but I'm splitting a hair here.

The reason I want to do this is exactly that. Think about type class derivation in other languages (e.g., Scala). There you can define derivation rules even outside the module in which an original type class was defined and that enables a lot of powerful features for building good APIs. I don't believe it's dangerous in that you already get halfway there with extensions to concrete types. The Int: MyProto example above still applies today and I don't consider that a problem. Aside from whether or not this is useful feature to have though, I am wondering if there are any compiler implementation reasons that make it hard to support with the current model for extensions.

But this is not the same, here you are extending Int, I think OP wants to extend Countable, not individual types. At least that's what I'm asking about, sorry to hijack the question if he wanted something else.

1 Like

@GreatApe you're perfectly right. My question is about extending other protocols rather than concrete types.

So then this would be a minimal example of what you want to be able to do?

extension Codable : Hashable {
    func hash(into hasher: inout Hasher) {
        hasher.combine(try! JSONEncoder().encode(self))
    }
}

This seems like something that could become possible (if not allowed) when some of the enhanced existentials ideas land:

extension <T>: SomeProtocol where T: OtherProtocol { }

Whether it makes sense as a feature is another question.

1 Like

I think this has a slightly different meaning. This line says: "extend every concrete T that conforms to OtherProtocol to also conform to SomeProtocol".

extension OtherProtocol : SomeProtocol {}
Instead would work (in my head at least) also for existentials of OtherProtocol without a concrete type.
My assumption is based on the fact that existentials of a protocol do not conform to it.

extension Int: OtherProtocol {}

class A {
    var a: OtherProtocol // With the generic extension way is NOT also SomeProtocol, but with the protocol conformance extension is
    var b: Int  // Is also SomeProtocol in both ways
}
4 Likes

Yes I agree. Also, I believe that my question is simpler than existentials. At a very basic level, I am wondering why it's not currently possible to define such extensions. Is there a specific compiler limitation that prevents us from allowing that?

The comments on the JIRA issue here include a good discussion of why this can be problematic.

3 Likes

I don’t really understand the explanation in the Jira link but it seems that it should at least be possible to make all concrete types that conform to ProtocolX also conform to ProtocolY in one go, since it is possible to extend each individual type?

1 Like

Thanks. @owenv! This helped clarify some of the related problems. In the meantime, I also find this as a good justification for this limitation. Related to this note, I would love to see multiple conformances to the same protocol be supported for clearly mutually exclusive cases.