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

Adrian Zubarev adrian.zubarev at devandartist.com
Sun Jul 10 10:28:29 CDT 2016


Can you point me to some reading? I’m curious what exactly you’re talking about!?

—

I found a negative side effect of sealing T.Type. The problem appears lies in the dynamic is cast.

Currently we could do something like this:

func isInt<T>(metatype: T.Type) -> Bool {
     
    return metatype is Int.Type
}
There is no way to express the same type check with Type<T> except this:

func isInt<T>(type: Type<T>) -> Bool {
     
    return type == Type<Int>()
     
    // since this check is something where we store/pass a type (name)
    // we could implicitly convert `Int` into an instance of `Type<Int>`
    //
    // The result would look like this:
     
    return type == Int // which is logically equivalent to `metatype is Int.Type`
}


-- 
Adrian Zubarev
Sent with Airmail

Am 10. Juli 2016 um 16:24:50, L. Mihalkovic (laurent.mihalkovic at gmail.com) schrieb:


It looks like this is touching on a small subset of the not-yet-designed reflection API (still tabled for 4.0?). I am interested to see what balance it strikes between declarations (eg. being able to reflect extensions declarations), types (eg reflecting type conformance), and operations (xxx.newInstance(), xxx.setValue()). The mirror api shows a general direction, maybe there is a way to squeeze a tiny subset in 3.0 (just like was done with P&Q that will remain a degenerate case of the upcoming more general syntax). Maybe just enough for people not to have to use ObjectIdentifier(:Any.Type).

Regards
(From mobile)

On Jul 10, 2016, at 2:22 PM, Adrian Zubarev via swift-evolution <swift-evolution at swift.org> wrote:

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
_______________________________________________
swift-evolution mailing list
swift-evolution at swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160710/8c4fa607/attachment.html>


More information about the swift-evolution mailing list