[swift-evolution] [Discussion] Seal `T.Type` into `Type<T>`

Adrian Zubarev adrian.zubarev at devandartist.com
Sat Jul 16 05:05:29 CDT 2016

One more thing to consider. If we had no Type<T> struct/class there would be no way to get the size of a dynamic metatype after SE–0101 and SE–0096.

func dynamicType(_ instance: T) -> Metatype<T>

We can not check the size of T because then we might end up with the wrong size if Metatype<T> was downcasted from Metatype<U>.

Our current Type<T> solves that issue with instance properties which calculate the correct value for the dynamic metatype.

Adrian Zubarev
Sent with Airmail

Am 16. Juli 2016 um 11:57:33, Adrian Zubarev (adrian.zubarev at devandartist.com) schrieb:

Hmmmm, currently I’m inserting some changes and tweaks into your last gist update.

Metatypes are still in the language; it turned out that they must remain in the language
Type<T> wraps around metatypes and will provide better maintenance if ever needed, because metatype instantiation will be sealed to Type<T>.metatype or typeInstance.metatype.

The new primary Type<T> struct duplicates semantics and interface of metatypes.
True, but properties of a Type<T> instance work with a ‘dynamic’ metatype, which can be up- and downcased. However static properties are used for quick access and do only with the fixed metatype for T.

But it cannot get extensive native support, so it uses init?(casting:) instead of as cast, is(_:) method instead of is, etc.
I believe this is not a huge problem. I’m sure dynamic casts can be teched to work with with Type<T> instances. This can be purely additional and added after Swift 3.

class A {}
class B: A {}

// In Swift 3
let typeB: Type<B> = B.self
let typeA: Type<A>? = Type<A>(casting: typeB)
let anotherTypeA: Type<A> = Type<A>(casting: typeB)!

// Post Swift 3 - Easy migration and removing `init?(casting:)`
let typeA: Type<A>? = typeB as? Type<A>   
let anotherTypeA: Type<A> = typeB as! Type<A>   
Same for for is:

let typeB: Type<B> = B.self
typeB.`is`(A.self) // true

// Post Swift 3 - Easy migration and removing `func `is`(_:) -> Bool`
// Here the `is` cast extract `A` from `Type<A>` and checks the   
// metatype inside of `typeB` if it's compatible with `A`
typeB is Type<A> // true
The as dynamic cast needs additional teaching post Swift 3 without any regrets. Type<T> would be a special case for dynamic casts.

Type<T> does not add new possibilities right now, although the proposal promises to add reflection to Type<T> in the future.
This is my personal opinion, but we’d move SE–0101 into a better place tied side by side to the (dynamic) metatype. MemoryLayout doesn’t provide an instance of itself, it’s purely static.

An instance of Type<T> can be casted and we still can get nicely all the needed information and do not need to extract the dynamic metatype.

let typeB: Type<B> = B.self
let typeA: Type<A>? = Type<A>(casting: typeB)
let anotherTypeA: Type<A> = Type<A>(casting: typeB)!

Mirror already does reflection. It wraps Any.Type statically, which is a simpler and more suitable model for reflection.
I can’t argue on that one. The only thing that I know and have a strong feeling about is that Any.Type is broken. There should be AnyMetatype and current Any.Type should be the metatype for Any returned from the current Any.self. The bug is mentioned in our proposal.

We should move reflection to possible future direction.

Rename metatypes T.Type to Type<T>
I don’t like .Type the way it is right now. T.Metatype makes more sense, which would implies (MHO) it should be called Metatype<T>. This is coved in our proposal.

Rename T.self to T
It’s not about renaming here. SE–0090 aims to drop .self completely. Okay we could go the same way like I already mentioned in some previous examples:

// Only renaming `T.Type` into `Metatype<T>`
let const1: Metatype<T> = T
let const2: T = T()
let const3: T = T.init()
let const4: SomeOtherType = T.staticMember

// My vision
let const1: Type<T> = T
let const2: T = T()
let const3: T = T.init()
let const4: SomeOtherType = T.staticMember
I asked the community if’s possible to make current T.Type conform to Hashable protocol. The response was positive, because this would be really handy.

Such a change would need more compiler magic or an internal protocol which I believe isn’t the best way to solve this. There I come up with the idea wrapping the metatype into a type called Type<T> and make the public T.self notation construct an instance of Type<T> instead.

Allow Type<Type<T>>
Already possible with our current Type<T>.

Extend Mirror for Swift 4
Maybe, but I would still tackle the proposal for Type<T>. Maybe we’ll find a solution which will suit everyone.


I’m updating your last gist and preparing two refactored up (possible) implementation.
I’ll need a few hours, because I’m not that fast. :)
Stay patient.

Adrian Zubarev
Sent with Airmail
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160716/da91de93/attachment.html>

More information about the swift-evolution mailing list