I recently ran into a situation where I had a generic type with a protocol constraint, and I needed to dynamically convert it to a generic type with a different constraint if possible. I believe there is sufficient metadata that this could be done at runtime, but I could not figure out how to express it.
Example:
// API consumers can only see this function. I do not control the API,
// so I can’t expose my fastPath() function
public func encode<T>(_ value: T) throws where T: Encodable {
If let v = value as? T: MyProtocol {
fastPath(v)
} else {
// ...
}
}
internal func fastPath<T>(_ value: T) where T: MyProtocol {
// ...
}
For reasons, my fastPath function can’t accept an existential, it has to be generic (otherwise this would be easy).
I need a way to dynamically convert from a concrete type T: Encodable to a concrete type T: MyProtocol.
Right, I'm not expecting this to work statically because there is not enough information at the call site. I thought that at runtime the list of protocols a type conforms to was dynamically knowable, so it should be possible to cast a T: Foo to a T: Bar if the underlying type T conforms to both Foo and Bar even if the Bar conformance is not statically known at the call site.
Thank you for the link! I will read up on it, but it's not something I can understand at a glance
Unfortunately function specializations won't work in this case because this is inside the implementation of an UnkeyedEncodingContainer. The Encoder API vends an existential of UnkeyedEncodingContainer so my specializations could never be called because they are not part of the protocol.
I could dynamically cast the container existential in all of my implementations of encode(to:) to check if it's this one, but that won't work for Encodable types that I don't control such as Array, etc.