[swift-evolution] [Pitch] Refactor Metatypes

Adrian Zubarev adrian.zubarev at devandartist.com
Fri Sep 30 14:09:14 CDT 2016

About the proposed names:

To be crystal clear we could use more descriptive names for our two types. Today T.Type is referred as *metatype* and serving two different purposes at once.

It’s a concrete type; we call it Type<T> or other suggested names looked like ExactType<T>, StaticType<T> etc.

T.Type is also the base type for all subtypes of T.

Protocols has one exception here.

1.1. The concrete type for protocols is not T.Type but T.Protocol.

2.1. T.Protocol has only one supertype, which is the existential (#2) Any.Type type.

Our proposal slices this behaviour into two different types, where you only can create a *concrete type* Type<T> with T.self or shadow a concrete type behind Subtype<U> with subtype(of:) function.

To be precise the correct names should be:

Metatype<T> for the concrete type (#1).
ExistentialMetatype<T> for the existential type (#2).
But we felt that we should adopt the existing name from T.Type and use the short form for the *concrete type* Type<T>.

Brent already showed in multiple examples but the question seems to come up over and over about the correct name of the current type(of:) function.

Imagine this scenario:

protocol P {}
struct A : P {}

let proto: P = A()
let any: Any = proto

// the old behaviour looked like this

// *concrete* `A.Type` is hidden behind the existential `Any.Type`
let anyMetatype: Any.Type = any.dynamicType  

anyMetatype is P.Type //=> true `P.Type` is the existential type here
anyMetatype is A.Type //=> true
let aMetatype = anyMetatype as! A.Type // Okay

// today `type(of:)` does the same trick

// After this proposal:
// subtype<T>(of instance: T) -> Subtype<T>

// The function will extract `Type<A>` for `any` but shadow it behind `Subtype<Any>`
let anyMetatype: `Subtype<Any>` = subtype(of: any)

// The correct relationship look like this:
// Subtype<P> : Subtype<Any>
// Subtype<A> : Subtype<P>
// Type<A> : Subtype<A>

anyMetatype is Subtype<P> //=> true
anyMetatype is Subtype<A> //=> true
anyMetatype is Type<A>    //=> true
anyMetatype is Type<P>    //=> false
anyMetatype is Type<Any>  //=> false
let aMetatype_1 = anyMetatype as! Subtype<A> // Okay
let aMetatype_2 = anyMetatype as! Type<A>    // Okay
subtype(of:) function extracts the *concrete type* from the given instance but shadows it behind the *existential type* equal to the type of the given instance.

subtype(of: T) returns a existential metatype instance Subtype<T> where in reality it’s a concrete metatype Type<U> with the relationship like U : T.

This is exact the same behaviour as the old .dynamicType had.

I hope that cleared some raising questions.

Adrian Zubarev
Sent with Airmail

Am 30. September 2016 um 09:00:53, Goffredo Marocchi via swift-evolution (swift-evolution at swift.org) schrieb:

Calling it SuperTypeOf<T> and SubTypeOf<T> would make it less confusing as that is how I read it in my mind in your last example.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160930/5b6c10cf/attachment.html>

More information about the swift-evolution mailing list