<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>@Karl: Thank you for your feedback:</p>

<blockquote>
<p>I’m not sure about the name “Metatype” and the relationship with “Type” - particularly with the protocol example, it isn’t obvious to a novice user why it’s like this or what these mean.</p>
</blockquote>

<p>Do you mean the example from <strong>known issues</strong> where in a generic context the metatype will become <code>T.Protocol</code> instead of expected <code>T.Type</code>? We haven’t dug that far in Swifts C++ code so we could tell the exact need of it.</p>

<p>In my personal experience with Swift, I haven’t written anything that would make use of <code>.Protocol</code> and I also haven’t seen anyone doing this:</p>

<pre><code class="swift">protocol P {}

P.self is P.Protocol //=&gt; TRUE
</code></pre>

<blockquote>
<p>You say that you want this for Swift 3, and it seems like you’ve done quite a lot of research in to the implementation details. When you talk about “internal” metatypes, do you mean that this information already exists, and that the majority of the implementation work would be to expose it?</p>
</blockquote>

<p>I believe you mean when we talked about <code>T.metatype</code>:</p>

<ul>
<li>Currently <code>T.self</code> does this job already.</li>
<li>But we want to repurpose it to return a lightweight instance of <code>Type&lt;T&gt;</code> instead.</li>
<li>That requires a distinctions between the new <strong>public</strong> <code>T.self</code> notation and the sealed <code>T.metatype</code> notation that previously was <code>T.self</code> in general.</li>
</ul>

<hr>

<p>For the research, as not a compiler expert, we had something like this:</p>

<pre><code class="swift">protocol P {}
protocol R : P {}

class A : P {}
class B : R {}

let b = B()
let hide: Any = b
let dynamicMetatype = hide.dynamicType // Any.Type (Any.self??)

dynamicMetatype is P.Type // true
dynamicMetatype is R.Type // true
dynamicMetatype is A.Type // false - WHY??
dynamicMetatype is B.Type // true
dynamicMetatype is Any.Type // true


public func !=&lt;T : Hashable, U, V&gt;(lhs: T&lt;U&gt;, rhs: T&lt;V&gt;) -&gt; Bool {
    return lhs.hashValue != rhs.hashValue
}


print(new)
let c = unsafeBitCast(new, to: C.Type.self)


class A {
    var value1: Int = 35
    var value2: Int = 35
    var value3: Int = 35
    var value4: Int = 35
    var value5: Int = 35
}

struct B {
    var value1: Int = 35
    var value2: Int = 35
    var value3: Int = 35
    var value4: Int = 35
    var value5: Int = 35
}

enum C {
    case a
    case b
    case c
    case d
     
    var value1: Int { return 35 }
    var value2: Int { return 35 }
    var value3: Int { return 35 }
    var value4: Int { return 35 }
    var value5: Int { return 35 }
}

protocol D {
    var value1: Int { get }
    var value2: Int { get }
    var value3: Int { get }
    var value4: Int { get }
    var value5: Int { get }
    var value6: Int { get }
}

let metatypeA = A.self           // A.Type
let metatypeB = B.self           // B.Type
let metatypeC = C.self           // C.Type
let metatypeD = D.self           // D.Protocol
let metatypeAny = Any.self       // protocol&lt;&gt;.Protocol

let metatypeA_ = A.Type.self     // A.Type.Type
let metatypeB_ = B.Type.self     // B.Type.Type
let metatypeC_ = C.Type.self     // C.Type.Type
let metatypeD_ = D.Type.self     // D.Type.Protocol
let metatypeAny_ = Any.Type.self // protocol&lt;&gt;.Protocol

sizeof(metatypeA)    // 8
sizeof(metatypeB)    // 40
sizeof(metatypeC)    // 1
sizeof(metatypeD)    // 40
sizeof(metatypeAny)  // 32

sizeof(A.self)       // 8
sizeof(B.self)       // 40
sizeof(C.self)       // 1
sizeof(D.self)       // 40
sizeof(Any.self)     // 32

sizeof(metatypeA_)   // 8
sizeof(metatypeB_)   // 0
sizeof(metatypeC_)   // 0
sizeof(metatypeD_)   // 16
sizeof(metatypeAny_) // 8

sizeof(A.Type.self)  // 8
sizeof(B.Type.self)  // 0
sizeof(C.Type.self)  // 0
sizeof(D.Type.self)  // 16
sizeof(Any.Type.self)// 8 &lt;----

let q1: Any.Type = A.self              // A.Type
let q2: Any.Type = B.self              // B.Type
let q3: Any.Type = C.self              // C.Type
let q4: Any.Type = D.self              // D.Protocol
let q5: Any.Type = Any.self            // protocol&lt;&gt;.Protocol
let q6: Any.Type = A.Type.self         // A.Type.Type
let q7: Any.Type = B.Type.self         // B.Type.Type
let q8: Any.Type = C.Type.self         // C.Type.Type
let q9: Any.Type = D.Type.self         // D.Type.Protcol
let q0: Any.Type = Any.Type.self       // protocol&lt;&gt;.Type.Protcol


let q10: Any.Type = Metatype&lt;A&gt;.self   // A.Type.Type
let q11: Any.Type = Metatype&lt;B&gt;.self   // B.Type.Type
let q12: Any.Type = Metatype&lt;C&gt;.self   // C.Type.Type
let q13: Any.Type = Metatype&lt;D&gt;.self   // D.Protocol.Type
let q14: Any.Type = Metatype&lt;Any&gt;.self // protocol&lt;&gt;.Protocol.Type

let q15: Metatype&lt;D&gt;.Type = Metatype&lt;D&gt;.self


// Everything is 8 byte
sizeofValue(q1)
sizeofValue(q2)
sizeofValue(q3)
sizeofValue(q4)
sizeofValue(q5)
sizeofValue(q6)
sizeofValue(q7)
sizeofValue(q8)
sizeofValue(q9)
sizeofValue(q0)

sizeofValue(q10)
sizeofValue(q11)
sizeofValue(q12)
sizeofValue(q13)
sizeofValue(q14)

sizeofValue(q15)


sizeofValue(metatypeA)

// 0 bytes
sizeofValue(metatypeB)
sizeofValue(metatypeC)
sizeofValue(metatypeD)
sizeofValue(metatypeAny)

// 8 bytes
sizeofValue(A.self)

// 0 bytes
sizeofValue(B.self)
sizeofValue(C.self)
sizeofValue(D.self)
sizeofValue(Any.self)

// 8 bytes
sizeofValue(metatypeA_)

// 0 bytes
sizeofValue(metatypeB_)
sizeofValue(metatypeC_)
sizeofValue(metatypeD_)
sizeofValue(metatypeAny_)

// 8 bytes
sizeofValue(A.Type.self)

// 0 bytes
sizeofValue(B.Type.self)
sizeofValue(C.Type.self)
sizeofValue(D.Type.self)
sizeofValue(Any.Type.self)

// 8 bytes
sizeofValue(Metatype&lt;A&gt;.self)

// 0 bytes
sizeofValue(Metatype&lt;B&gt;.self)
sizeofValue(Metatype&lt;C&gt;.self)
sizeofValue(Metatype&lt;D&gt;.self)
sizeofValue(Metatype&lt;Any&gt;.self)
</code></pre>

<p>And also something like this (You can find the full experiment Gist here: <a href="https://gist.github.com/DevAndArtist/d622bf1fb1cf304f87cfc4f98d2a3c63">LINK</a>):</p>

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

P.self is Any.Type                          //=&gt; always true

// STRANGE ISSUE: does not require `.Type`
Mirror(P.self).is(Any.self)                 //=&gt; true
Mirror(P.self).is(Type&lt;Any&gt;())              //=&gt; true
Mirror(P.self).is(Type&lt;Any&gt;.metatype)       //=&gt; true

P.self is Any.Protocol                      //=&gt; false

Mirror(P.self).is(Any.Type.self)            //=&gt; true
Mirror(P.self).is(Type&lt;Any.Type&gt;())         //=&gt; true
Mirror(P.self).is(Type&lt;Any.Type&gt;.metatype)  //=&gt; true

P.self is P.Type                            //=&gt; true

Mirror(P.self).is(P.self)                   //=&gt; true
Mirror(P.self).is(Type&lt;P&gt;())                //=&gt; true
Mirror(P.self).is(Type&lt;P&gt;.metatype)         //=&gt; true

R.self is Any.Type                          //=&gt; always true

// STRANGE ISSUE: does not require `.Type`
Mirror(R.self).is(Any.self)                 //=&gt; true
Mirror(R.self).is(Type&lt;Any&gt;())              //=&gt; true
Mirror(R.self).is(Type&lt;Any&gt;().metatype)     //=&gt; true

// KNOWN ISSUE: Without `.Type` we'd have `.Protocol`
// result -&gt; FALSE
Mirror(R.self).is(Any.Type.self)            //=&gt; true
Mirror(R.self).is(Type&lt;Any.Type&gt;())         //=&gt; true
Mirror(R.self).is(Type&lt;Any.Type&gt;.metatype)  //=&gt; true

// KNOWN ISSUE: I couldn't implemt it so it does
// work as expected
R.self is P.Type                            //=&gt; true

Mirror(R.self).is(P.self)                   //=&gt; false
Mirror(R.self).is(Type&lt;P&gt;())                //=&gt; false
Mirror(R.self).is(Type&lt;P&gt;.metatype)         //=&gt; false

// KNOWN ISSUE: mirror a protocol and check  
// against another protocol with `.Type` fails
Mirror(R.self).is(P.Type.self)              //=&gt; false
Mirror(R.self).is(Type&lt;P.Type&gt;())           //=&gt; false
Mirror(R.self).is(Type&lt;P.Type&gt;.metatype)    //=&gt; false

R.self is R.Type                            //=&gt; true

// STRANGE ISSUE: does not require `.Type`
Mirror(R.self).is(R.self)                   //=&gt; true
Mirror(R.self).is(Type&lt;R&gt;())                //=&gt; true
Mirror(R.self).is(Type&lt;R&gt;.metatype)         //=&gt; true

// KNOWN ISSUE: mirror a protocol and check
// against another protocol with `.Type` fails
Mirror(R.self).is(R.Type.self)              //=&gt; false
Mirror(R.self).is(Type&lt;R.Type&gt;())           //=&gt; false
Mirror(R.self).is(Type&lt;R.Type&gt;.metatype)    //=&gt; false

A.self is Any.Type                          //=&gt; always true

// STRANGE ISSUE: does not require `.Type`
Mirror(A.self).is(Any.self)                 //=&gt; true
Mirror(A.self).is(Type&lt;Any&gt;())              //=&gt; true
Mirror(A.self).is(Type&lt;Any&gt;.metatype)       //=&gt; true

// KNOWN ISSUE: Without `.Type` we'd have `.Protocol`
// result -&gt; FALSE
Mirror(A.self).is(Any.Type.self)            //=&gt; true
Mirror(A.self).is(Type&lt;Any.Type&gt;())         //=&gt; true
Mirror(A.self).is(Type&lt;Any.Type&gt;.metatype)  //=&gt; true

A.self is P.Type                            //=&gt; always true

// KNOWN ISSUE: Without `.Type` we'd have `.Protocol`
// result -&gt; FALSE
Mirror(A.self).is(P.Type.self)              //=&gt; true
Mirror(A.self).is(Type&lt;P.Type&gt;())           //=&gt; true
Mirror(A.self).is(Type&lt;P.Type&gt;.metatype)    //=&gt; true

B.self is Any.Type                          //=&gt; always true

// STRANGE ISSUE: does not require `.Type`
Mirror(B.self).is(Any.self)                 //=&gt; true
Mirror(B.self).is(Type&lt;Any&gt;())              //=&gt; true
Mirror(B.self).is(Type&lt;Any&gt;.metatype)       //=&gt; true

// KNOWN ISSUE: Without `.Type` we'd have `.Protocol`
// result -&gt; FALSE
Mirror(B.self).is(Any.Type.self)            //=&gt; true
Mirror(B.self).is(Type&lt;Any.Type&gt;())         //=&gt; true
Mirror(B.self).is(Type&lt;Any.Type&gt;.metatype)  //=&gt; true

B.self is P.Type                            //=&gt; always true

// KNOWN ISSUE: Without `.Type` we'd have `.Protocol`
// result -&gt; FALSE
Mirror(B.self).is(P.Type.self)              //=&gt; true
Mirror(B.self).is(Type&lt;P.Type&gt;())           //=&gt; true
Mirror(B.self).is(Type&lt;P.Type&gt;.metatype)    //=&gt; true

B.self is R.Type                            //=&gt; always true

// KNOWN ISSUE: Without `.Type` we'd have `.Protocol`
// result -&gt; FALSE
Mirror(B.self).is(R.Type.self)              //=&gt; true
Mirror(B.self).is(Type&lt;R.Type&gt;())           //=&gt; true
Mirror(B.self).is(Type&lt;R.Type&gt;.metatype)    //=&gt; true

B.self is A.Type                            //=&gt; always true

Mirror(B.self).is(A.self)                   //=&gt; true
Mirror(B.self).is(Type&lt;A&gt;())                //=&gt; true
Mirror(B.self).is(Type&lt;A&gt;.metatype)         //=&gt; true
</code></pre>

<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_1469001743743976192" class="bloop_sign"><div style="font-family:helvetica,arial;font-size:13px">--&nbsp;<br>Adrian Zubarev<br>Sent with Airmail</div></div> <br><p class="airmail_on">Am 20. Juli 2016 um 04:30:38, Karl (<a href="mailto:razielim@gmail.com">razielim@gmail.com</a>) schrieb:</p> <blockquote type="cite" class="clean_bq"><span><div><div class="" style="color: rgb(0, 0, 0); font-family: 'helvetica Neue', helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">In general a strong +1 because I’ve been bumping against the .Protocol problem several times.</div><div class="" style="color: rgb(0, 0, 0); font-family: 'helvetica Neue', helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="color: rgb(0, 0, 0); font-family: 'helvetica Neue', helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">I’m not sure about the name “Metatype” and the relationship with “Type” - particularly with the protocol example, it isn’t obvious to a novice user why it’s like this or what these mean.</div><div class="" style="color: rgb(0, 0, 0); font-family: 'helvetica Neue', helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="color: rgb(0, 0, 0); font-family: 'helvetica Neue', helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">You say that you want this for Swift 3, and it seems like you’ve done quite a lot of research in to the implementation details. When you talk about “internal” metatypes, do you mean that this information already exists, and that the majority of the implementation work would be to expose it?</div><div class="" style="color: rgb(0, 0, 0); font-family: 'helvetica Neue', helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="color: rgb(0, 0, 0); font-family: 'helvetica Neue', helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Karl</div></div></span></blockquote></div><div class="bloop_markdown"><p></p></div></body></html>