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

Anton Zhilin antonyzhilin at gmail.com
Thu Jul 14 15:17:46 CDT 2016


I still didn't answer the original question:

>> Values of Type store identifiers of U such that U: T.
>Why would we want to store more than one unique identifier?

We don't. What I meant is the following.
Type<T> can have multiple non-equal values. Each of them contains a single
identifier of some type U:T. This type U is different for non-equal values
of Type<T>.

2016-07-14 22:01 GMT+03:00 Anton Zhilin <antonyzhilin at gmail.com>:

> I didn't send the link to evolution, so here it is:
> https://gist.github.com/Anton3/08a069a3b6f634bece7ad666922741d2
>
> Response inline:
>
> 2016-07-14 20:52 GMT+03:00 Adrian Zubarev via swift-evolution <
> swift-evolution at swift.org>:
>>
>>
>>    -
>>
>>    There is a small typo (SE–0090 is not accepted yet) - only in the
>>    first example:
>>
>>    func unsafeBitCast<T, U>(_: T, to: U.Type)
>>    unsafeBitCast(10, to: Double)
>>
>>    // The second line should be
>>    unsafeBitCast(10, to: Double.self)
>>
>>
>> I'll fix the examples.
>
>>
>>    -
>>
>>    Size and internal structure of Type will be the same as of T.Type
>>
>>    - Do we really need this to be the same?
>>
>> Yes, otherwise we cannot remove T.Type. If you want to store *additional*
> data in Type<T> and have a reason for that, then why not.
>
>>
>>    -
>>       -
>>
>>    Values of Type store identifiers of U such that U: T.
>>
>>    - Why would we want to store more than one unique identifier?
>>
>> Another try at explaining my model of Type<T>. Warning: it will be a
> long read this time!
>
> During compilation, each type is assigned a unique integer identifier.
> Let's suppose there are only three types used in the program: Any is 1,
> BaseClass is 2, DerivedClass is 3.
>
> Values of type Type<Any> can contain one of identifiers 1, 2 or 3.
> Values of type Type<BaseClass> can contain one of identifiers 2 or 3.
> Values of type Type<DerivedClass> can only contain 3.
>
> The same in terms of sets:
>
> Type<Any> = { 1, 2, 3 }
> Type<BaseClass> = { 2, 3 }
> Type<DerivedClass> = { 3 }
>
> In terms of set theory, type Type<T> contains identifiers of all types U
> that are subtypes of T.
> If U1, ..., Uk are subtypes of T used in the program, then Type<T> = { T,
> U1, ..., Uk }
>
> Example:
>
> let x = Type<MyType>()
> let y = Type<MyProtocol>(casting: x)
> Type<MyType>.size      //=> 50
> Type<MyProtocol>.size  //=> 40
> x.size                 //=> 50
> y.size                 //=> 50
>
> Again, example with dynamicType. Let's suppose that T = BaseClass and DerivedClass:
> BaseClass.
>
> func dynamicType(_ value: BaseClass) -> Type<BaseClass>
>
> We can't know statically, which type information it returns.
> Type<BaseClass> = { 2, 3 }
> At runtime, we get to know if value is of BaseClass or of DerivedClass.
>
> In my version, Type<T> should get all capabilities and all syntax of
> T.Type, therefore we should be able to drop the latter.
>
> Again, main idea: *rename* T.Type to Type<T>, *maintain* its behaviour
> and tweak syntax.
>
> Actually I thought for a while about the negative effect of fully removing
>> metatypes from the language. Metatypes allow us to build neat looking
>> execution branches like showed in SE–0101.
>>
>> extension MemoryLayout<T> {
>>     init(_ : @autoclosure () -> T) {}
>>     public static func of(_ candidate : @autoclosure () -> T) -> MemoryLayout<T>.Type {
>>         return MemoryLayout.init(candidate).dynamicType
>>     }
>> }
>>
>> // Value
>> let x: UInt8 = 5
>> MemoryLayout.of(x).size // 1
>> MemoryLayout.of(1).size // 8
>> MemoryLayout.of("hello").stride // 24
>> MemoryLayout.of(29.2).alignment // 8
>>
>> I wouldn’t want to throw this away.
>>
> We won't lose literally anything by moving from T.Type to Type<T>.
>
> of returns MemoryLayout<T>.Type, which currently doesn't have size
> property. Could you correct your example?
>
>> I played with the idea of keeping T.Type internally but disallow it in
>> public declarations. Furthermore metatypes would still exist, but can only
>> be instantiated through Type<T>.metatype or Type<T>().metatype.
>>
>> To keep the neat designing feature but get rid of T.Type we could abuse
>> generic typealiases here:
>>
>> // T.Type would be only visible here but is disallowed in public declarations
>> // in favor of `Metatype<T>`
>> public typealias Metatype<T> = T.Type
>>
>> public struct Type<T> : Hashable, CustomStringConvertible, CustomDebugStringConvertible {
>>
>>>>     public var metatype: Metatype<T> { return Type<T>.metatype }
>>
>>     // Internally `.self` should be renamed to `.metatype` and return
>>     // a metatype instance
>>     public static var metatype: Metatype<T> { return T.metatype }
>>>> }
>>
>> That way the sample from above won’t break from its designing point, but
>> will require some refactoring:
>>
>> extension MemoryLayout<T> {
>>     init(_ : @autoclosure () -> T) {}
>>     public static func of(_ candidate : @autoclosure () -> T) -> Metatype<MemoryLayout<T>> {
>>         return dynamicType(MemoryLayout.init(candidate)).metatype
>>     }
>> }
>>
>>  If you wish, Type<T> in my version is rebranded metatype T.Type.
>
>> We should also mention that dynamic casts need some tweaking to work with Type<T>.
>>
>> In the gist, I suggest to live without tweaking and replace dynamic casts
> with failable initializer of Type<T>. That will tweaking syntax of that
> casts, but reduce amount of magic.
>
>> And one more thing:
>>
>> public var size: Int      { get }
>> public var stride: Int    { get }
>> public var alignment: Int { get }
>>
>> public static var size: Int      { return Type<T>().size }
>> public static var stride: Int    { return Type<T>().stride }
>> public static var alignment: Int { return Type<T>().alignment }
>>
>> Shouldn’t these work exactly the opposite way? If in the future Type<T>
>> would be extended with reflection functionality and contain more stored
>> properties, it would be lightweight to compute size etc. from static size
>> without the need of instantiating the whole type.
>>
> See example above with sizes.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160714/bc7cc183/attachment.html>


More information about the swift-evolution mailing list