<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. </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 <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, <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<Value, Element> : 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=""> public final func withUnsafeMutablePointerToValue<R>(body: (UnsafeMutablePointer<Value>) -> R) -> 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=""> public final func withUnsafeMutablePointerToElements<R>(body: (UnsafeMutablePointer<Element>) -> R) -> 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=""> public final func withUnsafeMutablePointers<R>(</span><span style="font-size: 11px;" class="">body: (_: UnsafeMutablePointer<Value>, _: UnsafeMutablePointer<Element>) -> R</span><span style="font-size: 11px;" class="">) -> 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<Value, Element> </font><span style="color: rgb(102, 102, 102); font-family: Menlo;" class="">: ManagedProtoBuffer<Value, Element> {</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=""> public final class func create(</font><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class="">minimumCapacity: Int, </span><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class="">initialValue: (ManagedProtoBuffer<Value,Element>) -> Value</span><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class="">) -> ManagedBuffer<Value,Element> </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<Value, Element> : 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=""> public init(bufferClass: AnyClass, minimumCapacity: Int, initialValue: (buffer: AnyObject, allocatedCount: (AnyObject) -> Int) -> 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=""> public func withUnsafeMutablePointerToValue<R>(body: (UnsafeMutablePointer<Value>) -> R) -> 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=""> public func withUnsafeMutablePointerToElements<R>(body: (UnsafeMutablePointer<Element>) -> R) -> 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=""> public func withUnsafeMutablePointers<R>(body: (_: UnsafeMutablePointer<Value>, _: UnsafeMutablePointer<Element>) -> R) -> 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<Value, Element> : 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=""> public final func withUnsafeMutablePointerToValue<R>(<b class="">@noescape</b> body: (UnsafeMutablePointer<Value>) <b class="">throws</b> -> R) <b class="">rethrows</b> -> 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=""> public final func withUnsafeMutablePointerToElements<R>(<b class="">@noescape</b> body: (UnsafeMutablePointer<Element>) <b class="">throws</b> -> R) <b class="">rethrows</b> -> 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=""> public final func withUnsafeMutablePointers<R>(</span><span style="font-size: 11px;" class=""><b class="">@noescape</b> body: (_: UnsafeMutablePointer<Value>, _: UnsafeMutablePointer<Element>) <b class="">throws</b> -> R</span><span style="font-size: 11px;" class="">) <b class="">rethrows</b> -> 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<Value, Element> </font><span style="color: rgb(102, 102, 102); font-family: Menlo;" class="">: ManagedProtoBuffer<Value, Element> {</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=""> public final class func create(</font><font color="#666666" face="Menlo" style="font-size: 11px;" class="">minimumCapacity: Int, </font><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class=""><b class="">@noescape</b> initialValue: (ManagedProtoBuffer<Value,Element>) -> Value</span><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class="">) -> ManagedBuffer<Value,Element> </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<Value, Element> : 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=""> public init(bufferClass: AnyClass, minimumCapacity: Int, <b class="">@noescape</b> initialValue: (buffer: AnyObject, allocatedCount: (AnyObject) -> Int) -> 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=""> public func withUnsafeMutablePointerToValue<R>(</span></font><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class=""><b class="">@noescape</b> body: (UnsafeMutablePointer<Value>) <b class="">throws</b> -> R</span><span style="font-size: 11px; color: rgb(102, 102, 102); font-family: Menlo;" class="">) <b class="">rethrows</b> -> 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=""> public func withUnsafeMutablePointerToElements<R>(<b class="">@noescape</b> body: (UnsafeMutablePointer<Element>) <b class="">throws</b> -> R) <b class="">rethrows</b> -> 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=""> public func withUnsafeMutablePointers<R>(<b class="">@noescape</b> body: (_: UnsafeMutablePointer<Value>,_: UnsafeMutablePointer<Element>) <b class="">throws</b> -> R) <b class="">rethrows</b> -> 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 <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="">-- </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>