Why is (any Any).Type different to any Any.Type?

Why is (any Any).Type different to any Any.Type :sob:

That's it. That's the post.

  • for any concrete T.Type, it can be upcast to any Any.Type
  • (any Any).Type can be implicitly opened to some concrete T.Type

Why the assymmetry?

Is it possible to convert from one to the other (and back again)?

any Any.Type is an existential container which can store any concrete metatype. You can also spell it as Any.Type.

(any Any).Type is specifically the type of the Any type.

Int.Type is a subtype of any Any.Type. However, Int.Type is not a subtype of (any Any).Type.

1 Like


So prior to the introduction of the any keyword, there was no way to spell "the type of the Any type"?

And why the assymmetry? Like, if I have:

protocol P {}
struct S: P {}

I expect that I can both upcast an instance of S to any P, and open an existential of type any P back to a generic of type S.

But when .Type gets involved, I can upcast String.self (of type String.Type) to any Any.Type, but I can't open any Any.Type back to a generic of type String.Type. I can open (any Any).Type back to a generic of type String.Type, though. If I knew how to get an (any Any).Type representing String.self?

The "protocol metatype" of Any, or the singleton metatype of the existential type Any, was (and still can be) spelled Any.Protocol, but is additionally now spelled (any Any).Type.

The "existential metatype" which used to be spelled Any.Type can now also be spelled any Any.Type, but just as for Any the new keyword is considered optional for the existential metatype.

...existential opening also works with metatypes:

protocol P { }
struct S: P { }

func h<T: P>(_ x: T.Type) {
h(S.self) // prints "S"

func i(_ x: any P.Type) {
i(S.self) // prints "S"

Yeah, I can't explain why existential opening specifically doesn't work currently when it comes to Any.Type (and also AnyObject.Type):

func j<T>(_ x: T.Type) {
func k(_ x: Any.Type) {
    // error: cannot convert value of type 'any Any.Type' to
    // expected argument type 'T.Type'

Seems like a bug? cc @hborla
(At a minimum, the diagnostics that arise here are hilariously off-base, which is itself a bug.)

1 Like

is (any P).Type equivalent to P.Protocol for any protocol P?

Yeah, P.Protocol is the older syntax.