If I have a value of Any.Type, is there a way to check if a type T conforms?
For example, if I have a type, and a type as a value:
struct MyError: Error {}
let errorType: Any.Type = Error.self
I want to check if MyError conforms to errorType.
The is operator is out of the question, since I merely have a value, and the scopes don't match:
MyError.self is errorType
Cannot find type 'errorType' in scope
I was hoping I could prod the Any existential using _openExistential, but this doesn't return the right thing:
func conforms<T>(to type: T.Type) -> Bool {
return MyError.self is T.Type
}
_openExistential(errorType, do: conforms(to:))
// returns false
// vs.
MyError.self is Error.Type
// returns true
Am I missing something subtle here? Or is there an entirely different way of accomplishing the same thing?
1 Like
For protocol types, substituting into a generic parameter T in T.Type can only give you the concrete metatype for the protocol, Error.Protocol, and not what you want, the existential metatype Error.Type. Inside conforms(to:), you're really asking MyError.self is Error.Protocol, which is false because only Error.self is an instance of Error.Protocol. You will need to bind T to the entire existential metatype Error.Type in order to do the test you want; something like this:
func conforms<T>(to type: T.Type) -> Bool {
print(T.self)
return MyError.self is T
}
let errorType: Any.Type = Error.Type.self
struct MyError: Error {}
print(_openExistential(errorType, do: conforms(to:)))
4 Likes
Thanks for the explanation!
In the context I'm working in, though, I already have a value of Error.Protocol. Is there any way to dynamically get an Error.Type.Protocol out of that? (type(of: errorType) yields an Error.Protocol.Type, which makes sense but isn't helpful.
I was working with metadata layout earlier (using Echo as a reference), but it's doing some funny things in C to populate protocol conformance data, which is complexity I was hoping to avoid.
There is no real protocol polymorphism in Swift right now, so there isn't a way to get from P to P.Type within the confines of the language itself. You would have to use the runtime yourself to do the dynamic protocol tests.
1 Like