[Pitch] Refactor Metatypes

I’ll join the conversation tomorrow. Thanks to Brent for his huge contribution. :)

Just a quick side note:

Moving from T.Type and T.Protocol to Type<T> and Subtype<T> would also allow us to finally reuse and correctly nest our custom Type and Protocol types.
struct A {
   struct Type {}
}

A.Type() // <— Yeay
This proposal also aims to fix the problem with generics where any protocol metatype was converted to P.Protocol.

···

--
Adrian Zubarev
Sent with Airmail

Am 30. September 2016 um 06:22:34, Xiaodi Wu via swift-evolution (swift-evolution@swift.org) schrieb:

What does the proposal offer that goes beyond what we currently have?

Can you elaborate on your two reasons for the proposed Type<T>?

In particular, what do you mean by inheritable and non-inheritable members of T? Where do these come into play? How is the current T.Type deficient in this respect?

Consider a snippet of code like this:

  class A { init(a: Int) { } }
  class B: A { init(b: Int) { super.init(a: b) } }

You can call `A.init(a:)` directly:

  A(a: 0)
  A.self.init(a: 0)

However, if you try to assign `A`'s type instance to a variable and do it through there, you can't:

  let aType: A.Type = A.self
  aType.init(a: 0) // Error: constructing an object of class type 'A' with a metatype value must use a 'required' initializer

This is a reflection of the fact that an `A.Type` could be `A.self` or `B.self` (or any other subclass of `A`), and `B.self` may not have an `init(a:)`.

`Type<A>` does not have this problem because it *is* guaranteed to be an `A`. It can express initializers and potentially anything else we might add that doesn't get inherited.

Of course, that isn't hugely useful right now because `Type<T>` only has one instance, and you can just refer to that instance directly. But I don't like that this distinction is unutterable; `Type<T>` corrects that.

And I think we may have features in the future where this is useful. For instance, if reflection ever gains the ability to access non-stored-property members, the distinction between `Subtype<T>` and `Type<T>` may become important. And if we ever get the ability to conform metatypes to protocols, I think non-inheritable conformances may be a good thing.

Regarding (2), it is already possible to do precise type matches using `==` instead of `is` (see corelibs-foundation for extensive uses). What does the proposal offer that goes beyond what we currently have?

`as?` compatibility, I suppose? Honestly, that's just something I noticed when I was writing it up. It might not be important.

···

On Sep 29, 2016, at 9:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

--
Brent Royal-Gordon
Architechies

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@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.

Goffredo Marocchi wrote:

I think the names should be bikeshedded more still. From your examples they seem to make sense when I mentally add Of like TypeOf<> and SubTypeOf<>, but since you are not commenting on why that is wrong or right or misleading, or at least I have missed your reply on that, I am still a bit at loss. Maybe we need other words altogether?

OTOH, we don't have ArrayOf<Element> or DictionaryOfKeyAndValue<Key, Value>, while we still pronounce them that way. I don't think prepositions belong in the name of types but in exceptional cases, and this doesn't sound exceptional enough to me.

— Pyry

The problem I was describing is about nested types named .Type, indeed. Assuming the proposal would go with Type<T>, then it means you _might_ be able to create nested types called Type, but you always would need to call if through the whole namespace (e.g. A.B.Type). That is a huge downside.

Metatype on the other hand describes exactly what that _thing_ really is.

Currently on a different branch I added this important note to the alternatives, but I’d rather use these types for the whole proposal.

Assuming that the accepted proposal decides to use Metatype<T>, AnyMetatype<T> over Type<T> and AnyType<T> would imply that the type Type would no longer be ambiguous to use in custome modules. However, such naming choice will affect the type(of:) function. It might be necessary to align the function name to metatype(of:) to avoid any confusion, which will result in another breaking change. Alternatively we could leave the function as func type<T>(of instance: T) -> AnyMetatype<T>.
If we’re going for breaking changes again than I’d prefer to align the magical type(of:) function to metatype(of:).

I’d love to hear more input on this.

···

--
Adrian Zubarev
Sent with Airmail

Am 18. Februar 2017 um 17:00:27, Anton Zhilin (antonyzhilin@gmail.com) schrieb:

Type is a bad name for a public type:
FooType is almost always a better name. Libraries that describe “just types”, Swift types, can as well use
Metatype or
Mirror or something.
For nested types, like
Foo.Type, in the meaning of “type of
Foo“,
Type can’t be used even now.
I’d give up on
Type name for the greater future of metatypes.

2017-02-18 16:28 GMT+03:00 Adrian Zubarev <adrian.zubarev@devandartist.com>:

Personally I’d prefer Metatype<T> and AnyMetatype<T> to get rid of the restriction where you mostly cannot create custom types called Type, which annoys me a lot. Sometimes Kind as a good workaround but there are times where Kind doesn’t fit. :/

Actually Brent has just now convinced me that Metatype would be a bad name to choose. So forget what I said in my last messages.

···

--
Adrian Zubarev
Sent with Airmail

Am 18. Februar 2017 um 17:55:33, Adrian Zubarev (adrian.zubarev@devandartist.com) schrieb:

The problem I was describing is about nested types named .Type, indeed. Assuming the proposal would go with Type<T>, then it means you _might_ be able to create nested types called Type, but you always would need to call if through the whole namespace (e.g. A.B.Type). That is a huge downside.

Metatype on the other hand describes exactly what that _thing_ really is.

Currently on a different branch I added this important note to the alternatives, but I’d rather use these types for the whole proposal.

Assuming that the accepted proposal decides to use Metatype<T>, AnyMetatype<T> over Type<T> and AnyType<T> would imply that the type Type would no longer be ambiguous to use in custome modules. However, such naming choice will affect the type(of:) function. It might be necessary to align the function name to metatype(of:) to avoid any confusion, which will result in another breaking change. Alternatively we could leave the function as func type<T>(of instance: T) -> AnyMetatype<T>.
If we’re going for breaking changes again than I’d prefer to align the magical type(of:) function to metatype(of:).

I’d love to hear more input on this.

--
Adrian Zubarev
Sent with Airmail

Am 18. Februar 2017 um 17:00:27, Anton Zhilin (antonyzhilin@gmail.com) schrieb:

Type is a bad name for a public type:
FooType is almost always a better name. Libraries that describe “just types”, Swift types, can as well use
Metatype or
Mirror or something.
For nested types, like
Foo.Type, in the meaning of “type of
Foo“,
Type can’t be used even now.
I’d give up on
Type name for the greater future of metatypes.

2017-02-18 16:28 GMT+03:00 Adrian Zubarev <adrian.zubarev@devandartist.com>:

Personally I’d prefer Metatype<T> and AnyMetatype<T> to get rid of the restriction where you mostly cannot create custom types called Type, which annoys me a lot. Sometimes Kind as a good workaround but there are times where Kind doesn’t fit. :/

Sorry, my question at least has nothing to do with bikeshedding. I'm
confused about why the proposal feels it's necessary to have both Type and
Subtype. I don't understand Brent's two reasons and was hoping for some
elaboration. I've tried to clarify my question in a gist:

···

On Fri, Sep 30, 2016 at 2:09 PM, Adrian Zubarev via swift-evolution < swift-evolution@swift.org> wrote:

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.

   1.

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

   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@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.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

This is a very clear answer. So for my understanding, what you're saying
is: without other language features not yet proposed, `Type<T>` does not in
itself enable a particularly notable use case that's not currently possible
today. It is being included in this proposal because the original design of
Swift lumped two things together for simplicity, but you disagree with that
design decision and want the distinction to be utterable. Is that more or
less the gist of it?

···

On Fri, Sep 30, 2016 at 5:56 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

> On Sep 29, 2016, at 9:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
>
> Can you elaborate on your two reasons for the proposed Type<T>?
>
> In particular, what do you mean by inheritable and non-inheritable
members of T? Where do these come into play? How is the current T.Type
deficient in this respect?

Consider a snippet of code like this:

        class A { init(a: Int) { } }
        class B: A { init(b: Int) { super.init(a: b) } }

You can call `A.init(a:)` directly:

        A(a: 0)
        A.self.init(a: 0)

However, if you try to assign `A`'s type instance to a variable and do it
through there, you can't:

        let aType: A.Type = A.self
        aType.init(a: 0) // Error: constructing an object
of class type 'A' with a metatype value must use a 'required' initializer

This is a reflection of the fact that an `A.Type` could be `A.self` or
`B.self` (or any other subclass of `A`), and `B.self` may not have an
`init(a:)`.

`Type<A>` does not have this problem because it *is* guaranteed to be an
`A`. It can express initializers and potentially anything else we might add
that doesn't get inherited.

Of course, that isn't hugely useful right now because `Type<T>` only has
one instance, and you can just refer to that instance directly. But I don't
like that this distinction is unutterable; `Type<T>` corrects that.

And I think we may have features in the future where this is useful. For
instance, if reflection ever gains the ability to access
non-stored-property members, the distinction between `Subtype<T>` and
`Type<T>` may become important. And if we ever get the ability to conform
metatypes to protocols, I think non-inheritable conformances may be a good
thing.

> Regarding (2), it is already possible to do precise type matches using
`==` instead of `is` (see corelibs-foundation for extensive uses). What
does the proposal offer that goes beyond what we currently have?

`as?` compatibility, I suppose? Honestly, that's just something I noticed
when I was writing it up. It might not be important.

--

Brent Royal-Gordon
Architechies

I replied on your gist directly, but you can also read my reply below.

I though I made it crystal clear in my last post what the main problem is.

Again:

T.Type serves two jobs at once.

It’s a concrete metatype of T.
It’s an existential metatype of T where other metatypes where U is a subtype of T (U : T) are subtypes of this existential metatype.
Forget about protocols for a moment:

struct S { }

let metatype_1: Any.Type = S.self // <~~ (concrete) metatype
// ~~~~~~~~~~~~ ^ existential metatype

let metatype_s: S.Type = S.self // <~~ (concrete) metatype
// ~~~~~~~~~~~~ ^ existential metatype

/*
   The relationship looks here like this
    
   (concrete metatype) `T.Type : T.Type` (existential metatype)
    
   OR for the given example: `S.Type : S.Type : Any.Type` (last one is again an existential metatype)
   This looks confusing right?
*/

class B { }
class D : B { }

let metatype_b: B.Type = B.self // <~~ (concrete) metatype
// ~~~~~~~~~~~~ ^ existential metatype

metatype_b is D.Type // false

let metatype_d: D.Type = D.self // <~~ (concrete) metatype
// ~~~~~~~~~~~~ ^ existential metatype

let metatype_2: B.Type = metatype_d // Totally fine
let metatype_3: Any.Type = metatype_2 // Okay

metatype_3 is D.Type // true

/*
   Relationship:
    
   (existential metatype) `B.Type : Any.Type` (existential metatype)
   (concrete metatype) `B.Type : B.Type` (existential metatype)
    
   (existential metatype) `D.Type : B.Type` (existential metatype)
   (concrete metatype) `D.Type : D.Type` (existential metatype)
*/
It should be clear by now that there is this odd T.Type : T.Type relationship. We want to correct this behaviour + solve the problem that raises with protocols with one simple and single design.

Let’s see what happens with protocols:

protocol P { }

let metatype_p: P.Type = P.self // Error, because the concrete metatype is not a subtype of the existential metatype of P

// Furthermore `P.self` is `P.Protocol`

let metatype_3: Any.Type = P.self // fine <~~ (concrete) metatype
// ~~~~~~~~~~~~ ^ existential metatype

/*
   Relationship:
   (concrete metatype) `P.Protocol : Any.Type` (existential metatype)
   (existential metatype) `P.Type : Any.Type` (existential metatype)
    
   At this time `P.Type : Any.Type` is an existential metatype that exists but it does not have any subtypes!
*/

struct I : P { }

let metatype_i: I.Type = I.self // <~~ (concrete) metatype
// ~~~~~~~~~~~~ ^ existential metatype

let metatype_4: P.Type = metatype_i // fine
// ~~~~~~~~~~~~ ^ existential metatype

metatype_4 is I.Type // true

/*
   Relationship:
   (existential metatype) `P.Type : Any.Type` (existential metatype)
   (existential metatype) `I.Type : P.Type` (existential metatype)
   (concrete metatype) `I.Type : I.Type` (existential metatype)
*/
There is a huge overlap in the current design. I hope this cleared your question here.

Side note: The following function isn’t possible to implement with the current T.Type design because in generic context a protocol will end up T.Protocol.

func dynamic<T>(subtype: Subtype<Any>, `is` _: Type<T>) -> Bool {
  return type is Subtype<T>
}
The proposed design however solves these problems and the relationship becomes clearer:

(existential metatype) `Subtype<B> : Subtype<Any>` (existential metatype)
(concrete metatype) `Type<B> : Subtype<B>` (existential metatype)
    
(existential metatype) `Subtype<D> : Subtype<B>` (existential metatype)
(concrete metatype) `Type<D> : Subtype<D>` (existential metatype)

(existential metatype) `Subtype<P> : Subtype<Any>` (existential metatype)
(concrete metatype) `Type<P> : Subtype<Any>` (existential metatype)

(existential metatype) `Subtype<P> : Subtype<Any>` (existential metatype)
(existential metatype) `Subtype<I> : Subtype<P>` (existential metatype)
(concrete metatype) `Type<I> : Subtype<I>` (existential metatype)
The only way to work with Subtype<T> is by using subtype(of:) function of by manually shadowing a concrete metatype Type<T>.

The only way to instantiate a concrete metatype is done with T.self.

···

--
Adrian Zubarev
Sent with Airmail

Am 30. September 2016 um 21:48:39, Xiaodi Wu (xiaodi.wu@gmail.com) schrieb:

Sorry, my question at least has nothing to do with bikeshedding. I'm confused about why the proposal feels it's necessary to have both Type and Subtype. I don't understand Brent's two reasons and was hoping for some elaboration. I've tried to clarify my question in a gist:

On Fri, Sep 30, 2016 at 2:09 PM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:
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@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.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Sorry, my question at least has nothing to do with bikeshedding. I'm

confused about why the proposal feels it's necessary to have both Type and
Subtype. I don't understand Brent's two reasons and was hoping for some
elaboration. I've tried to clarify my question in a gist:

Metatypes in Swift · GitHub

Regardless of syntax, there are Metatype<T> and ExistentialMetatype<T>
“under the hood”. I’ll take the liberty to use these names for this post.

Purpose and difference between the two kinds of metatypes is easy to
understand. If it helps, size of Metatype<T> is typically 0 while size of
ExistentialMetatype<T> is typically 8.

NOTE: Metatype<P> can’t be a subtype of ExistentialMetatype<P> for
protocols P, because protocols do not implement their own static
requirements.

Apparently, creators of Swift also thought that two kinds of metatypes are
too difficult for an average developer. So an attempt was made to unify
both under a single name, T.Type. For “final” types like structs, T.Type
maps onto Metatype<T>. For classes and protocols, T.Type maps onto
ExistentialMetatype<T>.

This abstraction turned out to be leaky. I’ll give 3 leaks.

   1. Because of Note, we could not have ID of a protocol itself inside of
   any kind of metatype. This feature was needed in real code. The solution
   was to add T.Protocol syntax that could only be used for protocols to
   create a Metatype<T>. But this solution created a plethora of other
   inconsistencies and abstraction leaks (which were explored by Adrian).
   Arguably the most important is (2).
   2. In generic functions accepting T.Type, passing T.self creates an
   instance of T.Protocol, which is still described in code as T.Type.
   *boom!*
   3. Accepting static metatypes in functions is often what people want.
   Consider the following basic example:

func create<T: Creatable>(type: T.Type)

Most probably, create does not read contents of type to deal with
appropriate subtype. It does not support existentiality, type is here for
function specialization. But in case T is subtypable, we still pass around
those 8 bytes that are not used by the create, confusing both compiler and
some developers. In 90% cases, when we see such a function, it throws off
value of metatype instance.

···

2016-09-30 22:48 GMT+03:00 Xiaodi Wu via swift-evolution < swift-evolution@swift.org>:

That’s right. I was about to say something similar about the Of.

Actually Type<T> would be the correct name for the static/concrete metatype.

We already have this notation but not in a generic way T.Type
If we add of only in our mind to Type<T>, we’ll get “Type of a type T” which is shortly referred as a “metatype of T”. (Array<Element> - Array of Element type)
Since Subtype<T> in reality is some *existential metatype* and the whole talk about existential types now tend to have the Any prefix, lets follow that trend here too.

Type<T> - (static/concrete/exact) metatype.
AnyType<T> - existential metatype.
It might be even easier to memorise this name than Subtype.

The example from the proposal rewritten:

// Types:
protocol Foo {}
protocol Boo : Foo {}
class A : Foo {}
class B : A, Boo {}
struct S : Foo {}

// Metatypes:
let a1: Type<A> = A.self //=> Okay
let p1: Type<Foo> = Foo.self //=> Okay
let p2: Type<Boo> = C.self //=> Error -- `C` is not the same as `Foo`

let any_1: AnyType<Any> = A.self //=> Okay
let any_2: AnyType<Any> = Foo.self //=> Okay

let a_1: AnyType<A> = A.self //=> Okay
let p_1: AnyType<Foo> = A.self //=> Okay
let p_2: AnyType<Foo> = Foo.self //=> Error -- `Type<Foo>` is not a subtype of `AnyType<Foo>`

// Generic functions:
func dynamic<T>(type: AnyType<Any>, `is` _: Type<T>) -> Bool {
  return type is AnyType<T>
}

func dynamic<T>(type: AnyType<Any>, `as` _: Type<T>) -> AnyType<T>? {
  return type as? AnyType<T>
}

let s1: Type<S> = S.self

dynamic(type: s1, is: Foo.self) //=> true
dynamic(type: s1, as: Foo.self) //=> an `Optional<AnyType<Foo>>`
The type(of:) function could now stay, because now we’d only need to change the return type.

func type<T>(of instance: T) -> AnyType<T>
Isn’t this a good compromise?

···

--
Adrian Zubarev
Sent with Airmail

Am 2. Oktober 2016 um 09:01:45, Pyry Jahkola via swift-evolution (swift-evolution@swift.org) schrieb:

OTOH, we don't have ArrayOf<Element> or DictionaryOfKeyAndValue<Key, Value>, while we still pronounce them that way. I don't think prepositions belong in the name of types but in exceptional cases, and this doesn't sound exceptional enough to me.

That sounds very good to me, and AnyType<T> aligns well with the proposed Any<...> syntax.

— Pyry

···

Adrian Zubarev wrote:

That’s right. I was about to say something similar about the Of.

Actually Type<T> would be the correct name for the static/concrete metatype.

We already have this notation but not in a generic way T.Type
If we add of only in our mind to Type<T>, we’ll get “Type of a type T” which is shortly referred as a “metatype of T”. (Array<Element> - Array of Element type)
Since Subtype<T> in reality is some *existential metatype* and the whole talk about existential types now tend to have the Any prefix, lets follow that trend here too.

Type<T> - (static/concrete/exact) metatype.
AnyType<T> - existential metatype.
It might be even easier to memorise this name than Subtype.

The example from the proposal rewritten:

// Types:
protocol Foo {}
protocol Boo : Foo {}
class A : Foo {}
class B : A, Boo {}
struct S : Foo {}

// Metatypes:
let a1: Type<A> = A.self //=> Okay
let p1: Type<Foo> = Foo.self //=> Okay
let p2: Type<Boo> = C.self //=> Error -- `C` is not the same as `Foo`

let any_1: AnyType<Any> = A.self //=> Okay
let any_2: AnyType<Any> = Foo.self //=> Okay

let a_1: AnyType<A> = A.self //=> Okay
let p_1: AnyType<Foo> = A.self //=> Okay
let p_2: AnyType<Foo> = Foo.self //=> Error -- `Type<Foo>` is not a subtype of `AnyType<Foo>`

// Generic functions:
func dynamic<T>(type: AnyType<Any>, `is` _: Type<T>) -> Bool {
  return type is AnyType<T>
}

func dynamic<T>(type: AnyType<Any>, `as` _: Type<T>) -> AnyType<T>? {
  return type as? AnyType<T>
}

let s1: Type<S> = S.self

dynamic(type: s1, is: Foo.self) //=> true
dynamic(type: s1, as: Foo.self) //=> an `Optional<AnyType<Foo>>`
The type(of:) function could now stay, because now we’d only need to change the return type.

func type<T>(of instance: T) -> AnyType<T>
Isn’t this a good compromise?

--
Adrian Zubarev
Sent with Airmail

Am 2. Oktober 2016 um 09:01:45, Pyry Jahkola via swift-evolution (swift-evolution@swift.org) schrieb:

OTOH, we don't have ArrayOf<Element> or DictionaryOfKeyAndValue<Key, Value>, while we still pronounce them that way. I don't think prepositions belong in the name of types but in exceptional cases, and this doesn't sound exceptional enough to me.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Love it :)!

···

Sent from my iPhone

On 2 Oct 2016, at 09:37, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

That’s right. I was about to say something similar about the Of.

Actually Type<T> would be the correct name for the static/concrete metatype.

We already have this notation but not in a generic way T.Type
If we add of only in our mind to Type<T>, we’ll get “Type of a type T” which is shortly referred as a “metatype of T”. (Array<Element> - Array of Element type)
Since Subtype<T> in reality is some *existential metatype* and the whole talk about existential types now tend to have the Any prefix, lets follow that trend here too.

Type<T> - (static/concrete/exact) metatype.
AnyType<T> - existential metatype.
It might be even easier to memorise this name than Subtype.

The example from the proposal rewritten:

// Types:
protocol Foo {}
protocol Boo : Foo {}
class A : Foo {}
class B : A, Boo {}
struct S : Foo {}

// Metatypes:
let a1: Type<A> = A.self //=> Okay
let p1: Type<Foo> = Foo.self //=> Okay
let p2: Type<Boo> = C.self //=> Error -- `C` is not the same as `Foo`

let any_1: AnyType<Any> = A.self //=> Okay
let any_2: AnyType<Any> = Foo.self //=> Okay

let a_1: AnyType<A> = A.self //=> Okay
let p_1: AnyType<Foo> = A.self //=> Okay
let p_2: AnyType<Foo> = Foo.self //=> Error -- `Type<Foo>` is not a subtype of `AnyType<Foo>`

// Generic functions:
func dynamic<T>(type: AnyType<Any>, `is` _: Type<T>) -> Bool {
  return type is AnyType<T>
}

func dynamic<T>(type: AnyType<Any>, `as` _: Type<T>) -> AnyType<T>? {
  return type as? AnyType<T>
}

let s1: Type<S> = S.self

dynamic(type: s1, is: Foo.self) //=> true
dynamic(type: s1, as: Foo.self) //=> an `Optional<AnyType<Foo>>`
The type(of:) function could now stay, because now we’d only need to change the return type.

func type<T>(of instance: T) -> AnyType<T>
Isn’t this a good compromise?

--
Adrian Zubarev
Sent with Airmail

Am 2. Oktober 2016 um 09:01:45, Pyry Jahkola via swift-evolution (swift-evolution@swift.org) schrieb:

OTOH, we don't have ArrayOf<Element> or DictionaryOfKeyAndValue<Key, Value>, while we still pronounce them that way. I don't think prepositions belong in the name of types but in exceptional cases, and this doesn't sound exceptional enough to me.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

We added a note to the proposal:

Both Type<T> and AnyType<T> will be declared in the Swift standard library even if part of the implementation might be compiler magic. That move is really important to allow developers to created custom nested types named as Type. ModuleName.TypeName.Type is ambigious today, but will become possible after this proposal. That means Type<T> and AnyType<T> will be shortcuts for Swift.Type<T> and Swift.AnyType<T>.
We also think that the proposal is ready for the review. :)

···

--
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 09:40:19, Adrian Zubarev (adrian.zubarev@devandartist.com) schrieb:

Actually Brent has just now convinced me that Metatype would be a bad name to choose. So forget what I said in my last messages.

--
Adrian Zubarev
Sent with Airmail

Am 18. Februar 2017 um 17:55:33, Adrian Zubarev (adrian.zubarev@devandartist.com) schrieb:

The problem I was describing is about nested types named .Type, indeed. Assuming the proposal would go with Type<T>, then it means you _might_ be able to create nested types called Type, but you always would need to call if through the whole namespace (e.g. A.B.Type). That is a huge downside.

Metatype on the other hand describes exactly what that _thing_ really is.

Currently on a different branch I added this important note to the alternatives, but I’d rather use these types for the whole proposal.

Assuming that the accepted proposal decides to use Metatype<T>, AnyMetatype<T> over Type<T> and AnyType<T> would imply that the type Type would no longer be ambiguous to use in custome modules. However, such naming choice will affect the type(of:) function. It might be necessary to align the function name to metatype(of:) to avoid any confusion, which will result in another breaking change. Alternatively we could leave the function as func type<T>(of instance: T) -> AnyMetatype<T>.
If we’re going for breaking changes again than I’d prefer to align the magical type(of:) function to metatype(of:).

I’d love to hear more input on this.

--
Adrian Zubarev
Sent with Airmail

Am 18. Februar 2017 um 17:00:27, Anton Zhilin (antonyzhilin@gmail.com) schrieb:

Type is a bad name for a public type:
FooType is almost always a better name. Libraries that describe “just types”, Swift types, can as well use
Metatype or
Mirror or something.
For nested types, like
Foo.Type, in the meaning of “type of
Foo“,
Type can’t be used even now.
I’d give up on
Type name for the greater future of metatypes.

2017-02-18 16:28 GMT+03:00 Adrian Zubarev <adrian.zubarev@devandartist.com>:

Personally I’d prefer Metatype<T> and AnyMetatype<T> to get rid of the restriction where you mostly cannot create custom types called Type, which annoys me a lot. Sometimes Kind as a good workaround but there are times where Kind doesn’t fit. :/

You can read the updated version of the proposal on a sub-branch: swift-evolution/0126-refactor-metatypes.md at refactor_existential_metatypes · DevAndArtist/swift-evolution · GitHub

···

--
Adrian Zubarev
Sent with Airmail

Am 2. Oktober 2016 um 11:47:50, Goffredo Marocchi (panajev@gmail.com) schrieb:

Love it :)!

Sent from my iPhone

On 2 Oct 2016, at 09:37, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

That’s right. I was about to say something similar about the Of.

Actually Type<T> would be the correct name for the static/concrete metatype.

We already have this notation but not in a generic way T.Type
If we add of only in our mind to Type<T>, we’ll get “Type of a type T” which is shortly referred as a “metatype of T”. (Array<Element> - Array of Element type)
Since Subtype<T> in reality is some *existential metatype* and the whole talk about existential types now tend to have the Any prefix, lets follow that trend here too.

Type<T> - (static/concrete/exact) metatype.
AnyType<T> - existential metatype.
It might be even easier to memorise this name than Subtype.

The example from the proposal rewritten:

// Types:
protocol Foo {}
protocol Boo : Foo {}
class A : Foo {}
class B : A, Boo {}
struct S : Foo {}

// Metatypes:
let a1: Type<A> = A.self //=> Okay
let p1: Type<Foo> = Foo.self //=> Okay
let p2: Type<Boo> = C.self //=> Error -- `C` is not the same as `Foo`

let any_1: AnyType<Any> = A.self //=> Okay
let any_2: AnyType<Any> = Foo.self //=> Okay

let a_1: AnyType<A> = A.self //=> Okay
let p_1: AnyType<Foo> = A.self //=> Okay
let p_2: AnyType<Foo> = Foo.self //=> Error -- `Type<Foo>` is not a subtype of `AnyType<Foo>`

// Generic functions:
func dynamic<T>(type: AnyType<Any>, `is` _: Type<T>) -> Bool {
  return type is AnyType<T>
}

func dynamic<T>(type: AnyType<Any>, `as` _: Type<T>) -> AnyType<T>? {
  return type as? AnyType<T>
}

let s1: Type<S> = S.self

dynamic(type: s1, is: Foo.self) //=> true
dynamic(type: s1, as: Foo.self) //=> an `Optional<AnyType<Foo>>`
The type(of:) function could now stay, because now we’d only need to change the return type.

func type<T>(of instance: T) -> AnyType<T>
Isn’t this a good compromise?

--
Adrian Zubarev
Sent with Airmail

Am 2. Oktober 2016 um 09:01:45, Pyry Jahkola via swift-evolution (swift-evolution@swift.org) schrieb:

OTOH, we don't have ArrayOf<Element> or DictionaryOfKeyAndValue<Key, Value>, while we still pronounce them that way. I don't think prepositions belong in the name of types but in exceptional cases, and this doesn't sound exceptional enough to me.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Where can I find a link to an updated version?

···

On 19 Feb 2017, at 21:42, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

We added a note to the proposal:

Both Type<T> and AnyType<T> will be declared in the Swift standard library even if part of the implementation might be compiler magic. That move is really important to allow developers to created custom nested types named as Type. ModuleName.TypeName.Type is ambigious today, but will become possible after this proposal. That means Type<T> and AnyType<T> will be shortcuts for Swift.Type<T> and Swift.AnyType<T>.
We also think that the proposal is ready for the review. :)

--
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 09:40:19, Adrian Zubarev (adrian.zubarev@devandartist.com <mailto:adrian.zubarev@devandartist.com>) schrieb:

Actually Brent has just now convinced me that Metatype would be a bad name to choose. So forget what I said in my last messages.

--
Adrian Zubarev
Sent with Airmail

Am 18. Februar 2017 um 17:55:33, Adrian Zubarev (adrian.zubarev@devandartist.com <mailto:adrian.zubarev@devandartist.com>) schrieb:

The problem I was describing is about nested types named .Type, indeed. Assuming the proposal would go with Type<T>, then it means you _might_ be able to create nested types called Type, but you always would need to call if through the whole namespace (e.g. A.B.Type). That is a huge downside.

Metatype on the other hand describes exactly what that _thing_ really is.

Currently on a different branch I added this important note to the alternatives, but I’d rather use these types for the whole proposal.

Assuming that the accepted proposal decides to use Metatype<T>, AnyMetatype<T> over Type<T> and AnyType<T> would imply that the type Type would no longer be ambiguous to use in custome modules. However, such naming choice will affect the type(of:) function. It might be necessary to align the function name to metatype(of:) to avoid any confusion, which will result in another breaking change. Alternatively we could leave the function as func type<T>(of instance: T) -> AnyMetatype<T>.
If we’re going for breaking changes again than I’d prefer to align the magical type(of:) function to metatype(of:).

I’d love to hear more input on this.

--
Adrian Zubarev
Sent with Airmail

Am 18. Februar 2017 um 17:00:27, Anton Zhilin (antonyzhilin@gmail.com <mailto:antonyzhilin@gmail.com>) schrieb:

Type is a bad name for a public type:
FooType is almost always a better name. Libraries that describe “just types”, Swift types, can as well use
Metatype or
Mirror or something.
For nested types, like
Foo.Type, in the meaning of “type of
Foo“,
Type can’t be used even now.
I’d give up on
Type name for the greater future of metatypes.

2017-02-18 16:28 GMT+03:00 Adrian Zubarev <adrian.zubarev@devandartist.com <mailto:adrian.zubarev@devandartist.com>>:

Personally I’d prefer Metatype<T> and AnyMetatype<T> to get rid of the restriction where you mostly cannot create custom types called Type, which annoys me a lot. Sometimes Kind as a good workaround but there are times where Kind doesn’t fit. :/

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I’d say that subtype is correct there. As mentioned by some people here subtype feels like it has something to do with classes.

Assume this:

class Base { init() {...} }
class A : Base {}
     
let subtype: AnyType<Base> = subtype(of: Base.self, named: "A")!
     
// One day when `.self` magic is gone
let subtype: AnyType<Base> = subtype(of: Base, named: "A")!
     
let a: Base = subtype.init()
     
print(type(of: a)) // => A
It’s clear that we’re working with classes here. type(of:named:) seems odd to me and doesn’t fit here at all.

Any more feedback?

Waiting for Brent to reply. I can’t remember what Subprotocol<T> was for. That’s the reason why it looks like this for the moment. ;)

I don’t understand. I renamed Subtype with AnyType everywhere and mentioned it in Alternatives considered section.

I’d like to wait for more feedback, we’re not in rush now.

···

--
Adrian Zubarev
Sent with Airmail

Am 2. Oktober 2016 um 16:46:18, Anton Zhilin (antonyzhilin@gmail.com) schrieb:

I’m happy that everyone seems to agree on the new naming, and I also like that
type function is back.

Some fixes:

In Future directions, replace
subtype with
type
In Future directions, remove overstruck last item
In Alternatives considered, replace the naming and add old naming to alternative options

···

--
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 22:59:18, David Hart (david@hartbit.com) schrieb:

Where can I find a link to an updated version?

On 19 Feb 2017, at 21:42, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

We added a note to the proposal:

Both Type<T> and AnyType<T> will be declared in the Swift standard library even if part of the implementation might be compiler magic. That move is really important to allow developers to created custom nested types named as Type. ModuleName.TypeName.Type is ambigious today, but will become possible after this proposal. That means Type<T> and AnyType<T> will be shortcuts for Swift.Type<T> and Swift.AnyType<T>.
We also think that the proposal is ready for the review. :)

--
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 09:40:19, Adrian Zubarev (adrian.zubarev@devandartist.com) schrieb:

Actually Brent has just now convinced me that Metatype would be a bad name to choose. So forget what I said in my last messages.

--
Adrian Zubarev
Sent with Airmail

Am 18. Februar 2017 um 17:55:33, Adrian Zubarev (adrian.zubarev@devandartist.com) schrieb:

The problem I was describing is about nested types named .Type, indeed. Assuming the proposal would go with Type<T>, then it means you _might_ be able to create nested types called Type, but you always would need to call if through the whole namespace (e.g. A.B.Type). That is a huge downside.

Metatype on the other hand describes exactly what that _thing_ really is.

Currently on a different branch I added this important note to the alternatives, but I’d rather use these types for the whole proposal.

Assuming that the accepted proposal decides to use Metatype<T>, AnyMetatype<T> over Type<T> and AnyType<T> would imply that the type Type would no longer be ambiguous to use in custome modules. However, such naming choice will affect the type(of:) function. It might be necessary to align the function name to metatype(of:) to avoid any confusion, which will result in another breaking change. Alternatively we could leave the function as func type<T>(of instance: T) -> AnyMetatype<T>.
If we’re going for breaking changes again than I’d prefer to align the magical type(of:) function to metatype(of:).

I’d love to hear more input on this.

--
Adrian Zubarev
Sent with Airmail

Am 18. Februar 2017 um 17:00:27, Anton Zhilin (antonyzhilin@gmail.com) schrieb:

Type is a bad name for a public type: FooType is almost always a better name. Libraries that describe “just types”, Swift types, can as well use Metatype or Mirror or something.
For nested types, like Foo.Type, in the meaning of “type of Foo“, Type can’t be used even now.
I’d give up on Type name for the greater future of metatypes.

2017-02-18 16:28 GMT+03:00 Adrian Zubarev <adrian.zubarev@devandartist.com>:

Personally I’d prefer Metatype<T> and AnyMetatype<T> to get rid of the restriction where you mostly cannot create custom types called Type, which annoys me a lot. Sometimes Kind as a good workaround but there are times where Kind doesn’t fit. :/

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Ups sorry. Found the mistake. Done.

···

--
Adrian Zubarev
Sent with Airmail

Am 2. Oktober 2016 um 17:40:47, Adrian Zubarev (adrian.zubarev@devandartist.com) schrieb:

I don’t understand. I renamed Subtype with AnyType everywhere and mentioned it in Alternatives considered section.

This is the latest draft of the proposal: swift-evolution/0126-refactor-metatypes.md at refactor_existential_metatypes · DevAndArtist/swift-evolution · GitHub

Refactor Metatypes

Proposal: SE–0126
Authors: Adrian Zubarev, Anton Zhilin, Brent Royal-Gordon
Status: Revision
Review manager: Chris Lattner
Revision: 2
Previous Revisions: 1
Introduction

This proposal removes .Type and .Protocol in favor of two generic-style syntaxes and aligns global type(of:) function (SE–0096) to match the changes.

Swift-evolution thread (post Swift 3):

[Pitch] Refactor Metatypes
Older swift-evolution threads: [1], [2], [3]

Motivation

Every type T has an instance, accessible through T.self, which represents the type itself. Like all instances in Swift, this “type instance” itself has a type, which is referred to as its “metatype”. The metatype of T is written T.Type. The instance members of the metatype are the same as the static or class members of the type.

Metatypes have subtype relationships which reflect the types they represent. For instance, given these types:

protocol Proto {}
class Base {}
class Derived: Base, Proto {}
Derived.Type is a subtype of both Base.Type and Proto.Type (and Any.Type). That means that Derived.self can be used anywhere a Derived.Type, Base.Type, Proto.Type, or Any.Type is called for.

Unfortunately, this simple picture is complicated by protocols. Proto.self is actually of type Proto.Protocol, not type Proto.Type. This is necessary because the protocol does not, and cannot, conform to itself; it requires conforming types to provide static members, but it doesn’t actually provide those members itself. Proto.Type still exists, but it is the supertype of all types conforming to the protocol.

Making this worse, a generic type always uses T.Type to refer to the type of T.self. So when Proto is bound to a generic parameter P, P.Type is the same as Proto.Protocol.

This shifting of types is complicated and confusing; we seek to clean up this area.

We also believe that, in the long term, the dot syntax will prevent us from implementing certain future enhancements that might be valuable:

Moving the implementation of metatypes at least partly into the standard library.
Adding members available on all type instances for features like read-write reflection or memory layout information.
Conforming metatypes to protocols like Hashable or CustomStringConvertible.
Offering straightforward syntaxes for dynamic features like looking up types by name.
Proposed solution

We abolish .Type and .Protocol in favor of two generic-style syntaxes:

Type<T> is the concrete type of T.self. A Type<T> only ever has one instance, T.self; even if T has a subtype U, Type<U> is not a subtype of Type<T>.

AnyType<T> is the supertype of all Types whose instances are subtypes of T, including T itself:

If T is a struct or enum, then Type<T> is the only subtype of AnyType<T>.

If T is a class, then Type<T> and the Types of all subclasses of T are subtypes of AnyType<T>.

If T is a protocol, then the Types of all concrete types conforming to T are subtypes of AnyType<T>. Type<T> is not itself a subtype of AnyType<T>, or of any AnyType other than AnyType<Any>.

Structural types follow the subtype/supertype relationships of their constituent types. For instance:

Type<(NSString, NSString)> is a subtype of AnyType<(NSObject, NSObject)>

Metatypes of functions are a little bit more special (the subtyping relation on functions flips around for parameter types):

Type<(Any) -> Void> is a subtype of AnyType<(Int) -> Void> etc.
Type<(Void) -> Int> is a subtype of AnyType<(Void) -> Any>
In this new notation, some of our existing standard library functions would have signatures like:

func unsafeBitCast<T, U>(_: T, to type: Type<U>) -> U
func ==(t0: AnyType<Any>?, t1: AnyType<Any>?) -> Bool
func type<T>(of instace: T) -> AnyType<T> // SE-0096
That last example, type(of:), is rather interesting, because it is actually a magic syntax rather than a function. We propose to align this syntax with Type and AnyType by correcting the return type to AnyType<T>. We believe this is clearer about both the type and meaning of the operation.

let anInstance: NSObject = NSString()
let aClass: AnyType<NSObject> = type(of: anInstance)

print(aClass) // => NSString
More details:

Every static or class member of T which can be called on all subtypes is an instance member of AnyType<T>. That includes:

Static/class properties and methods

Required initializers (as methods named init)

Unbound instance methods

The Type<T> of a concrete type T has all of the members required by AnyType<T>, plus non-required initializers.

The Type<T> of a protocol T includes only unbound instance methods of T.

If T conforms to P, then AnyType<T> is a subtype of AnyType<P>, even if T is a protocol.

The type of AnyType<T>.self is Type<AnyType<T>>.

The type of Type<T>.self is Type<Type<T>>, which is not a subtype of any type except AnyType<Type<T>>. There is an infinite regress of Type<...<Type<T>>>s.

AnyTypes are abstract types similar to class-bound protocols; they, too, support identity operations.

Types are concrete reference types which have identities just like objects do.

swift Int.self === Int.self // true Int.self === Any.self // false

Visual metatype relationship example (not a valid Swift code)
Some examples
Future Directions

We could allow extensions on Type and perhaps on AnyType to add members or conform them to protocols. This could allow us to remove some standard library hacks, like the non-Equatable-related == operators for types.

It may be possible to implement parts of Type as a fairly ordinary final class, moving code from the runtime into the standard library.

We could offer a new global function which would allow type-safe access to classes by name.

func subtype<T : AnyObject>(of type: Type<T>, named: String) -> AnyType<T>? { ... }
We could offer other reflection and dynamic features on Type and AnyType.

We could move the MemoryLayout members into Type (presumably prefixed), removing the rather artificial MemoryLayout enum.

Impact on existing code

This is a source-breaking change that can be automated by a migrator.

We suggest the following migration process; this can differ from the final migration process implemented by the core team if this proposal will be accepted:

Any.Type is migrated to AnyType<Any>.
If T.Type is in function parameter, where T is a generic type parameter, then it’s migrated to Type<T>.
Every T.Protocol will be replaced with Type<T>.
Every T.Type in a dynamic cast will be replaced with AnyType<T>.
If static members are called on a metatype instance, then this instance is migrated to AnyType<T>.
Return types of functions are migrated to AnyType<T>.
Variable declarations is migrated to AnyType<T>.
Alternatives considered

Other names for Type and AnyType were considered:

Type: SpecificType, Metatype or ExactType.
AnyType: Subtype, Supertype, Base, BaseType, ExistentialType, ExistentialMetatype or TypeProtocol.