I outlined the primary reason right after that sentence in the original post:
Trying to put it another way: because Swift has Self types in protocols, and allows them to be used as function arguments, you can write a protocol whose behavior as a type is fundamentally incompatible with its behavior as a generic constraint. If you consider a protocol like Swift's Equatable
:
protocol Equatable {
static func ==(a: Self, b: Self) -> Bool
}
The Self
requirement allows the protocol to require that an Equatable
type is only comparable to itself, not some arbitrary other Equatable
value. This makes Swift protocols able to express more powerful relationships than the features they took syntactic inspiration from, such as Java and C#'s interfaces, but it creates the situation where the type Equatable
can't directly satisfy the requirements of the protocol Equatable
—two values of type Equatable
can dynamically contain different types, but the requirement applies to two values of the same type. Changing the spelling to something like any Equatable
doesn't eliminate that situation, but my hope is that it makes it clearer that you're asking for a distinct thing from the protocol, and that it's easier to explain why the type any Equatable
doesn't conform to the protocol Equatable
than the seemingly-broken statement that Equatable
doesn't conform to Equatable
.
By contrast, the closest that those other languages' interface
features can get to self and associated type requirements is to represent them as generic arguments, this is why Comparable<T>
in Java makes you repeat the conforming class name in class Foo implements Comparable<Foo>
. And you can only use interfaces as types by providing all of their generic arguments, so you don't have the covariance issues of Swift's type erasure, though at the same time, Comparable<Foo>
is unlikely to be very useful as a type because only Foo
and its subclasses can usually implement it, so it provides little expressivity beyond using Foo
directly. (In the case of Java, you do also have the ?
wildcard to get something like Swift's type erasure, though Java's implementation is unsound and has problems of its own.) I do think that the strain on Swift's protocol types would be felt less by typical users if we had the analogous ability to bind their associated types, so that you could write any Sequence<Int>
instead of only any Sequence
. I talk about that a bit later in this post, but more recently Holly has just begun a pitch for this feature.