2021年4月11日星期日

Why does type(of:) return Metatype, rather than T.Type?

I noticed that type(of:) has this unexpected signature:

func type<T, Metatype>(of value: T) -> Metatype  

whereas I would have expected:

func type<T>(of value: T) -> T.Type  

The actual signature somehow takes 2 independent and unbounded type parameters, uses one of them as the parameter type, and the other as the return type. This seems to suggest that I can do something silly like this:

let foo: String = type(of: 1) // T is Int, Metatype is String  

But when I actually tried it,

Cannot convert value of type 'Int.Type' to specified type 'String'

So I don't get to specify Metatype after all, even though it's a generic type parameter. I was curious how the compiler did this, so I went to the source code and checked. I think what's preventing me from doing that silly thing is this @_semantics annotation:

@_transparent  @_semantics("typechecker.type(of:)")  public func type<T, Metatype>(of value: T) -> Metatype {  

I also saw some comments explaining that the implementation written here isn't actually called, and that this is directly handled by the type checker itself. But that doesn't answer my question - why does type(of:) return a completely unrelated type parameter Metatype, rather than T.Type?

My guess is that there is some edge case where type(of:) will return a completely unrelated type to T, but I have no idea what that is.

https://stackoverflow.com/questions/67051520/why-does-typeof-return-metatype-rather-than-t-type April 12, 2021 at 08:59AM

没有评论:

发表评论