<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jul 21, 2016 at 5:40 PM, Adrian Zubarev via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><p><a href="https://github.com/DevAndArtist/swift-evolution/blob/rename_t_dot_type/proposals/0126-rename-t-dot-type.md" target="_blank">https://github.com/DevAndArtist/swift-evolution/blob/rename_t_dot_type/proposals/0126-rename-t-dot-type.md</a></p>

<hr>

<h1>Rename <code>T.Type</code></h1>

<ul>
<li>Proposal: <a href="http://0126-refactor-metatypes-repurpose-t-dot-self-and-mirror.md" target="_blank">SE–0126</a></li>
<li>Authors: <a href="https://github.com/DevAndArtist" target="_blank">Adrian Zubarev</a>, <a href="https://github.com/Anton3" target="_blank">Anton Zhilin</a></li>
<li>Status: <strong>Revision</strong></li>
<li>Review manager: <a href="http://github.com/lattner" target="_blank">Chris Lattner</a></li>
<li>Revision: 2</li>
<li>Previous Revisions: <a href="https://github.com/apple/swift-evolution/blob/83707b0879c83dcde778f8163f5768212736fdc2/proposals/0126-refactor-metatypes-repurpose-t-dot-self-and-mirror.md" target="_blank">1</a></li>
</ul>

<h2>Introduction</h2>

<p>This proposal renames the current metatype <code>T.Type</code> notation and the global function from <strong>SE–0096</strong> to match the changes.</p>

<p>Swift-evolution threads: </p>

<ul>
<li><a>[Pitch] Rename <code>T.Type</code></a></li>
<li><a>[Review] SE–0126: Refactor Metatypes, repurpose T[dot]self and Mirror</a></li>
<li><a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160718/024772.html" target="_blank">[Proposal] Refactor Metatypes, repurpose T[dot]self and Mirror</a></li>
<li><a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160704/023818.html" target="_blank">[Discussion] Seal <code>T.Type</code> into <code>Type&lt;T&gt;</code></a></li>
</ul>

<h2>Motivation</h2></div></div></blockquote><div><br></div><div>For improved reader comprehension, this section could use some more information and reorganization. Specifically, the structure should (IMO) be refactored to have:</div><div><br></div><div>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.</div><div><br></div><div>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&#39;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?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>

<p>In Swift metatypes have the following notation: <strong><code>T.Type</code></strong></p>

<p>As already showed in <strong>SE–0096</strong> and <strong>SE–0090</strong> the Swift community strongly is in favor of (re)moving magical intstance or type properties.</p>

<ul>
<li><p><strong>SE–0096</strong> moves <code>instanceOfT.dynamicType</code> to <code>type&lt;T&gt;(of: T) -&gt; T.Type</code>.</p></li>
<li><p><strong>SE–0090</strong> aims to remove <code>.self</code> completely.</p></li>
</ul>

<p>We propose to rename <code>T.Type</code> to a generic-like notation <code>Metatype&lt;T&gt;</code>. To be able to achieve this notation we have to resolve a few issues first.</p>

<h3>Known issues of metatypes:</h3>

<p>Assume this function that checks if an <code>Int</code> type conforms to a specific protocol. This check uses current model of metatypes combined in a generic context:</p>

<pre><code>func intConforms&lt;T&gt;(to _: T.Type) -&gt; Bool {
   return Int.self is T.Type
}

intConforms(to: CustomStringConvertible.self) //=&gt; false

Int.self is CustomStringConvertible.Type      //=&gt; true
</code></pre>

<blockquote>
<p>[1] When <code>T</code> is a protocol <code>P</code>, <code>T.Type</code> is the metatype of the protocol type itself, <code>P.Protocol</code>. <code>Int.self</code> is not <code>P.self</code>.</p>

<p>[2] There isn’t a way to generically expression <code>P.Type</code> <strong>yet</strong>.</p>

<p>[3] The syntax would have to be changed in the compiler to get something that behaves like <code>.Type</code> today.</p>

<p>Written by Joe Groff: <a href="https://twitter.com/jckarter/status/754420461404958721" target="_blank">[1]</a> <a href="https://twitter.com/jckarter/status/754420624261472256" target="_blank">[2]</a> <a href="https://twitter.com/jckarter/status/754425573762478080" target="_blank">[3]</a></p>
</blockquote>

<p>A possible workaround might look like the example below, but does not allow to decompose <code>P.Type</code>:</p>

<pre><code>func intConforms&lt;T&gt;(to _: T.Type) -&gt; Bool {
  return Int.self is T
}

intConforms(to: CustomStringConvertible.Type.self) //=&gt; true
</code></pre>

<p>We can extend this issue and find the second problem by checking against the metatype of <code>Any</code>:</p>

<pre><code>func intConforms&lt;T&gt;(to _: T.Type) -&gt; Bool {
    return Int.self is T
}

intConforms(to: Any.Type.self) //=&gt; true

intConforms(to: Any.self)      //=&gt; true

Int.self is Any.Type           //=&gt; Always true
</code></pre>

<p>When using <code>Any</code> the compiler does not require <code>.Type</code> at all and returns <code>true</code> for both variations.</p>

<p>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:</p>

<pre><code>protocol P {}
protocol R : P {}

func rIsSubtype&lt;T&gt;(of _: T.Type) -&gt; Bool {
    return R.self is T
}

rIsSubtype(of: P.Type.self) //=&gt; false

R.self is Any.Type //=&gt; Always true
R.self is P.Type   //=&gt; true
R.self is R.Type   //=&gt; true
</code></pre>

<p>We also believe that this issue is the reason why the current global functions <code>sizeof</code>, <code>strideof</code> and <code>alignof</code> make use of generic <code>&lt;T&gt;(_: T.Type)</code> declaration notation instead of <code>(_: Any.Type)</code>.</p>

<h2>Proposed solution</h2>

<ul>
<li><p>Rename any occurrence of <code>T.Type</code> and <code>T.Protocol</code> to <code>Metatype&lt;T&gt;</code>.</p></li></ul></div></div></blockquote><div><br></div><div>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 &quot;magic&quot; properties would be to repaint them `Type&lt;T&gt;` and `Protocol&lt;T&gt;`. If you considered that most obvious choice and discarded it (as I&#39;m sure you have), what is the reasoning for suggesting `Metatype&lt;T&gt;` instead?<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><ul>
<li><p>Revise metatypes internally.</p></li></ul></div></div></blockquote><div><br></div><div>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?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><ul><li><p> </p></li>
<li><p>When <code>T</code> is a protocol, <code>T.self</code> should always return an instance of <code>Metatype&lt;T&gt;</code> (old <code>T.Type</code>) and never a <code>T.Protocol</code>. Furthermore, metatypes should reflect the same type relationship behavior like the actual types themselves.</p></li></ul></div></div></blockquote><div><br></div><div>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?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><ul><li><p> </p></li>
<li><p>To match the correct meaning and usage of the noun ‘Metatype’ from this proposal, we also propose to rename the global function from <strong>SE–0096</strong>:</p>

<ul>
<li>before: <code>public func type&lt;T&gt;(of instance: T) -&gt; T.Type</code></li>
<li>after: <code>public func metatype&lt;T&gt;(of instance: T) -&gt; Metatype&lt;T&gt;</code></li>
</ul></li>
</ul>

<h3>Examples:</h3>

<pre><code>protocol P {}
protocol R : P {}
class A : P {}
class B : A, R {}

func `is`&lt;T&gt;(metatype: Metatype&lt;Any&gt;, also _: Metatype&lt;T&gt; ) -&gt; Bool {
    return metatype is Metatype&lt;T&gt;
}

`is`(metatype: R.self, also: Any.self) //=&gt; true | Currently: false
`is`(metatype: R.self, also: P.self)   //=&gt; true | Currently: false
`is`(metatype: R.self, also: R.self)   //=&gt; true

`is`(metatype: B.self, also: Any.self) //=&gt; true | Currently: false
`is`(metatype: B.self, also: P.self)   //=&gt; true | Currently: false
`is`(metatype: B.self, also: R.self)   //=&gt; true | Currently: false
`is`(metatype: B.self, also: A.self)   //=&gt; true
`is`(metatype: B.self, also: B.self)   //=&gt; true

func cast&lt;T&gt;(metatype: Metatype&lt;Any&gt;, to _: Metatype&lt;T&gt;) -&gt; Metatype&lt;T&gt;? {
    return metatype as? Metatype&lt;T&gt;
}

cast(metatype: R.self, to: Any.self)     //=&gt; an Optional&lt;Metatype&lt;Any&gt;&gt; | Currently: nil
cast(metatype: R.self, to: P.self)       //=&gt; an Optional&lt;Metatype&lt;P&gt;&gt;   | Currently: nil
cast(metatype: R.self, to: R.self)       //=&gt; an Optional&lt;Metatype&lt;R&gt;&gt;   | Currently: an Optional&lt;R.Protocol&gt;

let anyR: Any.Type = R.self
let r = cast(metatype: anyR, to: R.self) //=&gt; an Optional&lt;Metatype&lt;R&gt;&gt;   | Currently: an Optional&lt;R.Protocol&gt;

cast(metatype: B.self, to: Any.self)     //=&gt; an Optional&lt;Metatype&lt;Any&gt;&gt; | Currently: nil
cast(metatype: B.self, to: P.self)       //=&gt; an Optional&lt;Metatype&lt;P&gt;&gt;   | Currently: nil
cast(metatype: B.self, to: R.self)       //=&gt; an Optional&lt;Metatype&lt;R&gt;&gt;   | Currently: nil
cast(metatype: B.self, to: A.self)       //=&gt; an Optional&lt;Metatype&lt;A&gt;&gt;
cast(metatype: B.self, to: B.self)       //=&gt; an Optional&lt;Metatype&lt;B&gt;&gt;

let pB: P.Type = B.self
let b = cast(metatype: pB, to: B.self)   //=&gt; an Optional&lt;Metatype&lt;B&gt;&gt;
</code></pre>

<h2>Impact on existing code</h2>

<p>This is a source-breaking change that can be automated by a migrator. Any occurrence of <code>T.Type</code> or <code>T.Protocol</code> will be simply renamed to <code>Metatype&lt;T&gt;</code>.</p>

<h2>Alternatives considered</h2>

<ul>
<li>Alternatively it’s reasonable to consider to rename <code>T.self</code> to <code>T.metatype</code>.</li>
<li>It was considered to reserve <code>Type&lt;T&gt;</code> for different usage in the future.</li><span class="HOEnZb"><font color="#888888">
</font></span></ul><span class="HOEnZb"><font color="#888888">

<p></p></font></span></div><span class="HOEnZb"><font color="#888888"><div><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto"><br></div><br><div><div style="font-family:helvetica,arial;font-size:13px">-- <br>Adrian Zubarev<br>Sent with Airmail</div></div></div><div><p></p></div></font></span></div><br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div></div>