<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Thanks for the review!<div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Oct 2, 2017, at 10:57 PM, Chris Lattner &lt;<a href="mailto:clattner@nondot.org" class="">clattner@nondot.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="">This is a great proposal, I’m a strong supporter, but have one question and one strong push back:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="">On Oct 2, 2017, at 1:31 PM, Slava Pestov via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><h2 id="toc_1" style="-webkit-print-color-adjust: exact; margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; 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="-webkit-print-color-adjust: exact; 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="-webkit-print-color-adjust: exact; 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></div></div></div></blockquote><div class="">The major question I have is “why yet another attribute”. &nbsp;The thread about exhaustive/extensible enums is similarly proposing introducing another one-off way to be enums fragile, and this is directly related just for function-like things.</div><div class=""><br class=""></div><div class="">I’d love to see rationale in the proposal for why you’re not taking this in one of these directions:</div><div class=""><br class=""></div><div class="">1) Why not another level of access control? &nbsp;There is a reasonable argument that what you’re doing is making something “more public than public” or that you’re making the “body also public”. &nbsp;I’m not strongly in favor of this design approach, but if you agree, the doc should explain why you’re not in favor of it.</div><div class=""><br class=""></div><div class="">2) Why can’t we have a single Swift-wide concept that unifies all of the resilience ideas under a single umbrella like “fragile” - which indicates that the body of a declaration is knowable to clients? &nbsp;There is a very reasonable holistic design where “fragile public func” makes its body inlinable, and “fragile enum” similarly makes the cases knowable to the client (thus making exhaustive switching a possibility). &nbsp;I am strongly in favor of this approach. &nbsp;</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">In any case, even if you’re opposed to these approaches, I’d love for the “alternatives considered” section to indicate what the objection is. &nbsp;I am really very concerned that you’re causing a keyword/attribute explosion and conceptual complexity by adding too many small things to individual parts of the language. &nbsp;We would ideally have a simple and holistic solution to resilience.</div></div></div></div></blockquote><div><br class=""></div>I agree with that keyword/attribute explosion is a concern. We also plan on submitting a proposal to add a @fixedContents attribute for structs (currently implemented as @_fixed_layout) which enables more efficient access patterns in resilient code, for example direct access of stored properties, at the cost of preventing new stored properties from being added in a binary-compatible manner. So we would have ‘nonexhaustive’ enums, @fixedContents structs, and @inlinable functions/properties/initializers.</div><div><br class=""></div><div>Perhaps it makes sense to have a single ‘fragile’ keyword replace @fixedContents and @inlinable. For enums, ‘nonexhaustive’ does “feel” a bit different, so perhaps it makes sense for it to be its own thing. From an implementation perspective it doesn’t really matter if we have multiple attributes or one, so of course I’d prefer to go with the approach that makes the most sense to people language design-wise.</div><div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">This semantic doesn’t make sense to me, and I think we need to change it. &nbsp;I think we are better served with the semantics of “the body may be inlined, but doesn’t have to.”</div></div></div></blockquote><div><br class=""></div>That is the effect it has today. The decision to inline or not is made by the optimizer, and @inlinable doesn’t change anything here; it makes the body available if the optimizer chooses to do so.</div><div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">2) there are lots of reasons why the compiler may not *want* to inline the body of a declaration, including wanting fast debug builds, “optimizing for size” builds, or cost heuristics that lead the compiler to believe that there is no gain for inlining the body of a function in some context.</div></div></div></blockquote><div><br class=""></div>Right.</div><div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">3) If the symbol is always guaranteed to be present, adding @inlinable is an ABI preserving change. &nbsp;I think that this is also really important because it reflects a natural evolution of code: in R1 of a module’s public release, a symbol my be public, but after numerous releases, it may be decided that it is stable enough to make “inlinable”.</div><div class=""><br class=""></div><div class="">4) Certain declarations *have* to be emitted anyway, e.g. an @inlinable open method on a class can’t actually be inlined in most cases, because the call is dynamicly dispatched.</div></div></div></blockquote><div><br class=""></div>Yes. The function is still emitted into the library, but the symbol does not have public linkage. If we make the change to give the attribute ‘always emit into client’ semantics, a client can still reference the function without inlining it, for whatever reason, either because it cannot be (you’re using the function as a value) or the optimizer decides that it is not profitable to inline it. However the client binary would have to emit its own copy of the function (again, with non-public linkage).</div><div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><p style="-webkit-print-color-adjust: exact; 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="-webkit-print-color-adjust: exact; 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></div></div></blockquote><div class="">5) It eliminates this complexity.</div></div></div></blockquote><div><br class=""></div>Yeah. In fact the current implementation of @inlinable does not change the function’s linkage — it remains public. It just enables SIL serialization for the body. I recall the standard library folks had good reasons to prefer the ‘always emit into client’ behavior though; maybe Jordan or Dave can explain.</div><div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><h2 id="toc_8" style="-webkit-print-color-adjust: exact; margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; 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="-webkit-print-color-adjust: exact; 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="-webkit-print-color-adjust: exact; 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="-webkit-print-color-adjust: exact; 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="-webkit-print-color-adjust: exact; 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="-webkit-print-color-adjust: exact; 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="-webkit-print-color-adjust: exact; 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="-webkit-print-color-adjust: exact; 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="-webkit-print-color-adjust: exact; 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 can only reference other "public" declarations, that is, those that are defined in other header files.</p></div></div></blockquote><div class="">The writing should be clarified, because there are multiple concepts going on here, including GNU89’s notion of inline, C99’s notion of inline (aka extern inline), and static inline, each with overlapping but and confusingly different semantics.</div></div></div></blockquote><div><br class=""></div>Can you suggest some better wording for this section? I admit I don’t know C very well compared to some of you here, having never implemented my own C compiler or participated in standards committee. :-)</div><div><br class=""></div><div>Slava</div><div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><div class="">-Chris</div><div class=""><br class=""></div></div><br class=""></div></blockquote></div><br class=""></div></body></html>