How do you convert a metatype to an existential which references it through a generic type which references it?

Following from this thread, a related question—find it in the topic title.

This compiles:

protocol P { }
enum E1: P { }
enum E2: P { }

protocol SDelegate<T> {
  associatedtype T: P
}

struct S<T: P> {
  static var delegateType: any SDelegate.Type {
    switch T.self {
    case let e1Type as E1.Type: S<E1>.SE1.self
    case let e2Type as E2.Type: S<E2>.SE2.self
    default: fatalError()
    }
  }
}

extension S<E1> { enum SE1: SDelegate { } }
extension S<E2> { enum SE2: SDelegate { } }

It doesn’t compile, with the addition of this <T>:

struct S<T: P> {
  static var delegateType: any SDelegate<T>.Type {
    switch T.self {
    case let e1Type as E1.Type: S<E1>.SE1.self
    case let e2Type as E2.Type: S<E2>.SE2.self
    default: fatalError()
    }
  }
}

I understand why. What are you supposed to do when you want a more constrained translation of a metatype?

Note: I don’t actually want to have to use existentials, and this switching over a known set of types. Please, please tell me how to avoid that without the associatedtypes from the other thread.

You need to force cast the result. In fact, I believe you can achieve the same thing by:

Thank you. That's what I came up with later as well. :confused: I don't think it's possible without using an intermediate result (delegateType, here), without force casting at the end of the line of every case?:

let delegateType: any SDelegate.Type = switch T.self {
case let e1Type as E1.Type: S<E1>.SE1.self
case let e2Type as E2.Type: S<E2>.SE2.self
default: fatalError()
}
return delegateType as! any SDelegate<_>.Type

No, the T here is an associated type of SDelegate, not an SDelegate itself. (Following from the other thread, this is a reversal of each P having an associated type which conforms to SDelegate.)

For complex metadata type manipulation, another approach on ABI-stable Darwin platforms is to retrieve the corresponding data directly from the Runtime.

See detail on this in one of my blog post.

Also inspired by a private framework, I’ve wrapped and exposed such ability as the OpenGraph.Metadata API. If you’d prefer not to build the Swift Toolchain locally, I also provide a prebuilt xcframework version if you want to quickly try it.