Possibilities working with metatypes

I made a system that helps add Codable to objects with existential properties and it requires collecting all the metatypes involved into a data structure. I got something working but it’s lacking constraints I don’t know if are possible, basically I can’t constrain an existential metatype to ‘conforming’ to another protocol and I can’t constrain/verify that an array of concrete metatypes conform to that existential.

So for a setup like this

protocol PolyCodable {}
protocol Gear: PolyCodable {}
struct HexGear: Gear {}
struct RoundGear: Gear {}

I want to collect the metatypes like this

let pg = PolyGroup(for: (any Gear).self, with: [HexGear.self, RoundGear.self])

Which I’m doing now like this, except it doesn’t restrict (any Gear).self to having PolyCodable and it doesn’t verify that HexGear.self and RoundGear.self are conforming to Gear.

struct PolyGroup<T> {
    let polyType: T.Type                
    let concretes: [any PolyCodable.Type]
    init(for polyType: T.Type, with concretes: [any PolyCodable.Type]) {
        self.polyType = polyType
        self.concretes = concretes
        //somehow compare and verify that the concretes are of polyType

I noticed that I can restrict concretes to only allow Gears with the type [any Gear.Type] so tried this variation but get the error that ‘any’ has no effect.

struct PolyGroup<T> {
    let polyType: T.Type = T.self
    let concretes: [any T.Type] // error, but “Gear” works here in place of “T”

let pg = PolyGroup<Gear>(concretes: [HexGear.self, RoundGear.self])

I’ve been doing lots of trial and error and guesswork because I don’t know metatypes that well and don’t know whats possible. Maybe this isn’t doable yet and I should just move on?

A protocol P is a constraint. any P is a type. In other words, adding any turns a constraint into a type — you can’t add it to a type.

Here, T is already a type, so you can’t add any. There’s no way to make a struct generic over protocols rather than types, so you’ll have to think of another way to express what you mean.

I’ve been here before, the short answer is you can’t easily do that at runtime, especially for protocol existentials.

1 Like