The generic constraint syntax where T == U
says that the type T
must be the same type as type U
.
Let's do a simpler example first:
protocol GenericProtocol {
associatedtype T
associatedtype U
}
extension GenericProtocol where T == U {
func foo() {}
}
class ConcreteClassA: GenericProtocol {
typealias T = Int
typealias U = Float
}
class ConcreteClassB: GenericProtocol {
typealias T = Int
typealias U = Int
}
let a = ConcreteClassA()
let b = ConcreteClassB()
Now which of these, a
or b
has the member foo
? The answer is b
.
Since the extension's generic constraint says that T
and U
must be the same type, the extension is only applied to ConcreteClassB
because its T
and U
are both Int
.
Back to your code now.
In your code, you're saying that Indices.Iterator.Element
must be the same type as Index
. Let's figure what these two types are respectively.
Indices
is the type of the property indices
. So Indices.Iterator.Element
is type of each index of the collection. Index
on the other hand, is the type of value that you can put into the subscript of of the collection. This constraint seems excessive but it is in fact not. I can't think of an example of a type where the constraint is not true. But you can in theory create such a type. That's why the constraint is there.
If the constraint weren't there, this would not compile:
indices.contains(index)