<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="">This is an amazing document. &nbsp;I do not understand half of it, but the half I do understand will set software engineering forward ten years.<div class=""><br class=""></div><div class="">It will take me a long time to digest all of it, but 2 quick things:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">It is legal to change the implementation of an inlineable function in the next release of the library. However,&nbsp;any such change must be made with the understanding that it may or may not affect existing clients.<br class=""></blockquote><div class=""><br class=""></div><div class="">I think this is wrong. &nbsp;Specifically, let's say I have a security bug in my inlineable function. &nbsp;*Currently*, the industry practice for responding to security issues is "download the new version of the library". &nbsp;But for inlined functions, this is not good enough to correctly apply the patch.</div><div class=""><br class=""></div><div class="">In my view, "somebody" (the linker, the loader, the runtime... it's all greek to me) should say "hold on a minute, you cannot use the new library version, recompile your code". &nbsp;Because as long as it appears the new library version installs/works fine, the security fix is falsely assumed to be applied.</div><div class=""><br class=""></div><div class="">Another thing I think we are missing here is versioning the function bodies themselves. &nbsp;For example (ignore syntax) suppose we have</div><div class=""><br class=""></div></div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class="">public (1.0) func removeTheCacheFiles() {</div></div><div class=""><div class="">&nbsp; &nbsp; &nbsp; os.rmdir("/path/to/cache")</div></div><div class=""><div class="">}</div></div></blockquote><div class=""><div class=""><br class=""></div><div class="">We may evolve this function in two orthogonal ways:</div><div class=""><br class=""></div><div class=""><ol class="MailOutline"><li class="">We may develop other cache files as our program grows</li><li class="">We may discover that we forgot to check if the user is allowed&nbsp;by the security policy&nbsp;to remove the cache files.</li></ol><div class=""><br class=""></div></div><div class="">Therefore we may evolve this function as follows (again, I use pretend syntax):</div><div class=""><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div class="">public (1.0) func removeTheCacheFiles() {</div></div></div><div class=""><div class=""><div class="">&nbsp; &nbsp; &nbsp; precondition(userIsAuthorized()) //this change is backported to 1.0</div></div></div><div class=""><div class=""><div class="">&nbsp; &nbsp; &nbsp; os.rmdir("/path/to/cache")</div></div></div><div class=""><div class=""><div class="">&nbsp; &nbsp; &nbsp; #if 1.1 { //this code only for 1.1-era callers</div></div></div><div class=""><div class=""><div class="">&nbsp; &nbsp; &nbsp; &nbsp; os.rmdir("/path/to/cache2")</div></div></div><div class=""><div class=""><div class="">&nbsp; &nbsp; &nbsp; }</div></div></div><div class=""><div class=""><div class="">}</div></div></div></blockquote><div class=""><div class=""><br class=""></div><div class="">It is important to support this case because very often in server land, certain clients only want to pick up the security fixes (and not, say, new features). &nbsp;See e.g. this&nbsp;<a href="https://www.debian.org/security/faq#oldversion" class="">Debian Security FAQ</a>, where people spend a huge amount of time backporting security fixes to old versions.</div><div class=""><br class=""></div><div class="">I realize this is not at all the practice in "consumer-grade" applications like iOS/OSX/etc., but it is very entrenched in serverland, and I really think there is value in supporting this at the language level for those people who work in that world.</div><div class=""><br class=""></div><div class="">I think the implementation of this is just to compile all possibilities and just let the client pick the implementation based on the API version. &nbsp;I realize this may result in larger binaries, but only when the feature is used, so it's opt-in.</div><div class=""><br class=""></div><div class="">Apologies for not using fancy compiler words, I am still trying to grasp the full implications of this amazing paper.</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 8, 2016, at 8:24 PM, Jordan Rose 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="">Hi, swift-evolution. We've been making references for a while to "resilience" as a cornerstone of the Swift 3.0 work, the collection of features that allows a library to evolve over time while maintaining binary compatibility. Among other things, this is necessary if we want to stop bundling the Swift standard library with any app that uses Swift, a noted complaint from iOS developers. :-)</div><div class=""><br class=""></div><div class="">If you're wondering what this is all about, take a look at the prologue for the design document:</div><div class=""><br class=""><blockquote type="cite" class="">One of Swift’s primary design goals is to allow efficient execution of code without sacrificing load-time abstraction of&nbsp;implementation.<br class=""><br class="">Abstraction of implementation means that code correctly written against a published interface will correctly function when the&nbsp;underlying implementation changes to anything which still satisfies the original interface. There are many potential reasons to&nbsp;provide this sort of abstraction. Apple’s primary interest is in making it easy and painless for our internal and external developers to&nbsp;improve the ecosystem of Apple products by creating good and secure programs and libraries; subtle deployment problems and/or&nbsp;unnecessary dependencies on the behavior of our implementations would work against these goals.<br class=""><br class="">Our current design in Swift is to provide opt-out load-time abstraction of implementation for all language features. Alone, this would&nbsp;either incur unacceptable cost or force widespread opting-out of abstraction. We intend to mitigate this primarily by designing the&nbsp;language and its implementation to minimize unnecessary and unintended abstraction:<br class=""><br class=""><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• Avoiding unnecessary language guarantees and taking advantage of that flexibility to limit load-time costs.<br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• Within the domain that defines an entity, all the details of its implementation are available.<br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• When entities are not exposed outside their defining module, their implementation is not constrained.<br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• By default, entities are not exposed outside their defining modules. This is independently desirable to reduce accidental API&nbsp;surface area, but happens to also interact well with the performance design.<br class=""></div></blockquote><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class="">This last point is a specific case of a general tenet of Swift:&nbsp;<b class="">the default behavior is safe</b>. Where possible, choices made when an&nbsp;entity is first published should not limit its evolution in the future.</blockquote></div><div class=""><br class=""></div><div class="">RFC stands for "request for comments", and that's what this is: I'd appreciate the eager and discriminating eyes of swift-evolution on this model. It is quite long—nearly ten thousand words—and attempts to be fairly precise in describing what is and isn't allowed, so feel free to focus on the parts that interest you most. This isn't a proposal and won't be going through the Swift Evolution Process, but many existing or planned proposals will affect or support the model described here. (There's a list of them at the end of the document.)</div><div class=""><br class=""></div><div class="">The document is written in ReStructuredText to match the rest of the compiler documentation, but it's using some features from the Sphinx system that GitHub's ReST renderer doesn't support. Consequently, I've put up a&nbsp;<a href="http://jrose-apple.github.io/swift-library-evolution/" class="">rendered form</a>, which I'll update every few days when there are changes. (This is pretty much the same rendering you get from running "make" in the docs/ directory in the Swift repo.) The canonical document is still the one&nbsp;<a href="https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst" class="">in the Swift repository</a>.</div><div class=""><br class=""></div><div class="">Looking forward to your feedback!</div><div class="">Jordan</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=""></div></div></body></html>