I'm wondering, is it even possible to create a `Set` in Swift whose members are guaranteed only to share conformance to a Protocol?
My initial attempt looked like this:
protocol MyProtocol {}
var mySet: Set<MyProtocol> = []
But that yields the compiler error "Type 'MyProtocol' does not conform to protocol 'Hashable'".
Next I tried:
protocol MyProtocol: Hashable { }
var mySet: Set<MyProtocol> = []
But now we get the error "Protocol 'MyProtocol' can only be used as a generic constraint because it has Self or associated type requirements"
Clearly we've hit a problem with the Swift distinction between static and dynamic protocols that prevents us from using a Hashable protocol as a type parameter (because Hashable is Equatable, and Equatable for some reason requires that you're trying to equate a class to itself).
What if we try adding Hashable compliance to MyProtocol via an extension?
protocol MyProtocol {}
extension MyProtocol: Hashable {}
"Extension of protocol 'MyProtocol' cannot have an inheritance clause" - Ok, so protocol extensions cannot add protocol conformance like class extensions can.
Ok, how about we try to add conformance via a protocol extension to Hashable?
protocol MyProtocol {}
extension Hashable where Self: MyProtocol {
var hashValue: Int { get { return 0 } } // TODO: An actual implementation
}
var mySet: Set<MyProtocol> = []
"Type 'MyProtocol' does not conform to protocol 'Hashable'" - Ok, we can't add protocol conformance like that
Protocol composition as part of the Set type parameter?
protocol MyProtocol {}
var mySet: Set<protocol<MyProtocol, Hashable>> = []
"Protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements" - here we are again
The one thing that does seem to work is:
protocol MyProtocol, Hashable {}
func getMySet<T: MyProtocol> -> Set<T> {
return []
}
But now we have the problem that when we create our Set we need to provide a class (because, again, we can't use a protocol that extends MyProtocol as our T parameter because you can't use any protocol that inherits from MyProtocol as a type parameter) that all the members of our Set are guaranteed to extend.
This is severely limiting to the power of Protocols because now I cannot, for example, construct a set of all UserLike objects without knowing a single class (assuming there even is one) that all UserLike objects will also subclass. Is there a way to accomplish this without requiring that all members of my Set extend a given class?