<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>A few things were already updated (such as reflection rationale from SE–0096) and can be vied here: <a href="https://github.com/DevAndArtist/swift-evolution/blob/refactor_metatypes_repurpose_t_dot_self_and_mirror/proposals/0000-refactor-metatypes-repurpose-t-dot-self-and-mirror.md">LINK</a></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_1468963968942840064" class="bloop_sign"><div style="font-family:helvetica,arial;font-size:13px">-- <br>Adrian Zubarev<br>Sent with Airmail</div></div> <br><p class="airmail_on">Am 19. Juli 2016 um 22:38:44, Adrian Zubarev (<a href="mailto:adrian.zubarev@devandartist.com">adrian.zubarev@devandartist.com</a>) schrieb:</p> <blockquote type="cite" class="clean_bq"><span><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div></div><div>
<title></title>
<div class="bloop_markdown">
<p>Dear Swift community,</p>
<p>Anton Zhilin and I worked hard past days to finish this
proposal, which we started about a weak ago in a different
discussion thread. We’d like you to review the proposal before we
push a PR for final review.</p>
<p>Thanks to everyone who’s willing to help.</p>
<p>You can read the formatted proposal on GitHub: <a href="https://github.com/DevAndArtist/swift-evolution/blob/refactor_metatypes_repurpose_t_dot_self_and_mirror/proposals/0000-refactor-metatypes-repurpose-t-dot-self-and-mirror.md">
HERE</a></p>
<p>Or bellow (Email is markdown formatted):</p>
<hr>
<h1 id="refactormetatypesrepurposet.selfandmirror">Refactor
Metatypes, repurpose <code>T.self</code> and
<code>Mirror</code></h1>
<ul>
<li>Proposal: <a href="nnnn-seal-metatype.md">SE-NNNN</a></li>
<li>Author: <a href="https://github.com/DevAndArtist">Adrian
Zubarev</a>, <a href="https://github.com/Anton3">Anton
Zhilin</a></li>
<li>Status: <strong><a href="#rationale">Awaiting
review</a></strong></li>
<li>Review manager: TBD</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>This proposal want to revise metatypes <code>T.Type</code>,
repurpose <em>public</em> <code>T.self</code> notation to return a
new <code>Type<T></code> type instance rather than a
metatype, merge <strong>SE–0101</strong> into
<code>Type<T></code>, rename the global function from
<strong>SE–0096</strong> to match the changes of this proposal and
finally rename current <code>Mirror</code> type to introduce a new
(lazy) <code>Mirror</code> type.</p>
<p>Swift-evolution threads:</p>
<ul>
<li><a href="">[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">
[Discussion] Seal <code>T.Type</code> into
<code>Type<T></code></a></li>
<li><a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160627/023067.html">
[Discussion] Can we make <code>.Type</code> Hashable?</a></li>
</ul>
<p>GitHub Gist thread:</p>
<ul>
<li><a href="https://gist.github.com/Anton3/9931463695f1c3263333e18f04f9cd8e">Refactor
metatypes</a></li>
</ul>
<h2 id="motivation">Motivation</h2>
<p>The following tasks require metatype-like types:</p>
<ol>
<li>Explicit specialization of functions and expressing specific
static types.</li>
<li>Dynamic dispatch of <code>static</code> methods.</li>
<li>Representing any value as a tree, for debug purposes.</li>
<li>Retrieving and passing around information about dynamic types -
Reflection.</li>
</ol>
<p>Current state of things:</p>
<p>[1] is given to metatypes <code>T.Type</code>:</p>
<ul>
<li>The metatype instance is usually ignored.</li>
<li>For example, if you pass <code>Derived.self as Base.self</code>
into function taking <code>T.Type</code>, it will work with
<code>Base</code>.</li>
<li>This raises concerns: are metatypes perfectly suited for that
purpose?</li>
</ul>
<p>[2] is also given to metatypes <code>T.Type</code>:</p>
<ul>
<li>Because they are used so often, it’s tempting to add useful
methods to them, but we can’t, because metatypes are not extensible
types.</li>
</ul>
<p>[3] is given to <code>Mirror</code>:</p>
<ul>
<li>Does its name reflect what it’s intended to do?</li>
<li><code>Mirror.DisplayStyle</code> contains <code>optional</code>
and <code>set</code> as special cases, but does not contain
<code>function</code> at all.</li>
<li><code>Mirror</code> collects all information possible at
initialization, while for “true” reflection we want
<em>laziness</em>.</li>
<li><code>Mirror</code> allows customization. For example,
<code>Array<T></code> is represented with a field for each of
its elements. Do we want this for “true” reflection we want to add
in the future?</li>
</ul>
<p>[4] is given to both metatypes <code>T.Type</code> and
<code>Mirror</code>:</p>
<ul>
<li>Metatypes are generic. But do we want genericity in reflection?
No, we almost always want to cast to <code>Any.Type</code>.</li>
<li>Metatypes are used for getting both static and dynamic
sizes.</li>
<li>In this context, distinction between generic parameter
<code>T</code> and value of metatype instance is unclear.</li>
<li>People are confused that <code>Mirror</code> is intended to be
used for full-featured reflection, while it does not aim for
that.</li>
</ul>
<h3 id="knownissuesofmetatypes:">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 class="swift">func intConformsTo<T>(_: T.Type) -> Bool {
return Int.self is T.Type
}
intConformsTo(CustomReflectable.self) //=> FALSE
</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 <code>not
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">[1]</a>
<a href="https://twitter.com/jckarter/status/754420624261472256">[2]</a>
<a href="https://twitter.com/jckarter/status/754425573762478080">[3]</a></p>
</blockquote>
<p>A possible workaround might look like the example below, but
does not allow to decompose <code>P.Type</code> which is a major
implementation problem of this proposal:</p>
<pre><code class="swift">func intConformsTo<T>(_: T.Type) -> Bool {
return Int.self is T
}
intConformsTo(CustomReflectable.Type.self) //=> TRUE
</code></pre>
<p>This issue was first found and documented as a strange issue in
<strong><a href="https://bugs.swift.org/browse/SR-2085">SR–2085</a></strong>. It
also raises the concerns: do we need <code>.Protocol</code> at
all?</p>
<p>We can extend this issue and find the second problem by checking
agains the metatype of <code>Any</code>:</p>
<pre><code class="swift">func intConformsTo<T>(_: T.Type) -> Bool {
return Int.self is T
}
intConformsTo(Any.Type.self) //=> TRUE
intConformsTo(Any.self) //=> TRUE
</code></pre>
<p>As you clearly can see, when using <code>Any</code> the compiler
does not require <code>.Type</code> at all.</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 class="swift">protocol P {}
protocol R : P {}
func rIsSubtypeOf<T>(_: T.Type) -> Bool {
return R.self is T
}
rIsSubtypeOf(P.Type.self) //=> FALSE
</code></pre>
<p>We also believe that this issue is also the reason why the
current gloabl functions <code>sizeof</code>, <code>strideof</code>
and <code>alignof</code> make use of generic <code><T>(_:
T.Type)</code> declaration notation instead of <code>(_:
Any.Type)</code>.</p>
<h2 id="proposedsolution">Proposed solution</h2>
<h3 id="metatypet:"><code>Metatype<T></code>:</h3>
<ul>
<li>Revise metatypes in generic context so the old
<code>T.Type</code> notation does not produce
<code>T.Protocol</code> when a protocol metatype is passed
around.</li>
<li>Intoduce a distinction between <strong>public</strong> and
<strong>internal</strong> <code>T.self</code> notation where the
<strong>internal</strong> <code>T.self</code> notation will be
renamed to <code>T.metatype</code>.</li>
<li>Rename old metatype <code>T.Type</code> notation to
<code>Metatype<T></code>.</li>
<li>Make <strong>internal</strong> <code>T.metatype</code> notation
(Buildin - not visible in public Swift) return an instance of
<code>Metatype<T></code>.</li>
<li>Public construction of metatypes will look like
<code>Type<T>.metatype</code> or
<code>T.self.metatype</code>, see below.</li>
<li>Metatypes will be used <strong>only</strong> for dynamic
dispatch of static methods, see example below:</li>
</ul>
<pre><code class="swift">protocol HasStatic { static func staticMethod() -> String; init() }
struct A : HasStatic { static func staticMethod() -> String { return "I am A" }; init() {} }
struct B : HasStatic { static func staticMethod() -> String { return "I am B" }; init() {} }
func callStatic(_ metatype: Metatype<HasStatic>) {
let result = metatype.staticMethod()
print(result)
let instance = metatype.init()
print(instance)
}
let a = Type<A>.metatype
let b = Type<B>.metatype
callStatic(a) //=> "I am A" "A()"
callStatic(b) //=> "A am B" "B()"
</code></pre>
<h3 id="typetapi:"><code>Type<T></code> API:</h3>
<p><code>T.self</code> will be repurposed to return ab instance of
<code>Type<T></code> that is declared as follows:</p>
<pre><code class="swift">public struct Type<T> : Hashable, CustomStringConvertible, CustomDebugStringConvertible {
/// Creates an instance that reflects `T`.
/// Example: `let type = T.self`
public init()
/// Returns the contiguous memory footprint of `T`.
///
/// Does not include any dynamically-allocated or "remote" storage.
/// In particular, `Type<T>.size`, when `T` is a class type, is the
/// same regardless of how many stored properties `T` has.
public static var size: Int { get }
/// Returns the least possible interval between distinct instances of
/// `T` in memory. The result is always positive.
public static var stride: Int { get }
/// Returns the default memory alignment of `T`.
public static var alignment: Int { get }
/// Returns an instance of `Metatype<T>` from captured `T` literal.
public static var metatype: Metatype<T> { get }
/// Returns the contiguous memory footprint of `T`.
///
/// Does not include any dynamically-allocated or "remote" storage.
/// In particular, `Type<T>().size`, when `T` is a class type, is the
/// same regardless of how many stored properties `T` has.
public var size: Int { get }
/// Returns the least possible interval between distinct instances of
/// `T` in memory. The result is always positive.
public var stride: Int { get }
/// Returns the default memory alignment of `T`.
public var alignment: Int { get }
/// Returns an instance of `Metatype<T>` from captured `T` literal.
public var metatype: Metatype<T> { get }
/// Hash values are not guaranteed to be equal across different executions of
/// your program. Do not save hash values to use during a future execution.
public var hashValue: Int { get }
/// A textual representation of `self`.
public var description: String { get }
/// A textual representation of `self`, suitable for debugging.
public var debugDescription: String { get }
}
public func ==<T>(lhs: Type<T>, rhs: Type<T>) -> Bool
</code></pre>
<p>Size of <code>Type<T></code> struct equals <code>0</code>.
It will be used for generic function specialization:</p>
<pre><code class="swift">func performWithType(_ type: Type<T>)
performWithType(Float.self)
</code></pre>
<h3 id="dynamicmetatypefunction:"><code>dynamicMetatype</code>
function:</h3>
<p>The global <code>dynamicType</code> function from
<strong>SE–0096</strong> will be renamed to
<code>dynamicMetatype</code> and receive the following
declaration:</p>
<pre><code class="swift">/// Returns a dynamic instance of `Metatype<T>`. A dynamic
/// metatype can reflect type `U` where `U : T`.
public func dynamicMetatype<T>(_ instance: T) -> Metatype<T>
</code></pre>
<h3 id="mirrorapi:"><code>Mirror</code> API:</h3>
<p>Rename current <code>Mirror</code> (Swift 2.2) to
<code>DebugRepresentation</code> and <code>CustomReflectable</code>
to <code>CustomDebugRepresentable</code>.</p>
<p>A <em>completely different</em> <code>Mirror</code> type will be
introduced in Swift 3.</p>
<ul>
<li><code>Mirror</code> wraps metatypes and allows checking subtype
relationships at runtime.</li>
<li><code>Mirror</code> contains dynamic versions of
<code>size</code>, <code>stride</code> and
<code>alignment</code>.</li>
<li>Size of <code>Mirror</code> itself is always <code>8</code>
bytes, because it only needs to store a single metatype.</li>
<li><code>Mirror</code> provides a starting point for adding fully
functional (lazy) reflection in the future.</li>
</ul>
<pre><code class="swift">public struct Mirror : Hashable, CustomStringConvertible, CustomDebugStringConvertible {
/// Creates an instance of `Mirror`, reflecting type, which is
/// reflected by a metatype.
public init(_ metatype: Metatype<Any>)
/// Creates an instance of `Mirror`, reflecting type `T`
public init<T>(_ type: Type<T>)
/// Creates an instance of `Mirror`, reflecting
/// dynamic metatype of a given instance.
public init<T>(reflecting instance: T)
/// Returns the contiguous memory footprint of reflected metatype.
public var size: Int { get }
/// Returns the least possible interval between distinct instances of
/// the dynamic type in memory calculated from the reflected dynamic
/// metatype. The result is always positive.
public var stride: Int { get }
/// Returns the minimum memory alignment of the reflected dynamic
/// metatype.
public var alignment: Int { get }
/// Returns an instance of `Metatype<Any>` from reflected dynamic metatype.
public var metatype: Metatype<Any> { get }
/// Checks if type reflected by `self` is a subtype of type reflected by another `Mirror`.
public func `is`(_ mirror: Mirror) -> Bool { get }
/// Checks if type reflected by `self` is a subtype of `T`.
public func `is`<T>(_ type: Type<T>) -> Bool { get }
/// Checks if type reflected by `self` is a subtype of type reflected by a metatype.
public func `is`<T>(_ metatype: Metatype<T>) -> Bool { get }
/// Hash values are not guaranteed to be equal across different executions of
/// your program. Do not save hash values to use during a future execution.
public var hashValue: Int { get }
/// A textual representation of `self`.
public var description: String { get }
/// A textual representation of `self`, suitable for debugging.
public var debugDescription: String { get }
}
public func ==(lhs: Mirror, rhs: Mirror) -> Bool
</code></pre>
<h3 id="summaryofmetatype-liketypes:">Summary of metatype-like
types:</h3>
<h4 id="before">Before</h4>
<ul>
<li><code>T.Type</code> does three things:</li>
<li>Specialization of functions.</li>
<li>Dynamic dispatch of static methods.</li>
<li>Partial reflection using dynamic casts and functions like
<code>sizeof</code>, <code>strideof</code> etc.</li>
<li><code>Mirror</code> does two things:</li>
<li>It is primarily intended for use in debugging, like
<code>PlaygroundQuickLook</code>.</li>
<li>With less success, it can be used for reflection.</li>
</ul>
<h4 id="after">After</h4>
<ul>
<li><code>Type<T></code> does specialization of
functions.</li>
<li><code>Mirror</code> does reflection.</li>
<li><code>Metatype<T></code> does dynamic dispatch of static
methods.</li>
<li><code>DebugRepresentation</code> is used in debugging.</li>
</ul>
<h2 id="detaileddesign">Detailed design</h2>
<h3 id="possibleimplementation:">Possible Implementation:</h3>
<pre><code class="swift">public struct Type<T> : Hashable, CustomStringConvertible, CustomDebugStringConvertible {
/// Creates an instance that reflects `T`.
/// Example: `let type = T.self`
public init() {}
/// Returns the contiguous memory footprint of `T`.
///
/// Does not include any dynamically-allocated or "remote" storage.
/// In particular, `Type<T>.size`, when `T` is a class type, is the
/// same regardless of how many stored properties `T` has.
public static var size: Int { return _size(of: T.metatype) }
/// Returns the least possible interval between distinct instances of
/// `T` in memory. The result is always positive.
public static var stride: Int { return _stride(of: T.metatype) }
/// Returns the default memory alignment of `T`.
public static var alignment: Int { return _alignment(of: T.metatype) }
/// Returns an instance of `Metatype<T>` from captured `T` literal.
public static var metatype: Metatype<T> { return T.metatype }
/// Returns the contiguous memory footprint of `T`.
///
/// Does not include any dynamically-allocated or "remote" storage.
/// In particular, `Type<T>().size`, when `T` is a class type, is the
/// same regardless of how many stored properties `T` has.
public var size: Int { return Type<T>.size }
/// Returns the least possible interval between distinct instances of
/// `T` in memory. The result is always positive.
public var stride: Int { return Type<T>.stride }
/// Returns the default memory alignment of `T`.
public var alignment: Int { return Type<T>.alignment }
/// Returns an instance of `Metatype<T>` from captured `T` literal.
public var metatype: Metatype<T> { return Type<T>.metatype }
/// Hash values are not guaranteed to be equal across different executions of
/// your program. Do not save hash values to use during a future execution.
public var hashValue: Int { return _uniqueIdentifier(for: self.metatype) }
/// A textual representation of `self`.
public var description: String { return "Type<\(self.metatype)>()" }
/// A textual representation of `self`, suitable for debugging.
public var debugDescription: String {
return "[" + self.description
+ " metatype: \(self.metatype)"
+ " size: \(self.size)"
+ " stride: \(self.stride)"
+ " alignment: \(self.alignment)]"
}
}
public func ==<T>(lhs: Type<T>, rhs: Type<T>) -> Bool { return true }
/// Returns a dynamic instance of `Metatype<T>`. A dynamic
/// metatype can reflect type `U` where `U : T`.
public func dynamicMetatype<T>(_ instance: T) -> Metatype<T> {
return /* implement */
}
public struct Mirror : Hashable, CustomStringConvertible, CustomDebugStringConvertible {
/// Storage for any dynamic metatype.
internal let _metatype: Metatype<Any>
/// Creates an instance of `Mirror`, reflecting type, which is
/// reflected by a metatype.
public init(_ metatype: Metatype<Any>) {
self._metatype = metatype
}
/// Creates an instance of `Mirror`, reflecting type `T`
public init<T>(_ type: Type<T>) {
self._metatype = type.metatype
}
/// Creates an instance of `Mirror`, reflecting
/// dynamic type of a given instance.
public init<T>(reflecting instance: T) {
self._metatype = dynamicMetatype(instance)
}
/// Returns the contiguous memory footprint of reflected metatype.
public var size: Int { return _size(of: self._metatype) }
/// Returns the least possible interval between distinct instances of
/// the dynamic type in memory calculated from the reflected dynamic
/// metatype. The result is always positive.
public var stride: Int { return _stride(of: self._metatype) }
/// Returns the minimum memory alignment of the reflected dynamic
/// metatype.
public var alignment: Int { return _alignment(of: self._metatype) }
/// Returns an instance of `Metatype<T>` from reflected dynamic metatype.
public var metatype: Any.Type { return self._metatype }
/// Checks if type reflected by `self` is a subtype of type reflected by another `Mirror`.
public func `is`(_ mirror: Mirror) -> Bool {
return _is(metatype: self._metatype, also: mirror.metatype)
}
/// Checks if type reflected by `self` is a subtype of `T`.
public func `is`<T>(_ type: Type<T>) -> Bool {
return _is(metatype: self._metatype, also: type.metatype)
}
/// Checks if type reflected by `self` is a subtype of type reflected by a metatype.
public func `is`<T>(_ metatype: Metatype<T>) -> Bool {
return _is(metatype: self._metatype, also: metatype)
}
/// Hash values are not guaranteed to be equal across different executions of
/// your program. Do not save hash values to use during a future execution.
public var hashValue: Int { return _uniqueIdentifier(for: self._metatype) }
/// A textual representation of `self`.
public var description: String { return "Mirror(\(self._metatype))" }
/// A textual representation of `self`, suitable for debugging.
public var debugDescription: String {
return "[" + self.description
+ " metatype: \(self._metatype)"
+ " size: \(self.size)"
+ " stride: \(self.stride)"
+ " alignment: \(self.alignment)]"
}
}
public func ==(lhs: Mirror, rhs: Mirror) -> Bool {
return lhs.hashValue == rhs.hashValue
}
</code></pre>
<h3 id="internalfunctions:">Internal functions:</h3>
<p>These functions were used in the implementation above to
calculate metatype related informations.</p>
<ul>
<li>
<p><code>_size(of:)</code>, <code>_stride(of:)</code> and
<code>_alignment(of:)</code> functions need some additional
tweaking so they will work with any matatype stored in an instance
of <code>Metatype<Any></code> rather than a dynamic
<code><T>(of metatype: Metatype<T>)</code> variant,
which is not suitable for calculations needed in
<code>Mirror</code>.</p>
</li>
<li>
<p><code>_uniqueIdentifier(for:)</code> function is fully
implemented and should just work when the current generic issue
with <code>.Protocol</code> metatypes is resolved.</p>
</li>
<li>
<p><code>_is(metatype:also:)</code> relies on the resolved
<code>.Protocol</code> issue. The final implementation should allow
to check type relationship between two different metatype
instances.</p>
</li>
</ul>
<pre><code class="swift">internal func _size(of metatype: Metatype<Any>) -> Int {
// Fix this to allow any metatype
return Int(Builtin.sizeof(metatype))
}
internal func _stride(of metatype: Metatype<Any>) -> Int {
// Fix this to allow any metatype
return Int(Builtin.strideof_nonzero(metatype))
}
internal func _alignment(of metatype: Metatype<Any>) -> Int {
// Fix this to allow any metatype
return Int(Builtin.alignof(metatype))
}
internal func _uniqueIdentifier(for metatype: Metatype<Any>) -> Int {
let rawPointerMetatype = unsafeBitCast(metatype, to: Builtin.RawPointer.metatype)
return Int(Builtin.ptrtoint_Word(rawPointerMetatype))
}
internal func _is(metatype m1: Metatype<Any>, also m2: Metatype<Any>) -> Bool {
return /* implement - checks type ralationshiop `M1 : M2` and `M1 == M2` */
}
</code></pre>
<h3 id="summaryofsteps:">Summary of Steps:</h3>
<ul>
<li>Revise metatypes in generic context so the old
<code>T.Type</code> notation does not produce
<code>T.Protocol</code> when a protocol metatype is passed
around.</li>
<li>Make <strong>public</strong> <code>T.self</code> notation
return an instance of <code>Type<T></code>.</li>
<li>Rename <strong>internal</strong> <code>T.self</code> notation
to <code>T.metatype</code> (Buildin - not visible in public
Swift).</li>
<li>Rename old metatype <code>T.Type</code> notation to
<code>Metatype<T></code>.</li>
<li>Make <strong>internal</strong> <code>T.metatype</code> notation
return an instance of <code>Metatype<T></code>.</li>
<li>Revise APIs with current <code>T.Type</code> notation to use
<code>Type<T></code> and in few edge cases
<code>Metatype<T></code>.</li>
<li>Move <code>size</code>, <code>stride</code> and
<code>alignment</code> from <strong>SE–0101</strong> to
<code>Type<T></code>.</li>
<li>Provide a concrete declaration for <strong>SE–0096</strong> and
rename it to <code>dynamicMetatype</code>.</li>
<li>Rename current <code>Mirror</code> type (Swift 2.2) to
<code>DebugRepresentation</code> and <code>CustomReflectable</code>
to <code>CustomDebugRepresentable</code>.</li>
<li>Introduce a new <code>Mirror</code> type that is intended to
replace metatypes for most use cases and extended with reflection
in a future release.</li>
</ul>
<h2 id="impactonexistingcode">Impact on existing code</h2>
<p>This is a source-breaking change that can be automated by a
migrator.</p>
<p>The following steps reflects our suggestion of the migration
process, these can differ from the final migration process
implemented by the core team if this proposal will be accepted:</p>
<ul>
<li><code>T.Type</code> → <code>Metatype<T></code></li>
<li><code>T.self</code> → <code>Type<T>.metatype</code></li>
<li><code>Mirror</code> → <code>DebugRepresentation</code></li>
<li><code>CustomReflectable</code> →
<code>CustomDebugRepresentable</code></li>
<li><code>customMirror</code> →
<code>customDebugRepresentation</code></li>
<li><code>sizeof(T.self)</code> →
<code>Type<T>.size</code></li>
<li><code>sizeof(metatype)</code> →
<code>Mirror(metatype).size</code></li>
</ul>
<h3 id="migratingmetatypevariablestousetypetandmirror">Migrating
metatype variables to use <code>Type<T></code> and
<code>Mirror</code></h3>
<p><code>Metatype<T></code> is a safe default for transition,
but we want to discourage usage of metatypes. In some cases, we can
provide fix-its to replace usage of <code>Metatype<T></code>
with <code>Type<T></code> or <code>Mirror</code>.</p>
<p>To change type of a variable named <code>type</code> from
<code>Metatype<T></code> to <code>Type<T></code>:</p>
<ol>
<li>Replace its type with <code>Type<T></code>.</li>
<li>Use the migration patterns below.</li>
<li>If some use case does not match any of these, the variable
cannot be migrated to type <code>Type<T></code>.</li>
</ol>
<p>Migration patterns:</p>
<ul>
<li><code>type = T.self.metatype</code> → <code>type =
T.self</code></li>
<li><code>type = U.self.metatype</code> where <code>U != T</code> →
Automatic migration impossible</li>
<li><code>type = Type<T>.metatype</code> → <code>type =
T.self</code></li>
<li><code>type = Type<U>.metatype</code> where <code>U !=
T</code> → Automatic migration impossible</li>
<li><code>type = otherMetatype</code> where <code>otherMetatype:
Metatype<T></code> → <code>type = T.self</code></li>
<li><code>type = otherMetatype</code> where <code>otherMetatype:
Metatype<U></code>, <code>U != T</code> → Automatic migration
impossible</li>
<li><code>type = mirror.metatype</code> where <code>mirror:
Mirror</code> → Automatic migration impossible</li>
<li><code>otherMetatype = type</code> where <code>otherMetatype:
Metatype<U></code> → <code>otherMetatype =
Type<T>.metatype</code></li>
<li><code>Mirror(type)</code> → <code>Mirror(type)</code></li>
<li><code>type as otherMetatype</code> where <code>otherMetatype:
Metatype<U></code> → <code>type.metatype as
metatype<U></code></li>
<li><code>type as? otherMetatype</code> → Automatic migration
impossible</li>
<li><code>type as! otherMetatype</code> → Automatic migration
impossible</li>
<li><code>type is otherMetatype</code> → Automatic migration
impossible</li>
</ul>
<p>How to change type of a variable named <code>type</code> from
<code>Metatype<T></code> to <code>Mirror</code>:</p>
<ol>
<li>Replace its type with <code>Mirror</code>.</li>
<li>Use the migration patterns below.</li>
<li>If some use case does not match any of these, the variable
cannot be migrated to type <code>Mirror</code>.</li>
</ol>
<p>Migration patterns:</p>
<ul>
<li><code>type: Metatype<T></code> → <code>type:
Mirror</code></li>
<li><code>type = U.self.metatype</code> → <code>type =
Mirror(U.self)</code></li>
<li><code>type = Type<U>.metatype</code> → <code>type =
Mirror(U.self)</code></li>
<li><code>type = otherMetatype</code> → <code>type =
Mirror(otherMetatype)</code></li>
<li><code>type = mirror.metatype</code> where <code>mirror:
Mirror</code> → <code>type = mirror</code></li>
<li><code>otherMetatype = type</code> → <code>otherMetatype =
type.metatype</code></li>
<li><code>Mirror(type)</code> → <code>type</code></li>
<li><code>type as otherMetatype</code> → <code>type.metatype as!
otherMetatype</code></li>
<li><code>type as? otherMetatype</code> → <code>type.metatype as?
otherMetatype</code></li>
<li><code>type as! otherMetatype</code> → <code>type.metatype as!
otherMetatype</code></li>
<li><code>type is otherMetatype</code> →
<code>type.is(otherMetatype)</code></li>
</ul>
<p>We can also migrate metatype parameters of a function, where
assignment means passing an argument to that function.</p>
<p>In two cases we can apply these automatically:</p>
<ol>
<li>If a generic function takes parameter
<code>Metatype<T></code>, then we can try to replace
<code>Metatype<T></code> with
<code>Type<T></code>.</li>
<li>We can try to replace usage of <code>Metatype<Any></code>
(aka <code>AnyMetatype</code>) with <code>Mirror</code>.</li>
</ol>
<h2 id="alternativesconsidered">Alternatives considered</h2>
<ul>
<li>
<p>After refactoring metatypes it is assumed that any metatype can
be stored inside an instance of <code>Metatype<Any></code>.
If that will not be the case, then we propose to introduce a new
standalone type for explained behavior. That type could be named as
<code>AnyMetatype</code>. Therefore any type marked with
<code>Metatype<Any></code> in this proposal will become
<code>AnyMetatype</code>.</p>
</li>
<li>
<p>If the community and the core team are strongly against the
repurposing of <code>Mirror</code> we’d like to consider to merge
the proposed functionality into a single type. For such a change we
do believe <code>Type<T></code> might be the right type here.
However this introduces further complications such as storing
dynamic metatypes inside of <code>Type<T></code> and a few
other that we don’t want go in detail here.</p>
</li>
</ul>
<h2 id="futuredirections">Future directions</h2>
<h3 id="removepublic.self:">Remove public <code>.self</code>:</h3>
<p>When <strong>SE–0090</strong> is accepted we will remove
<code>T.self</code> notation and only have type literals like
<code>T</code>.</p>
<p>Examples:</p>
<pre><code class="swift">let someInstance = unsafeBitCast(1.0, to: Int)
let dynamicSize = Mirror(reflecting: someInstance).size
</code></pre>
<p>Then we can add <code>Type(_: Type<T>)</code> initializer
for disambiguation:</p>
<pre><code class="swift">Int.self.size // Works fine with this proposal, but what if we drop `.self`?
Int.size // Will be an error after dropping `.self`.
Type<Int>().size // Would work, but looks odd.
Type(Int).size // This version looks much better.
</code></pre>
<p>When combined with this proposal, the result will be to
eliminate all ‘magical’ members that existed in the language:</p>
<ul>
<li><code>.dynamicType</code></li>
<li><code>.Type</code></li>
<li><code>.self</code></li>
</ul>
<p>There is also <code>Self</code>, but it acts like an
<code>associatedtype</code>.</p>
<h3 id="extendmirrorwithreflectionfunctionality:">Extend
<code>Mirror</code> with reflection functionality:</h3>
<p>Reflection is one of stated goals for Swift 4. With this
proposal, adding reflection becomes as simple as extending
<code>Mirror</code>. For example, we could add the following
computed property:</p>
<pre><code class="swift">typealias FieldDescriptor = (name: String, type: Mirror, getter: (Any) -> Any, setter: (inout Any, Any) -> ())
var fields: [FieldDescriptor] { get }
</code></pre></div>
<div class="bloop_original_html">
<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_1468960184913713920" 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"></div>
</div></div></span></blockquote></div><div class="bloop_markdown"><p></p></div></body></html>