<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"><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=""><div style="margin: 0px; line-height: normal;" class="">I’d like to request feedback on the draft proposal below, about a (hopefully) trivial change to the standard library.&nbsp;</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">I considered adding it to&nbsp;<a href="https://github.com/apple/swift-evolution/blob/master/proposals/0012-add-noescape-to-public-library-api.md" class="">SE-0012</a>, which is also about @noescape, but that proposal is about modifying C/Obj-C API,&nbsp;<a href="https://github.com/apple/swift-evolution/pull/122" class="">so it’s not a good fit</a>.</div><div style="margin: 0px; line-height: normal;" class=""><b class=""><br class=""></b></div><div style="margin: 0px; line-height: normal;" class=""><b class="">Introduction</b></div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">stdlib’s ManagedBuffer family of APIs has some public initializers and methods taking closures that are missing the @noescape attribute. The same family has a set of withUnsafeMutablePointer* functions that do not have a rethrows declaration, while all similar methods elsewhere in the standard library allow closures to throw.</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">I propose to add the missing @noescape attributes and rethrows.</div><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; font-size: 11px;" class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><br class=""></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><b class="">Motivation</b></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><br class=""></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class="">- ManagedBuffer seems designed for raw performance. Not having @noescape on the only API that allows access to the buffer’s contents defeats some compiler optimizations, such as omitting unneccessary retain/release calls. This can negate the performance advantage of ManagedBuffer over simpler solutions, like using an Array.</div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class="">- Accepting throwing closures makes these APIs more versatile, and also improves their consistency with other parts of stdlib.</div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><br class=""></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><b class="">Detailed Design</b></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><br class=""></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class="">The following set of APIs would be affected by this proposal:</div></div></div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(102, 102, 102);" class=""><span style="font-size: 11px;" class=""><br class=""></span></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div style="margin: 0px; line-height: normal;" class=""><font color="#666666" face="Menlo" style="font-size: 11px;" class="">public class ManagedProtoBuffer&lt;Value, Element&gt; : NonObjectiveCBase {</font></div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(102, 102, 102);" class=""><span style="font-size: 11px;" class="">&nbsp; public final func withUnsafeMutablePointerToValue&lt;R&gt;(body: (UnsafeMutablePointer&lt;Value&gt;) -&gt; R) -&gt; R</span></div><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-size: 11px;" class="">&nbsp; public final func withUnsafeMutablePointerToElements&lt;R&gt;(body: (UnsafeMutablePointer&lt;Element&gt;) -&gt; R) -&gt; R</span></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-size: 11px;" class="">&nbsp; public final func withUnsafeMutablePointers&lt;R&gt;(</span><span style="font-size: 11px;" class="">body: (_: UnsafeMutablePointer&lt;Value&gt;, _: UnsafeMutablePointer&lt;Element&gt;) -&gt; R</span><span style="font-size: 11px;" class="">) -&gt; R</span></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-size: 11px;" class="">}</span></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-size: 11px;" class=""><br class=""></span></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica;" class=""><span style="font-size: 11px;" class=""><font color="#666666" face="Menlo" class="">public class ManagedBuffer&lt;Value, Element&gt;&nbsp;</font><span style="color: rgb(102, 102, 102); font-family: Menlo;" class="">: ManagedProtoBuffer&lt;Value, Element&gt; {</span></span></div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><div class=""><font color="#666666" face="Menlo" style="font-size: 11px;" class="">&nbsp; public final class func create(</font><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class="">minimumCapacity: Int,&nbsp;</span><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class="">initialValue: (ManagedProtoBuffer&lt;Value,Element&gt;) -&gt; Value</span><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class="">) -&gt; ManagedBuffer&lt;Value,Element&gt;&nbsp;</span></div></div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica;" class=""><span style="color: rgb(102, 102, 102); font-family: Menlo; font-size: 11px;" class="">}</span></div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica;" class=""><font color="#666666" face="Menlo" style="font-size: 11px;" class=""><br class=""></font></div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><font face="Menlo" color="#666666" style="font-size: 11px;" class=""><div class="">public struct ManagedBufferPointer&lt;Value, Element&gt; : Equatable {</div></font></div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><font face="Menlo" color="#666666" style="font-size: 11px;" class=""><div class="">&nbsp; public init(bufferClass: AnyClass, minimumCapacity: Int, initialValue: (buffer: AnyObject, allocatedCount: (AnyObject) -&gt; Int) -&gt; Value)</div></font></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><font face="Menlo" color="#666666" style="font-size: 11px;" class=""><div class=""><div class="">&nbsp; public func withUnsafeMutablePointerToValue&lt;R&gt;(body: (UnsafeMutablePointer&lt;Value&gt;) -&gt; R) -&gt; R</div></div></font></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><font face="Menlo" color="#666666" style="font-size: 11px;" class=""><div class=""><div class="">&nbsp; public func withUnsafeMutablePointerToElements&lt;R&gt;(body: (UnsafeMutablePointer&lt;Element&gt;) -&gt; R) -&gt; R</div></div></font></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><font face="Menlo" color="#666666" style="font-size: 11px;" class=""><div class=""><div class="">&nbsp; public func withUnsafeMutablePointers&lt;R&gt;(body: (_: UnsafeMutablePointer&lt;Value&gt;, _: UnsafeMutablePointer&lt;Element&gt;) -&gt; R) -&gt; R</div></div></font></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><font face="Menlo" color="#666666" style="font-size: 11px;" class=""><div class="">}</div></font></div></div></div></blockquote><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><font face="Menlo" color="#666666" style="font-size: 11px;" class=""><div class=""><br class=""></div><div class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; font-size: 11px;" class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class="">Here is how they would look after the proposed changes:</div><div class=""><br class=""></div></div></div></div></font></div></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><font color="#666666" face="Menlo" style="font-size: 11px;" class="">public class ManagedProtoBuffer&lt;Value, Element&gt; : NonObjectiveCBase {</font></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-size: 11px;" class="">&nbsp; public final func withUnsafeMutablePointerToValue&lt;R&gt;(<b class="">@noescape</b> body: (UnsafeMutablePointer&lt;Value&gt;) <b class="">throws</b> -&gt; R) <b class="">rethrows</b> -&gt; R</span></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-size: 11px;" class="">&nbsp; public final func withUnsafeMutablePointerToElements&lt;R&gt;(<b class="">@noescape</b> body: (UnsafeMutablePointer&lt;Element&gt;) <b class="">throws</b> -&gt; R) <b class="">rethrows</b> -&gt; R</span></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-size: 11px;" class="">&nbsp; public final func withUnsafeMutablePointers&lt;R&gt;(</span><span style="font-size: 11px;" class=""><b class="">@noescape</b> body: (_: UnsafeMutablePointer&lt;Value&gt;, _: UnsafeMutablePointer&lt;Element&gt;) <b class="">throws</b> -&gt; R</span><span style="font-size: 11px;" class="">) <b class="">rethrows</b> -&gt; R</span></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(102, 102, 102); font-family: Menlo;" class=""><span style="font-size: 11px;" class=""><br class=""></span></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><div class=""><span style="font-size: 11px;" class=""><font color="#666666" face="Menlo" class="">public class ManagedBuffer&lt;Value, Element&gt;&nbsp;</font><span style="color: rgb(102, 102, 102); font-family: Menlo;" class="">: ManagedProtoBuffer&lt;Value, Element&gt; {</span></span></div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><div class=""><div class=""><font color="#666666" face="Menlo" style="font-size: 11px;" class="">&nbsp; public final class func create(</font><font color="#666666" face="Menlo" style="font-size: 11px;" class="">minimumCapacity: Int,&nbsp;</font><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class=""><b class="">@noescape</b> initialValue: (ManagedProtoBuffer&lt;Value,Element&gt;) -&gt; Value</span><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class="">) -&gt; ManagedBuffer&lt;Value,Element&gt;&nbsp;</span></div></div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><div class=""><span style="color: rgb(102, 102, 102); font-family: Menlo; font-size: 11px;" class="">}</span></div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><span style="color: rgb(102, 102, 102); font-family: Menlo; font-size: 11px;" class=""><br class=""></span></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; font-size: 11px;" class="">public struct ManagedBufferPointer&lt;Value, Element&gt; : Equatable {</div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; font-size: 11px;" class="">&nbsp; public init(bufferClass: AnyClass, minimumCapacity: Int, <b class="">@noescape</b> initialValue: (buffer: AnyObject, allocatedCount: (AnyObject) -&gt; Int) -&gt; Value)</div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><div class=""><div class=""><font color="#666666" face="Menlo" class=""><span style="font-size: 11px;" class="">&nbsp; public func withUnsafeMutablePointerToValue&lt;R&gt;(</span></font><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class=""><b class="">@noescape</b> body: (UnsafeMutablePointer&lt;Value&gt;) <b class="">throws</b> -&gt; R</span><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class="">) <b class="">rethrows</b> -&gt; R</span></div></div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><div class=""><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class=""><div class="">&nbsp; public func withUnsafeMutablePointerToElements&lt;R&gt;(<b class="">@noescape</b> body: (UnsafeMutablePointer&lt;Element&gt;) <b class="">throws</b> -&gt; R) <b class="">rethrows</b> -&gt; R</div></span></div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><div class=""><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class=""><div class=""><div class="">&nbsp; public func withUnsafeMutablePointers&lt;R&gt;(<b class="">@noescape</b> body: (_: UnsafeMutablePointer&lt;Value&gt;,_: UnsafeMutablePointer&lt;Element&gt;) <b class="">throws</b> -&gt; R) <b class="">rethrows</b> -&gt; R</div></div></span></div></div></div></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; font-size: 11px;" class="">}</div></div></div></div></blockquote><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; margin: 0px; line-height: normal;" class=""></div><div class=""><br class=""></div><div class=""><div style="color: rgb(102, 102, 102); font-family: Menlo; font-size: 11px;" class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class="">A draft implementation is available at&nbsp;<a href="https://github.com/apple/swift/compare/master...lorentey:noescape" class="">https://github.com/apple/swift/compare/master...lorentey:noescape</a></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><br class=""></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><b class="">Impact on Existing Code</b></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><br class=""></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class="">Luckily, all modified API is either marked final, or defined in a struct, so I expect no existing code is going to break due to these changes.</div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><br class=""></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class="">--&nbsp;</div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class="">Károly</div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; margin: 0px; line-height: normal;" class=""><br class=""></div></div></div></div></div></body></html>