<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">Today's @available can't be the thing that makes symbols public, since it's also used to affect the availability context for private symbols. The one described in the library evolution document is specifically about marking something available with respect to the <i class="">current</i>&nbsp;module. So we would want another spelling.</div><div class=""><br class=""></div><div class="">(But it definitely shouldn't be "_versioned", which doesn't mean anything if we don't have "versions".)</div><div class=""><br class=""></div><div class="">Jordan</div><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Oct 2, 2017, at 13:47, Slava Pestov via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Thanks for taking a look.</div><div class=""><br class=""></div>@_versioned is not something we want to keep in the long term. The original idea was to allow @available annotations to be put on internal declarations, which would have the effect of giving their symbols public linkage. I think a follow-up proposal could introduce this feature as well as “conditionally available inlinable”, which I describe in document below. However if people feel strongly we could roll both of them into this proposal, but it would require some more implementation work.<div class=""><br class=""></div><div class="">Slava</div><div class=""><br class=""><div class=""><div class=""><blockquote type="cite" class=""><div class="">On Oct 2, 2017, at 1:44 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Very much looking forward to this. Any possibility of rolling in some version (ha) of @_versioned so that @inlinable functions can reference internal declarations?<div class=""><br class=""><div class="gmail_extra"><br class=""><div class="gmail_quote">On Mon, Oct 2, 2017 at 3:31 PM, Slava Pestov via swift-evolution <span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="">Hi all,<div class=""><br class=""></div><div class="">Here is a draft proposal that makes public a feature we’ve had for a while. Let me know what you think!</div><div class=""><br class=""></div><div class=""><h1 id="m_-8310696697508219353toc_0" style="margin:0px 0px 10px;padding:0px;font-size:28px;font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)" class="">Cross-module inlining and specialization ("@inlinable")</h1><ul style="margin:15px 0px;padding-left:30px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class=""><li style="margin:0px" class="">Proposal:&nbsp;<a style="color:rgb(65,131,196);margin-top:0px" class="">SE-NNNN</a></li><li style="margin:0px" class="">Authors:&nbsp;<a href="https://github.com/slavapestov" style="color:rgb(65,131,196);margin-top:0px" target="_blank" class="">Slava Pestov</a>,&nbsp;<a href="https://github.com/jrose-apple" style="color:rgb(65,131,196)" target="_blank" class="">Jordan Rose</a></li><li style="margin:0px" class="">Review Manager: TBD</li><li style="margin:0px" class="">Status:&nbsp;<strong style="margin-top:0px" class="">Initial pitch</strong></li><li style="margin:0px" class="">Implementation: Already implemented as an underscored attribute&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@_inlineable</code></li></ul><h2 id="m_-8310696697508219353toc_1" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)" class="">Introduction</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">We propose introducing an&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;attribute which exports the body of a function as part of a module's interface, making it available to the optimizer when referenced from other modules.</p><h2 id="m_-8310696697508219353toc_2" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)" class="">Motivation</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">One of the top priorities of the Swift 5 release is a design and implementation of&nbsp;<em class="">the Swift ABI</em>. This effort consists of three major tasks:</p><ul style="margin:15px 0px;padding-left:30px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class=""><li style="margin:0px" class=""><p style="margin:0px 0px 15px" class="">Finalizing the low-level function calling convention, layout of data types, and various runtime data structures. The goal here is to maintain compatibility across compiler versions, ensuring that we can continue to make improvements to the Swift compiler without breaking binaries built with an older version of the compiler.</p></li><li style="margin:0px" class=""><p style="margin:0px 0px 15px" class="">Implementing support for&nbsp;<em style="margin-top:0px" class="">library evolution</em>, or the ability to make certain source-compatible changes, without breaking binary compatibility. Examples of source-compatible changes we are considering include adding new stored properties to structs and classes, removing private stored properties from structs and classes, adding new public methods to a class, or adding new protocol requirements that have a default implementation. The goal here is to maintain compatibility across framework versions, ensuring that framework authors can evolve their API without breaking binaries built against an older version of the framework. For more information about the resilience model, see the&nbsp;<a href="https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst" style="color:rgb(65,131,196)" target="_blank" class="">library evolution document</a>&nbsp;in the Swift repository.</p></li><li style="margin:0px" class=""><p style="margin:0px 0px 15px" class="">Stabilizing the API of the standard library. The goal here is to ensure that the standard library can be deployed separately from client binaries and frameworks, without forcing recompilation of existing code.</p></li></ul><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">All existing language features of Swift were designed with these goals in mind. In particular, the implementation of generic types and functions relies on runtime reified types to allow separate compilation and type checking of generic code.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">Within the scope of a single module, the Swift compiler performs very aggressive optimization, including full and partial specialization of generic functions, inlining, and various forms of interprocedural analysis.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">On the other hand, across module boundaries, runtime generics introduce unavoidable overhead, as reified type metadata must be passed between functions, and various indirect access patterns must be used to manipulate values of generic type. We believe that for most applications, this overhead is negligible compared to the actual work performed by the code itself.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">However, for some advanced use cases, and in particular for the standard library, the overhead of runtime generics can dominate any useful work performed by the library. Examples include the various algorithms defined in protocol extensions of&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">Sequence</code>&nbsp;and&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">Collection</code>, for instance the&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">map</code>method of the&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">Sequence</code>&nbsp;protocol. Here the algorithm is very simple and spends most of its time manipulating generic values and calling to a user-supplied closure; specialization and inlining can completely eliminate the algorithm of the higher-order function call and generate equivalent code to a hand-written loop manipulating concrete types.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">We would like to annotate such functions with the&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;attribute. This will make their bodies available to the optimizer when building client code; on the other hand, calling such a function will cause it to be emitted into the client binary, meaning that if a library were to change the definition of such a function, only binaries built against the newer version of library will use the new definition.</p><h2 id="m_-8310696697508219353toc_3" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)" class="">Proposed solution</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">The&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;attribute causes the body of a function to be emitted as part of the module interface. For example, a framework can define a rather impractical implementation of an algorithm which returns&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">true</code>&nbsp;if all elements of a sequence are equal or if the sequence is empty, and&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">false</code>otherwise:</p><div style="font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class=""><pre class="m_-8310696697508219353language-swift" style="margin-top:0.5em;margin-bottom:0.5em;background-color:rgb(245,242,240);border:1px solid rgb(204,204,204);font-size:13px;line-height:1.5;overflow:auto;padding:1em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;word-spacing:normal;word-break:normal;word-wrap:normal"><code class="m_-8310696697508219353language-swift" style="margin:0px;padding:0px;border:none;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-image:none;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5">@inlinable <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">public</span> <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">func</span> allEqual<span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">&lt;</span>T<span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">&gt;</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">(</span><span class="m_-8310696697508219353token m_-8310696697508219353number" style="color:rgb(153,0,85)">_</span> seq<span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">:</span> T<span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">)</span> <span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">-</span><span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">&gt;</span> <span class="m_-8310696697508219353token m_-8310696697508219353builtin" style="color:rgb(102,153,0)">Bool</span>
    <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">where</span> T <span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">:</span> <span class="m_-8310696697508219353token m_-8310696697508219353builtin" style="color:rgb(102,153,0)">Sequence</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">,</span> T<span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">.</span><span class="m_-8310696697508219353token m_-8310696697508219353builtin" style="color:rgb(102,153,0)">Element</span> <span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">:</span> <span class="m_-8310696697508219353token m_-8310696697508219353builtin" style="color:rgb(102,153,0)">Equatable</span> <span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">{</span>
  <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">var</span> iter <span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">=</span> seq<span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">.</span><span class="m_-8310696697508219353token m_-8310696697508219353function" style="color:rgb(221,74,104)">makeIterator</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">(</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">)</span>
  <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">guard</span> <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">let</span> <span class="m_-8310696697508219353token m_-8310696697508219353builtin" style="color:rgb(102,153,0)">first</span> <span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">=</span> iter<span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">.</span><span class="m_-8310696697508219353token m_-8310696697508219353function" style="color:rgb(221,74,104)">next</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">(</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">)</span> <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">else</span> <span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">{</span> <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">return</span> <span class="m_-8310696697508219353token m_-8310696697508219353boolean" style="color:rgb(153,0,85)">true</span> <span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">}</span>

  <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">func</span> <span class="m_-8310696697508219353token m_-8310696697508219353function" style="color:rgb(221,74,104)">rec</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">(</span><span class="m_-8310696697508219353token m_-8310696697508219353number" style="color:rgb(153,0,85)">_</span> iter<span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">:</span> <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">inout</span> T<span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">.</span><span class="m_-8310696697508219353token m_-8310696697508219353builtin" style="color:rgb(102,153,0)">Iterator</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">)</span> <span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">-</span><span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">&gt;</span> <span class="m_-8310696697508219353token m_-8310696697508219353builtin" style="color:rgb(102,153,0)">Bool</span> <span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">{</span>
    <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">guard</span> <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">let</span> next <span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">=</span> iter<span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">.</span><span class="m_-8310696697508219353token m_-8310696697508219353function" style="color:rgb(221,74,104)">next</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">(</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">)</span> <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">else</span> <span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">{</span> <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">return</span> <span class="m_-8310696697508219353token m_-8310696697508219353boolean" style="color:rgb(153,0,85)">true</span> <span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">}</span>
    <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">return</span> next <span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">==</span> <span class="m_-8310696697508219353token m_-8310696697508219353builtin" style="color:rgb(102,153,0)">first</span> <span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">&amp;&amp;</span> <span class="m_-8310696697508219353token m_-8310696697508219353function" style="color:rgb(221,74,104)">rec</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">(</span><span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">&amp;</span>iter<span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">)</span>
  <span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">}</span>

  <span class="m_-8310696697508219353token m_-8310696697508219353keyword" style="color:rgb(0,119,170)">return</span> <span class="m_-8310696697508219353token m_-8310696697508219353function" style="color:rgb(221,74,104)">rec</span><span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">(</span><span class="m_-8310696697508219353token m_-8310696697508219353operator" style="color:rgb(166,127,89);background-color:rgba(255,255,255,0.498039);background-position:initial initial;background-repeat:initial initial">&amp;</span>iter<span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">)</span>
<span class="m_-8310696697508219353token m_-8310696697508219353punctuation" style="color:rgb(153,153,153)">}</span></code></pre></div><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">A client binary built against this framework can call&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">allEqual()</code>&nbsp;and enjoy a possible performance improvement when built with optimizations enabled, due to the elimination of abstraction overhead.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">On the other hand, once the framework author comes to their senses and implements an iterative solution to replace the recursive algorithm defined above, the client binary cannot make use of the more efficient implementation until recompiled.</p><h2 id="m_-8310696697508219353toc_4" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)" class="">Detailed design</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">The new&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;attribute can only be applied to the following kinds of declarations:</p><ul style="margin:15px 0px;padding-left:30px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class=""><li style="margin:0px" class="">Functions and methods</li><li style="margin:0px" class="">Subscripts</li><li style="margin:0px" class="">Computed properties</li><li style="margin:0px" class="">Initializers</li><li style="margin:0px" class="">Deinitializers</li></ul><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">The attribute can only be applied to public declarations. This is because the attribute only has an effect when the declaration is used from outside of the module. Within a module, the optimizer can always rely on the function body being available.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">For similar reasons, the attribute cannot be applied to local declarations, that is, declarations nested inside functions or statements. However, local functions and closure expressions defined inside public&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;functions are always implicitly&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">When applied to subscripts or computed properties, the attribute applies to the getter, setter,&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">didSet</code>and&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">willSet</code>, if present.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">The compiler will enforce certain restrictions on bodies of inlinable declarations:</p><ul style="margin:15px 0px;padding-left:30px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class=""><li style="margin:0px" class=""><p style="margin:0px 0px 15px" class="">inlinable declarations cannot define local types. This is because all types have a unique identity in the Swift runtime, visible to the language in the form of the&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">==</code>&nbsp;operator on metatype values. It is not clear what it would mean if two different libraries inline the same local type from a third library, with all three libraries linked together into the same binary. This becomes even worse if two&nbsp;<em class="">different</em>&nbsp;versions of the same inlinable function appear inside the same binary.</p></li><li style="margin:0px" class=""><p style="margin:0px 0px 15px" class="">inlinable declarations can only reference other public declarations. This is because they can be emitted into the client binary, and are therefore limited to referencing symbols that the client binary can reference.</p></li></ul><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class=""><strong class="">Note:</strong>&nbsp;The restrictions enforced on the bodies of&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;declarations are exactly those that we have in place on default argument expressions of&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">public</code>&nbsp;functions in Swift 4.</p><h2 id="m_-8310696697508219353toc_5" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)" class="">Source compatibility</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">The introduction of the&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;attribute is an additive change to the language and has no impact on source compatibility.</p><h2 id="m_-8310696697508219353toc_6" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)" class="">Effect on ABI stability</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">The introduction of the&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;attribute does not change the ABI of existing declarations. However, adding&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;to an existing declaration changes ABI, because the declaration will no longer have a public entry point in the generated library. Removing&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;from an existing declaration does not change ABI, because it merely introduces a new public symbol in the generated library.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">We have discussed adding a "versioned&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>" variant that preserves the public entry point for older clients, while making the declaration inlinable for newer clients. This will likely be a separate proposal and discussion.</p><h2 id="m_-8310696697508219353toc_7" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)" class="">Effect on API resilience</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">Because a declaration marked&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;is not part of the library ABI, removing such a declaration is a binary-compatible, but source-incompatible change.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">Any changes to the body of a declaration marked&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;should be considered very carefully. As a general guideline, we feel that&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;makes the most sense with "obviously correct" algorithms which manipulate other data types abstractly through protocols, so that any future changes to an&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;declaration are optimizations that do not change observed behavior.</p><h2 id="m_-8310696697508219353toc_8" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)" class="">Comparison with other languages</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">The closest language feature to the&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;attribute is found in C and C++. In C and C++, the concept of a header file is similar to Swift's binary&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">swiftmodule</code>&nbsp;files, except they are written by hand and not generated by the compiler. Swift's&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">public</code>&nbsp;declarations are roughly analogous to declarations whose prototypes appear in a header file.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">Header files mostly contain declarations without bodies, but can also declare&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">static inline</code>functions with bodies. Such functions are not part of the binary interface of the library, and are instead emitted into client code when referenced. As with&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;declarations,&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class=""><wbr class="">static inline</code>functions can only reference other "public" declarations, that is, those that are defined in other header files.</p><h2 id="m_-8310696697508219353toc_9" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)" class="">Alternatives considered</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">One possible alterative would be to add a new compiler mode where&nbsp;<em class="">all</em>&nbsp;declarations become implicitly&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">However, such a compilation mode would not solve the problem of delivering a stable ABI and standard library which can be deployed separately from user code. We&nbsp;<em class="">don't want</em>&nbsp;all declaration bodies in the standard library to be available to the optimizer when building user code.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">While such a feature might be useful for users who build private frameworks that are always shipped together their application without resilience concerns, we do not feel it aligns with our goals for ABI stability, and at best it should be a separate discussion.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">For similar reasons, we do not feel that an "opt-out" attribute that can be applied to declarations to mark them non-inlinable makes sense.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">We have also considered generalizing&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;to allow it to be applied to entire blocks of declarations, for example at the level of an extension. As we gain more experience with using this attribute in the standard library we might decide this would be a useful addition, but we feel that for now, it makes sense to focus on the case of a single inlinable declaration instead. Any future generalizations can be introduced as additive language features.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">We originally used the spelling&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlineable</code>&nbsp;for the attribute. However, we settled on&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;for consistency with the&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">Decodable</code>&nbsp;and&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">Encodable</code>&nbsp;<wbr class="">protocols, which are named as they are and not&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">Decodeable</code>&nbsp;and&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">Encodeable</code>.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)" class="">Finally, we have considered some alternate spellings for this attribute. The name&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@inlinable</code>&nbsp;is somewhat of a misnomer, because nothing about it actually forces the compiler to inline the declaration; it might simply generate a concrete specialization of it, or look at the body as part of an interprocedural analysis, or completely ignore the body. We have considered&nbsp;<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px" class="">@<wbr class="">alwaysEmitIntoClient</code>&nbsp;as a more accurate, but awkward, spelling of the attribute's behavior.</p></div></div><br class="">______________________________<wbr class="">_________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class="">
<br class=""></blockquote></div><br class=""></div></div></div>
</div></blockquote></div><br class=""></div></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>