<div dir="ltr"><a href="https://github.com/tanadeau/swift-evolution/blob/make-noescape-default/proposals/XXXX-make-noescape-default.md">https://github.com/tanadeau/swift-evolution/blob/make-noescape-default/proposals/XXXX-make-noescape-default.md</a><div><br></div><div><div># Make non-escaping closures the default</div><div><br></div><div>* Proposal: [SE-NNNN](NNNN-name.md)</div><div>* Author: [Trent Nadeau](<a href="https://github.com/tanadeau">https://github.com/tanadeau</a>)</div><div>* Status: **Awaiting review**</div><div>* Review manager: TBD</div><div><br></div><div>## Introduction</div><div><br></div><div>The current default of closure arguments to functions (i.e., arguments to functions that themselves have function type such as `(T) -> U`) is to be "escaping", meaning they can escape the function body such as saving it to a field in a struct or a global variable. In order to say that a closure argument cannot possibly escape the function body ("non-escaping"), the developer must explicitly add an `@noescape` annotation to the argument type.</div><div><br></div><div>This proposal switches the default to be non-escaping and requires an `@escaping` annotation if a closure argument can escape the function body. Since the escaping case can be statically detected, this annotation can be added via an error with a fixit. Other annotations that have consequences for escape semantics (e.g., `@autoclosure(escaping)`) will be altered to make use of the new `@escaping` annotation.</div><div><br></div><div>Swift-evolution threads: [Discussion thread topic for that proposal (TBD)](<a href="http://news.gmane.org/gmane.comp.lang.swift.evolution">http://news.gmane.org/gmane.comp.lang.swift.evolution</a>)</div><div><br></div><div>## Motivation</div><div><br></div><div>Per Chris Lattner [on swift-evolution](<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160530/019880.html">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160530/019880.html</a>):</div><div><br></div><div>> To provide some more details, this approach has the following advantages:</div><div>></div><div>> - Most functional algorithms written in pure Swift will benefit because they are naturally noescape. The core team feels that this will reduce the boilerplate involved with writing these algorithms.</div><div>></div><div>> - The compiler has enough logic in it to provide a great QoI experience when a developer doesn’t think about escaping, and tries to escape a closure - it can provide a fixit that suggests adding @escaping.</div><div>></div><div>> - Recent changes (to disallow escaping closures to close over an inout parameter) are pushing the language to prefer noescape closures. noescape closures have also always been the preferred default, since they eliminate a class of retain cycle issues.</div><div>></div><div>> - "@autoclosure(escaping)" can be simplified and standardized to "@autoclosure @escaping”</div><div><br></div><div>## Detailed design</div><div><br></div><div>The `@noescape` annotation is removed from the language. The compiler will emit an error with a fixit to remove the annotation.</div><div><br></div><div>The compiler will emit an error if a closure argument is found to possibly escape the function body. In order to silence the warning, the developer must add, manually or via fixit, the `@escaping` annotation to the argument type.</div><div><br></div><div>The compiler's semantic analysis implementation can be simplified as the more constrained escaping case that conflicts with other attributes is now no longer the default.</div><div><br></div><div>The standard library should be changed to use the new default whenever possible by removing all uses of `@noescape` and only adding `@escaping` where the compiler detects the need.</div><div><br></div><div>### Imported C/Objective-C APIs</div><div><br></div><div>Per the Core Team, most Cocoa closure/block parameters are escaping (e.g., delegates). As such the Clang importer will automatically add the `@escaping` annotation to closure/block parameters encountered in imported Objective-C APIs unless they are explicitly marked with the Clang `((noescape))` attribute. This will also be done with imported C APIs with function pointer or block parameters.</div><div><br></div><div>## Impact on existing code</div><div><br></div><div>Existing code using the `@noescape` attribute will need to be migrated to remove the attribute since it will be the default. In addition, the compiler will need to detect escaping closures that are not marked with `@escaping` and create an error with a fixit to add the required attribute.</div><div><br></div><div>Uses of `@autoclosure(escaping)` must be changed to `@autoclosure @escaping`.</div><div><br></div><div>There should be few, if any, changes required for uses of Cocoa APIs as these will be mostly marked as `@escaping`, and escaping closure arguments are *more* constrained than non-escaping ones.</div><div><br></div><div>## Future directions</div><div><br></div><div>The `@noescape(once)` annotation proposed in [SE-0073](<a href="https://github.com/apple/swift-evolution/blob/master/proposals/0073-noescape-once.md">https://github.com/apple/swift-evolution/blob/master/proposals/0073-noescape-once.md</a>) would, if some future version is accepted, just become `@once`.</div><div><br></div><div>## Alternatives considered</div><div><br></div><div>Leave the `@noescape` attribute and existing semantics as they are now.</div><div><br></div><div>## Acknowledgements</div><div><br></div><div>Thanks to Chris Lattner, **TBD**, and anyone else who reviewed and contributed to this proposal.</div><div><br></div><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">Trent Nadeau</div>
</div></div>