134

I am trying to create a Dictionary (actually a HashSet) keyed on a custom protocol in Swift, but it is giving me the error in the title:

Protocol 'myProtocol' can only be used as a generic constraint because it has Self or associated type requirements

and I can't make heads nor tails of it.

protocol Observing: Hashable { }

var observers = HashSet<Observing>()
Cristik
  • 30,989
  • 25
  • 91
  • 127
devios1
  • 36,899
  • 45
  • 162
  • 260
  • possible duplicate of [How to create Dictionary that can hold anything in Key? or all the possible type it capable to hold](http://stackoverflow.com/questions/24119624/how-to-create-dictionary-that-can-hold-anything-in-key-or-all-the-possible-type) – jtbandes Jul 24 '14 at 06:22
  • @jtbandes That's not a duplicate. I'm asking what the error message actually means. What is a "Self or associated type requirement"? – devios1 Jul 24 '14 at 17:25
  • possible duplicate of [Usage of protocols as array types and function parameters in swift](http://stackoverflow.com/questions/24888560/usage-of-protocols-as-array-types-and-function-parameters-in-swift) – newacct Jul 25 '14 at 18:33

2 Answers2

102

Protocol Observing inherits from protocol Hashable, which in turn inherits from protocol Equatable. Protocol Equatable has the following requirement:

func ==(lhs: Self, rhs: Self) -> Bool

And a protocol that contains Self somewhere inside it cannot be used anywhere except in a type constraint.

Here is a similar question.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • 8
    ...because the compiler has to ensure it's the *same* type on either side, but the protocol only ensures it meets the contract. I see. Still, it seems like `Equatable` ought not to necessarily imply `Equatable` since that's not strictly necessary to generate a hash code. – devios1 Jul 25 '14 at 21:35
  • 4
    Oh no wait it does, because `Dictionary` needs to be able to know if a given object is indeed the correct key, because it's possible for two different objects to generate the same hash code. Hmm, that is a bit tricky. So the problem here is really with `Equatable`. – devios1 Jul 25 '14 at 21:41
  • 6
    Look at 0:56 into the great presentation by Alexis Gallagher titled: Protocols with Associated Types and how they got that way (maybe) https://youtu.be/XWoNjiSPqI8 – finneycanhelp Dec 22 '15 at 14:47
  • @finneycanhelp Thanks for this . Great video! – devios1 Mar 20 '16 at 22:37
  • 3
    Swift is truly one of the most poorly designed languages I have ever seen... –  Nov 06 '20 at 15:38
12

To solve this you could use generics. Consider this example:

class GenericClass<T: Observing> {
   var observers = HashSet<T>()
}
ph1lb4
  • 1,982
  • 17
  • 24