[swift-evolution] [Revision] [Pitch] Rename `T.Type`

Xiaodi Wu xiaodi.wu at gmail.com
Thu Jul 21 18:41:46 CDT 2016


On Thu, Jul 21, 2016 at 5:40 PM, Adrian Zubarev via swift-evolution <
swift-evolution at swift.org> wrote:

>
> https://github.com/DevAndArtist/swift-evolution/blob/rename_t_dot_type/proposals/0126-rename-t-dot-type.md
> ------------------------------
> Rename T.Type
>
>    - Proposal: SE–0126
>    <http://0126-refactor-metatypes-repurpose-t-dot-self-and-mirror.md>
>    - Authors: Adrian Zubarev <https://github.com/DevAndArtist>, Anton
>    Zhilin <https://github.com/Anton3>
>    - Status: *Revision*
>    - Review manager: Chris Lattner <http://github.com/lattner>
>    - Revision: 2
>    - Previous Revisions: 1
>    <https://github.com/apple/swift-evolution/blob/83707b0879c83dcde778f8163f5768212736fdc2/proposals/0126-refactor-metatypes-repurpose-t-dot-self-and-mirror.md>
>
> Introduction
>
> This proposal renames the current metatype T.Type notation and the global
> function from *SE–0096* to match the changes.
>
> Swift-evolution threads:
>
>    - [Pitch] Rename T.Type
>    - [Review] SE–0126: Refactor Metatypes, repurpose T[dot]self and Mirror
>    - [Proposal] Refactor Metatypes, repurpose T[dot]self and Mirror
>    <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160718/024772.html>
>    - [Discussion] Seal T.Type into Type<T>
>    <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160704/023818.html>
>
> Motivation
>

For improved reader comprehension, this section could use some more
information and reorganization. Specifically, the structure should (IMO) be
refactored to have:

1. A consolidated section--which can be on the brief side--on the current
art (i.e., how do things currently work?). Some information is already
present, but the prose is not possible to follow unless one is already an
expert in the area. Please start each paragraph with a topic sentence
leading into an explanation in English, not just code, of the current
behavior. Perhaps you could used (attributed) quotations from existing
Swift documentation if necessary.

2. Subsequent to (1), a concise explanation in English (in addition to
Swift code, if desired, but the key is to have it also in English)
outlining the defects present in the current art. I know, for instance,
that type(of:) as approved can't quite be expressed in Swift code due to
issues related to existential metatypes. Could you elaborate on these
issues in a way that would set up your proposed solution?


> In Swift metatypes have the following notation: *T.Type*
>
> As already showed in *SE–0096* and *SE–0090* the Swift community strongly
> is in favor of (re)moving magical intstance or type properties.
>
>    -
>
>    *SE–0096* moves instanceOfT.dynamicType to type<T>(of: T) -> T.Type.
>    -
>
>    *SE–0090* aims to remove .self completely.
>
> We propose to rename T.Type to a generic-like notation Metatype<T>. To be
> able to achieve this notation we have to resolve a few issues first.
> Known issues of metatypes:
>
> Assume this function that checks if an Int type conforms to a specific
> protocol. This check uses current model of metatypes combined in a generic
> context:
>
> func intConforms<T>(to _: T.Type) -> Bool {
>    return Int.self is T.Type
> }
>
> intConforms(to: CustomStringConvertible.self) //=> false
>
> Int.self is CustomStringConvertible.Type      //=> true
>
> [1] When T is a protocol P, T.Type is the metatype of the protocol type
> itself, P.Protocol. Int.self is not P.self.
>
> [2] There isn’t a way to generically expression P.Type *yet*.
>
> [3] The syntax would have to be changed in the compiler to get something
> that behaves like .Type today.
>
> Written by Joe Groff: [1]
> <https://twitter.com/jckarter/status/754420461404958721> [2]
> <https://twitter.com/jckarter/status/754420624261472256> [3]
> <https://twitter.com/jckarter/status/754425573762478080>
>
> A possible workaround might look like the example below, but does not
> allow to decompose P.Type:
>
> func intConforms<T>(to _: T.Type) -> Bool {
>   return Int.self is T
> }
>
> intConforms(to: CustomStringConvertible.Type.self) //=> true
>
> We can extend this issue and find the second problem by checking against
> the metatype of Any:
>
> func intConforms<T>(to _: T.Type) -> Bool {
>     return Int.self is T
> }
>
> intConforms(to: Any.Type.self) //=> true
>
> intConforms(to: Any.self)      //=> true
>
> Int.self is Any.Type           //=> Always true
>
> When using Any the compiler does not require .Type at all and returns true
> for both variations.
>
> The third issue will show itself whenever we would try to check protocol
> relationship with another protocol. Currently there is no way (that we know
> of) to solve this problem:
>
> protocol P {}
> protocol R : P {}
>
> func rIsSubtype<T>(of _: T.Type) -> Bool {
>     return R.self is T
> }
>
> rIsSubtype(of: P.Type.self) //=> false
>
> R.self is Any.Type //=> Always true
> R.self is P.Type   //=> true
> R.self is R.Type   //=> true
>
> We also believe that this issue is the reason why the current global
> functions sizeof, strideof and alignof make use of generic <T>(_: T.Type)
> declaration notation instead of (_: Any.Type).
> Proposed solution
>
>    -
>
>    Rename any occurrence of T.Type and T.Protocol to Metatype<T>.
>
>
Why is this necessary? It is not clear from what you wrote in the
Motivation section. Naively, it would seem like the most straightforward
ways to remove the "magic" properties would be to repaint them `Type<T>`
and `Protocol<T>`. If you considered that most obvious choice and discarded
it (as I'm sure you have), what is the reasoning for suggesting
`Metatype<T>` instead?


>    -
>
>    Revise metatypes internally.
>
>
In what way? How would you want an implementer to tackle this bullet point?
What are the user-observable changes that will result, if any? If there
will be none, why is it part of the proposed solution?


>
>    -
>
>    -
>
>    When T is a protocol, T.self should always return an instance of
>    Metatype<T> (old T.Type) and never a T.Protocol. Furthermore,
>    metatypes should reflect the same type relationship behavior like the
>    actual types themselves.
>
>
If this is implemented, how will I then access the value currently returned
by `T.self`? Are you asserting that an instance of `T.Protocol` is never
useful, or are you providing an alternative way to get the same instance?


>
>    -
>
>    -
>
>    To match the correct meaning and usage of the noun ‘Metatype’ from
>    this proposal, we also propose to rename the global function from
>    *SE–0096*:
>    - before: public func type<T>(of instance: T) -> T.Type
>       - after: public func metatype<T>(of instance: T) -> Metatype<T>
>
> Examples:
>
> protocol P {}
> protocol R : P {}
> class A : P {}
> class B : A, R {}
>
> func `is`<T>(metatype: Metatype<Any>, also _: Metatype<T> ) -> Bool {
>     return metatype is Metatype<T>
> }
>
> `is`(metatype: R.self, also: Any.self) //=> true | Currently: false
> `is`(metatype: R.self, also: P.self)   //=> true | Currently: false
> `is`(metatype: R.self, also: R.self)   //=> true
>
> `is`(metatype: B.self, also: Any.self) //=> true | Currently: false
> `is`(metatype: B.self, also: P.self)   //=> true | Currently: false
> `is`(metatype: B.self, also: R.self)   //=> true | Currently: false
> `is`(metatype: B.self, also: A.self)   //=> true
> `is`(metatype: B.self, also: B.self)   //=> true
>
> func cast<T>(metatype: Metatype<Any>, to _: Metatype<T>) -> Metatype<T>? {
>     return metatype as? Metatype<T>
> }
>
> cast(metatype: R.self, to: Any.self)     //=> an Optional<Metatype<Any>> | Currently: nil
> cast(metatype: R.self, to: P.self)       //=> an Optional<Metatype<P>>   | Currently: nil
> cast(metatype: R.self, to: R.self)       //=> an Optional<Metatype<R>>   | Currently: an Optional<R.Protocol>
>
> let anyR: Any.Type = R.self
> let r = cast(metatype: anyR, to: R.self) //=> an Optional<Metatype<R>>   | Currently: an Optional<R.Protocol>
>
> cast(metatype: B.self, to: Any.self)     //=> an Optional<Metatype<Any>> | Currently: nil
> cast(metatype: B.self, to: P.self)       //=> an Optional<Metatype<P>>   | Currently: nil
> cast(metatype: B.self, to: R.self)       //=> an Optional<Metatype<R>>   | Currently: nil
> cast(metatype: B.self, to: A.self)       //=> an Optional<Metatype<A>>
> cast(metatype: B.self, to: B.self)       //=> an Optional<Metatype<B>>
>
> let pB: P.Type = B.self
> let b = cast(metatype: pB, to: B.self)   //=> an Optional<Metatype<B>>
>
> Impact on existing code
>
> This is a source-breaking change that can be automated by a migrator. Any
> occurrence of T.Type or T.Protocol will be simply renamed to Metatype<T>.
> Alternatives considered
>
>    - Alternatively it’s reasonable to consider to rename T.self to
>    T.metatype.
>    - It was considered to reserve Type<T> for different usage in the
>    future.
>
>
>
> --
> Adrian Zubarev
> Sent with Airmail
>
>
> _______________________________________________
> 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/20160721/df635cb0/attachment.html>


More information about the swift-evolution mailing list