4
votes

I have a generic protocol:

protocol GenericProtocol {
  associatedtype GenericParameter
}

I'm not able to use it like this:

var someValue: GenericProtocol?

I get the error message we all know well:

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

Having run into this error many times and having spent a long time pondering the conceptual reason for this error, I think I have grasped it at least somewhat. What I don't understand, is why I can't create a protocol which inherits from and specializes my generic protocol such that it can be used in type signatures. Here is the inheriting protocol:

protocol ConcreteProtocol: GenericProtocol where GenericParameter == Bool { }

But even this I can't use in a type signature:

var someValue: ConcreteProtocol?

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

Am I misunderstanding the meaning of a where clause? What is the conceptual reason that even constrained sub-protocols must be treated as generic? I am sure that this is not a bug but rather a purposeful fact of the language which is known to the Swift community. Can anyone explain this to me?

Also if anyone could provide a way in which I can to achieve what I want that would be much appreciated, though I'm not sure it's possible.

1

1 Answers

1
votes
var someValue: GenericProtocol?

Why this doesn’t work is quite obvious if you think of trying

var someValue: Class = Class1()
someValue            = Class2()

The point is that you have a protocol which is for every type you assign there different, has different method types for example, which makes someValue unusable.

protocol ConcreteProtocol: GenericProtocol where GenericParameter == Bool { }
var someValue: ConcreteProtocol?

does likely not work because classes may want to override the associatedtype and so could not be assigned to someValue. So implementing this in the language would probably deny classes to override, since ConcreteProtcol could use GenericParameter == Bool in one of its extensions already.