<html><head><style>
body {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        padding:1em;
        margin:auto;
        background:#fefefe;
}
h1, h2, h3, h4, h5, h6 {
        font-weight: bold;
}
h1 {
        color: #000000;
        font-size: 28pt;
}
h2 {
        border-bottom: 1px solid #CCCCCC;
        color: #000000;
        font-size: 24px;
}
h3 {
        font-size: 18px;
}
h4 {
        font-size: 16px;
}
h5 {
        font-size: 14px;
}
h6 {
        color: #777777;
        background-color: inherit;
        font-size: 14px;
}
hr {
        height: 0.2em;
        border: 0;
        color: #CCCCCC;
        background-color: #CCCCCC;
display: inherit;
}
p, blockquote, ul, ol, dl, li, table, pre {
        margin: 15px 0;
}
a, a:visited {
        color: #4183C4;
        background-color: inherit;
        text-decoration: none;
}
#message {
        border-radius: 6px;
        border: 1px solid #ccc;
        display:block;
        width:100%;
        height:60px;
        margin:6px 0px;
}
button, #ws {
        font-size: 12 pt;
        padding: 4px 6px;
        border-radius: 5px;
        border: 1px solid #bbb;
        background-color: #eee;
}
code, pre, #ws, #message {
        font-family: Monaco;
        font-size: 10pt;
        border-radius: 3px;
        background-color: #F8F8F8;
        color: inherit;
}
code {
        border: 1px solid #EAEAEA;
        margin: 0 2px;
        padding: 0 5px;
}
pre {
        border: 1px solid #CCCCCC;
        overflow: auto;
        padding: 4px 8px;
}
pre > code {
        border: 0;
        margin: 0;
        padding: 0;
}
#ws { background-color: #f8f8f8; }
.bloop_markdown table {
border-collapse: collapse;
font-family: Helvetica, arial, freesans, clean, sans-serif;
color: rgb(51, 51, 51);
font-size: 15px; line-height: 25px;
padding: 0; }
.bloop_markdown table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
.bloop_markdown table tr:nth-child(2n) {
background-color: #f8f8f8; }
.bloop_markdown table tr th {
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
.bloop_markdown table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
.bloop_markdown table tr th :first-child, table tr td :first-child {
margin-top: 0; }
.bloop_markdown table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }
.bloop_markdown blockquote{
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777; }
blockquote > :first-child {
margin-top: 0; }
blockquote > :last-child {
margin-bottom: 0; }
code, pre, #ws, #message {
word-break: normal;
word-wrap: normal;
}
hr {
display: inherit;
}
.bloop_markdown :first-child {
-webkit-margin-before: 0;
}
code, pre, #ws, #message {
font-family: Menlo, Consolas, Liberation Mono, Courier, monospace;
}
.send { color:#77bb77; }
.server { color:#7799bb; }
.error { color:#AA0000; }</style></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="bloop_markdown"><p>Hello Brent, thank you for your feedback on the review process of our proposal.</p>
<blockquote>
<p>I think this proposal is a huge mess. I don’t understand why the split between <code>Type</code> and <code>Metatype</code> exists. I think <code>Mirror</code> seems half-baked; it ought to be omitted entirely until we can actually design a reflection system.</p>
</blockquote>
<p>The reason why we took <code>Mirror</code> here, is because there can be metatypes that pretend to reflect <code>T</code> where the actual metatype could reflect <code>U</code> with relationship like <code>U : T</code>:</p>
<pre><code class="swift">class Superclass {}
class Subclass : Superclass {}
let hidden: Any = Subclass()
let dynamicMetatype = hidden.dynamicType // Any.Type
dynamicMetatype as? Any.Type //=> NOT nil
dynamicMetatype as? Superclass.Type //=> NOT nil
dynamicMetatype as? Subclass.Type //=> NOT nil
</code></pre>
<p>That is the reason why a standalone non-generic type was needed to solve the problem with the ‘current’ Swift.</p>
<blockquote>
<p>And <em>I can’t even tell if these are actual problems</em>. It’s possible that the design is just fine, but the proposal explains it poorly. At minimum, the proposal should be rewritten and the type names reconsidered. I’m not a person who gets confused by metatypes, but I simply cannot make heads or tails of this proposal.</p>
<p>My general sense of this area is that the main problem is the dual meaning of T.Type. T.Type wants to simultaneously be the type of the type instance and the supertype of all subtype type instances. But this breaks down with protocols, because protocol existentials don’t conform to themselves. So we end up with <code>T.Protocol</code>, which gets confusingly renamed when it crosses generic boundaries.</p>
<p>I think the answer here is to split these two roles:</p>
<ol>
<li><code>Metatype<T></code> is the type of the type instance. <code>T.self</code> is of type <code>Metatype<T></code>. (Yes, we can call it <code>T.metatype</code> if we want.)</li>
</ol>
</blockquote>
<p>If we don’t go into the direction of <code>Type<T></code> there is no need to rename the current <code>T.self</code> magic to <code>T.metatype</code>, that was only considered for the <code>Type<T></code> model. <code>.self</code> will be removed one day anyways (hopefully).</p>
<blockquote>
<p>Subtype-supertype relationships don’t translate directly to metaclasses; <code>Metatype<Subclass></code> is not a subtype of <code>Metatype<Superclass></code>.</p>
</blockquote>
<p>Why is that so, see the example above?!</p>
<blockquote>
<ol>
<li><code>T.Subtype</code> (or <code>T.SubtypeMetatype</code>? <code>T.Conforming</code>? this needs bikeshedding) is the supertype of all metatypes for <code>T</code> and its subtypes. <code>T.Subtype</code> is sort of like a protocol, in that there are no concrete instances of it, so it makes no sense to instantiate it. For classes, it only includes required (i.e. inherited) initializers.</li>
</ol>
<p>Happily, I believe—though I may be wrong—that we can mostly resyntax to fix this immediate problem. Adding new capabilities, like extending the metatypes of specific types and adding universal members, can wait (or mostly wait) for another day.</p>
<p>(But in general, I would like to see those added directly on <code>Metatype</code>, and I would like extending <code>Metatype<T></code> with instance members to be equivalent to extending <code>T</code> with static/class members. I’d also like to conform metatypes to protocols, to somehow define <code>Metatype</code> in the standard library as a relatively ordinary Swift type, and to have a pony.)</p>
</blockquote>
<p>This is an interesting suggestion you mentioned there. But I think that would imply that every member you’d add on the generic <code>Metatype<T></code> would be automatically not available on any Swift type:</p>
<pre><code class="swift">// Bikeshedding example:
buildin Metatype<T> : Hashable {
var hashValue: Int { .. }
}
struct New {
// NOT available anymore - even if it's needed for a different purpose
static hashValue: Int { .. }
}
</code></pre>
<p>The issue can be solve if metatypes gain a bottleneck access to the type <code>T</code>, like <code>Type<T>.metatype</code> for example.</p>
<pre><code class="swift">// Bikeshedding example:
buildin Metatype<T> : Hashable {
var hashValue: Int { .. }
var somethingToAccessT: T_XYZ { .. }
}
struct New {
static hashValue: Int { .. } // available again
}
</code></pre>
<p>If we now compare this to our <code>Type<T></code> model, we realize that the huge downside of <code>Type<T></code> is that we cannot cast it around like we’d do with metatypes.</p>
<hr>
<p>I’d appreciate the renaming of <code>T.Type</code> to <code>Metatype<T></code>, but I believe this can’t be done without solving the issue with <code>.Protocol</code> first. Feel free to correct me, if I’m wrong here. :)</p>
<hr>
<p>In SE–0101 rationale Chris said, that the core team considered to move <code>size</code> to types but dropped the idea because it would require <code>T.self</code>.</p>
<hr>
<p>If the core team and the community strongly feels it would be better to introduce a new scoped buildin type (not necessarily named <code>buildin</code>), which would be only visible in stdlib, we might revision our proposal and shrink it down to the minimum breaking changes for Swift 3. Of course such a new scoped type can be introduces post Swift 3 to gain extensibility.</p>
<p>Steps I have in my mind are:</p>
<ul>
<li>Rename <code>T.Type</code> to <code>Metatype<T></code> today and resolve the issue with <code>.Protocol</code> somehow (I’m not a compiler expert).</li>
<li>I’d rename <code>type(of:)</code> from SE–0096 to <code>metatype(of:)</code> (or better <code>dynamicMetatype<T>(of instance: T) -> Metatype<T></code>; not sure why ‘dynamic’ was dropped)</li>
<li>Drop the idea with <code>Mirror</code>, see below.</li>
<li>Come back post Swift 3 and talk about a new buildin extensible scoped type for metatypes with implicit inheritance ability like <code>U : T</code>, which merges the static and dynamic parts of <code>Mirror</code> and <code>Type<T></code>.</li>
</ul>
<pre><code class="swift">// Future bikeshedding:
buildin Metatype<T> : Hashable, CustomStringConvertible, CustomDebugStringConvertible {
/// Creates an instance that reflects `T`.
/// Example: `let type = T.self`
public init()
public static var somethingToAccessT: T_XYZ { get }
public var somethingToAccessT: T_XYZ { get }
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 hashValue: Int { get }
public var description: String { get }
public var debugDescription: String { get }
}
func ==<T>(lhs: Metatype<T>, rhs: Metatype<T>) -> Bool {
return lhs.hashValue == rhs.hashValue
}
</code></pre>
<p>If we can introduce this later, we might be able to drop the closed <code>MemoryLayout</code> enum then.</p>
<pre><code class="swift">let metatype: Metatype<SomeType> = SomeType.self // or SomeType when `.self` is dropped
metatype.size // returns the size of `SomeType`
metatype.somethingToAccessT.staticMemember // from SomeType
metatype.somethingToAccessT.init // from SomeType
let hiddenMetatype: Metatype<Any> = metatype
(hiddenMetatype as? SomeType)?.somethingToAccessT
[Metatype<Any>: String] = [Int.self: "hello", Any.self: "swift"]
</code></pre>
<p>The last ideas are my personal ideas which I do believe reflects some of your suggestions. </p>
<p>Anton might have a different point of view here.</p>
<p></p></div><div class="bloop_original_html"><style>body{font-family:Helvetica,Arial;font-size:13px}</style><div id="bloop_customfont" style="font-family:Helvetica,Arial;font-size:13px; color: rgba(0,0,0,1.0); margin: 0px; line-height: auto;"><br></div> <br> <div id="bloop_sign_1469108293864350976" class="bloop_sign"><div style="font-family:helvetica,arial;font-size:13px">-- <br>Adrian Zubarev<br>Sent with Airmail</div></div></div><div class="bloop_markdown"><p></p></div></body></html>