Take a very close look at the following:
// Note that this protocol can only be applied to reference types.
protocol Ref: class {
var zibbles: Int { get set }
}
class Reference: Ref {
var zibbles: Int = 42
}
// Note very carefully that we are NOT passing an
// instance, but a type itself.
func thwip<T: AnyObject>(into target: T.Type) {
}
// This compiles.
thwip(into: Reference.self)
// This fails to compile.
thwip(into: Ref.self)
However rare the case may be, this is something the language should be able to do as a matter of completeness. The compiler knows that any instance of Ref
must conform to AnyObject
, so the type constraint on thwip
should work, but it does not.
Note that if we remove the AnyObject
constraint from thwip
, it then compiles, but this defeats the purpose. I want to know whether the passed-in protocol has reference semantics or not.
// thwip without AnyObject
func thwip<T>(into target: T.Type) {
}
// Compiles, but useless to me
thwip(into: Ref.self)
Note that the following change also does not help us:
// Here we've changed class to AnyObject
protocol Ref: AnyObject {
var zibbles: Int { get set }
}
This is because Ref: class
and Ref: AnyObject
are synonyms. You can confirm this by putting them both together:
protocol Ref: class, AnyObject {}
The compiler will warn you about redundant conformance, though it will still compile.
Note that there is a very similar, but better-known compiler error:
protocol Base {}
protocol Ref: Base {}
func thwip<T: Base>(into target: T.Type) {
}
// Does not compile
thwip(into: Ref.self)
However, the compiler gives completely different errors for this case versus the one I'm having a problem with. In my case, I get "Cannot invoke 'thwip' with an argument list of type '(type: Ref.Protocol)'". In the latter case, I get "In argument type 'Ref.Protocol', 'Ref' does not conform to expected type 'Base'".