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

Adrian Zubarev adrian.zubarev at devandartist.com
Sun Jul 10 07:22:50 CDT 2016


Hello Chris,

my main concern for this change is the lack of extensibility of metatypes. We can access the metatype through the .self postfix, which potentially will be removed in the future (only the postfix). Through an instance of such a metatype we can then access the static members and all initializer for our type.

SomeType.staticMember equals metatypeInstance.staticMemeber
SomeType.init equals metatypeInstance.init
It is also possible to extract some more information from the metatypes with the help of Buildin wrapper functions like sizeof or strideof. And the last but not the least we can use metatypes in type checking scenarios.

Last weak I asked the community if there is a need for all metatypes conform to the Hashable protocol, which would be really handy. The overall response was positive, even if only a handful of people responded.

The whole idea of metatypes conforming to Hashable kept me thinking how this might be solved in the future. The main problem is that metatypes provide direct access to initializer and static members of the type and a conformance to Hashable seems to be impossible without some compiler magic or a hidden hashValue property. The main confusion here might be that metatypes can be stored (at least while runtime) inside variables and pretend to be instances of a T.Type type.

That said, I’d like to consider of sealing the direct access to a metatype into a real type for the sake of extensibility and clarity.

I’m aware that my bikeshedding introduced more boilerplate in terms of accessing the initializer and static members through a bottleneck property called sealed. Furthermore there is one more character to type if we’d go with Type<T> instead of T.Type.

This is why this is a discussion before making any further decisions. :)

PS: As I showed in my last code example a wrapper type Type<T> can also provide a few more information about the metatype.

Type<T>.size
Type<T>.stride
Type<T>.alignment
Furthermore sealing T.Type into Type<T> does solve the problem with the array/dictionary shorthand syntax.

Only when one would store/pass a type (name) we’d implicitly convert SomeType to Type<SomeType>.

Declarations do not follow this implicit conversion:

func foo(_: SomeType) is not equivalent to func foo(_: Type<SomeType>)
Array<SomeType>() == [SomeType]() but is not equivalent to [Type<SomeType>]() == Array<Type<SomeType>>()
Here is again my bikeshedding:

public struct Type<T> : Hashable, CustomStringConvertible, CustomDebugStringConvertible {
     
    // `metatype` is a better name than `sealed`
    // The tradeoff is this bottleneck property

    public let metatype: T.Type
      
    public let hashValue: Int
      
    public static var size: Int { get }
    public static var stride: Int { get }
    public static var alignment: Int { get }
      
    public var size: Int { get }
    public var stride: Int { get }
    public var alignment: Int { get }
      
    public var description: String { get }
    public var debugDescription: String { get }
}

public func ==<T, U>(lhs: Type<T>, rhs: Type<U>) -> Bool


-- 
Adrian Zubarev
Sent with Airmail

Am 10. Juli 2016 um 00:18:02, Chris Lattner (clattner at apple.com) schrieb:

Hi Adrian,

What’s the motivation for this change?

-Chris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160710/80c0bf5c/attachment.html>


More information about the swift-evolution mailing list