Why does Swift allow generics in protocol declarations if they aren't actually available in the protocol’s scope?
What is the language trying to achieve here—are there plans for something like primary associated types, or is this related to how Swift handles generics and protocols differently?
Is this behavior inspired by something similar to how Kotlin handles generic constructors or type parameters?
I'd appreciate a deeper explanation of what's going on under the hood, or pointers to any official Swift discussions or documentation on this topic.
Edit
By the way, does this mean that generics in protocols are similar to type aliases, where you can omit them and let Swift infer the types from the implementation?
Aren't there a "An associated type named 'Entity' must be declared in the protocol 'Repository' or a protocol it inherits" error, which gives a clearer view of what's wrong?
No. It has to be declared somewhere.
protocol Umbrella {
associatedtype T1
}
protocol S<T1> : Umbrella {
func a(in : T1) throws // T1 definition inherited from Umbrella
static func b() -> T1 // ditto
func c<T1>() -> T1 // !!! Type is unrelated to T1. equivalent to c<T>() -> T
}
func d<T2>(_ : T2) -> Float
where T2 : S, T2.T1 == OpaquePointer { // S<OpaquePointer> is more sugar-ful
return T2.c() // Compiles, calls a c<Float>() that resides under S<OpaquePointer>
}
Because we decided it’s very unlikely that we ever will support generic protocols, we’ve repurposed <…> for a different feature called primary associated types. As the name suggests, this feature allows you to designate one or more of the protocol’s associated types as “primary.”
A primary associated type allows you to express certain constraints that you couldn’t otherwise. For example, you can now write some Collection<Int>, an opaque type, where it’s not possible to write some (Collection where Element == Int).
Don’t confuse primary associated types with generic parameters. Recall that Array<Int> and Array<String> are two distinct types, and there isn’t some base type that’s just Array. By contrast, there is only one protocol Collection, and Collection<Int> and Collection<String> are merely ways of constraining its associated type Element.
As the name suggests, a primary associated type can’t be nominated if there isn’t an associated type of that name declared in the body of the protocol (or inherited).
What’s the correct terminology for such protocols? I’ve always thought that "generic protocol" is a valid name. To my understanding, existentials have broader meaning?