<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>This places the burden on users. &nbsp;The library is not able to offer a guarantee.<br><br>Sent from my iPad</div><div><br>On Feb 19, 2017, at 1:20 AM, Derrick Ho &lt;<a href="mailto:wh1pch81n@gmail.com">wh1pch81n@gmail.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><div>What wrong with [unowned self]<br><div class="gmail_quote"><div dir="ltr">On Sat, Feb 18, 2017 at 11:01 PM Daniel Duan via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This reminded me of an idea I had long time ago which will have a similar effect: add a way to disable implicit captures for closures. FWIW.<br class="gmail_msg">
<br class="gmail_msg">
&gt; On Feb 18, 2017, at 5:24 PM, Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; # `@selfsafe`: a new way to avoid reference cycles<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; * Proposal: [SE-NNNN](NNNN-selfsafe.md)<br class="gmail_msg">
&gt; * Authors: [Matthew Johnson](<a href="https://github.com/anandabits" rel="noreferrer" class="gmail_msg" target="_blank">https://github.com/anandabits</a>)<br class="gmail_msg">
&gt; * Review Manager: TBD<br class="gmail_msg">
&gt; * Status: **Awaiting review**<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ## Introduction<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; This proposal introduces the `@selfsafe` function argument attribute which together with a `withWeakSelf` property on values of function type.&nbsp; Together these features enable library authors to create APIs can be statically verified to never extend the lifetime of the `self` a function they take may have captured.&nbsp; This is accomplished by allowing the library implementation convert the function to a nearly identical function that is guaraneteed to have a `weak` capture of `self` and be a no-op after `self` is released.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; Swift-evolution thread: []()<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ## Motivation<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; Accidentally forgeting to use weak references is a common problem and can easily lead to reference cycles.&nbsp; Some APIs are best designed such that users *cannot* extend the lifetime of `self` by escaping a closure that happens to strongly capture `self`.&nbsp; For example, `UIControl.addTarget(_:action:for:) does not retain the target, thereby preventing users from making the mistake of using a closure with an accidental strong reference.&nbsp; We can do something similar in Swift:<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ```swift<br class="gmail_msg">
&gt; // in the library:<br class="gmail_msg">
&gt; func addTarget&lt;T: AnyObject&gt;(_ target: T, action: T -&gt; Int -&gt; Void) {<br class="gmail_msg">
&gt;&nbsp; &nbsp;// store a weak reference to the target<br class="gmail_msg">
&gt;&nbsp; &nbsp;// when the action is fired call ref.map{ action($0)(42) }<br class="gmail_msg">
&gt; }<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; // in user code:<br class="gmail_msg">
&gt; class C {<br class="gmail_msg">
&gt;&nbsp; &nbsp;init() {<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; addTarget(self, action: C.takesInt)<br class="gmail_msg">
&gt;&nbsp; &nbsp;}<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;&nbsp; &nbsp;func takesInt(_ i: Int) {}<br class="gmail_msg">
&gt; }<br class="gmail_msg">
&gt; ```<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; Both the library and the caller have to deal with a lot of details and boilerplate that we would prefer to avoid.&nbsp; The natural design in Swift would be to simply take an action function.&nbsp; Unfortunately if we do that we run into a problem:<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ```swift<br class="gmail_msg">
&gt; // in the library<br class="gmail_msg">
&gt; func addAction(_ f: Int -&gt; Void) {<br class="gmail_msg">
&gt;&nbsp; &nbsp;// store a strong ref to f, which might include a strong ref to a captured self<br class="gmail_msg">
&gt;&nbsp; &nbsp;// later when the action is fired call f(42)<br class="gmail_msg">
&gt; }<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; // in user code<br class="gmail_msg">
&gt; class C {<br class="gmail_msg">
&gt;&nbsp; &nbsp;init() {<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; addAction(takesInt)<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; // oops! should have been: addAction{ [weak self] self?.takesInt($0) }<br class="gmail_msg">
&gt;&nbsp; &nbsp;}<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;&nbsp; &nbsp;func takesInt(_ i: Int) {}<br class="gmail_msg">
&gt; }<br class="gmail_msg">
&gt; ```<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; Here the syntax is much nicer, but unfortunately we have unintentionally extended the lifetime of `self`.&nbsp; The burden of ensuring `self` is not captured or captured weakly falls on users of the library.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; It would very nice if it were possible to design an API that has weak capture semantics while still acheiving the more concise and Swifty syntax.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ## Proposed Solution<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; This proposal introduces a read-only property on all function types: `withWeakSelf` as well as a `@selfsafe` function argument annotation.&nbsp; (This name for the annotation is a strawman - I would love to hear better ideas)<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ### `withWeakSelf`<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; `withWeakSelf` can be imagined as a property declared like the following:<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ```swift<br class="gmail_msg">
&gt; extension T -&gt; Void {<br class="gmail_msg">
&gt;&nbsp; var withWeakSelf: T -&gt; Void { return // compiler magic }<br class="gmail_msg">
&gt; }<br class="gmail_msg">
&gt; extension T -&gt; U {<br class="gmail_msg">
&gt;&nbsp; var withWeakSelf: T -&gt; U? { return // compiler magic }<br class="gmail_msg">
&gt; }<br class="gmail_msg">
&gt; extension T -&gt; U? {<br class="gmail_msg">
&gt;&nbsp; var withWeakSelf: T -&gt; U? { return // compiler magic }<br class="gmail_msg">
&gt; }<br class="gmail_msg">
&gt; ```<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; It returns a closure that is identical to itself in every respect except four:<br class="gmail_msg">
&gt; 1. If the context includes a strong or unowned `self` capture, that is converted to a weak capture.<br class="gmail_msg">
&gt; 2. If the function returns a non-`Void`, non-`Optional` type the return type is wrapped in an `Optional`.<br class="gmail_msg">
&gt; 3. The function returned by `withWeakSelf` is a no-op after `self` has been released.&nbsp; If the return type is non-`Void`, the function returns `nil` after `self` has been released.<br class="gmail_msg">
&gt; 4. Any addtional non-`self` context is released as soon as possible after `self` is released.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; From these rules, it follows that `withWeakSelf` can be a no-op unless `self` is captured strong or unowned or the return type is non-`Void` and non-`Optional`.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; Important note: any additional context the closure requies beyond `self` continues to be captured as it was originally.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ### `@selfsafe`<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; When a function argument is annotated with `@selfsafe` two rules are in effect for the implementation:<br class="gmail_msg">
&gt; 1. The argument *is not* allowed to escape the function.<br class="gmail_msg">
&gt; 2. The closure returend by `withWeakSelf` *is* allowed to escape the function.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; There should also be a warning if `argument.withWeakSelf` *does not* escape the function in any code paths (because the `@selfsafe` annotation is meaningless if it does not escape).<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; This allows a library to do something like the following (a simplified version of a hypothetical future method on `UIControl`):<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ```swift<br class="gmail_msg">
&gt;&nbsp; &nbsp;class UIControl {<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; var action: () -&gt; Void<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; func setAction(_ action: @selfsafe () -&gt; Void) {<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self.action = action.withWeakSelf<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; }<br class="gmail_msg">
&gt;&nbsp; &nbsp;}<br class="gmail_msg">
&gt; ```<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; In the previous example the function declares the argument with the `@selfsafe` annotation.&nbsp; The compiler verifies that the `action` argument does not escape `setAction` and that `action.withWeakSelf` *does* escape.&nbsp; Because these verifications guarantee that the lifetime of `self` cannot be exteneded by calling `setAction`, the compiler can allow users to omit `self` if this function is called with a closure.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ```swift<br class="gmail_msg">
&gt; class UIViewController {<br class="gmail_msg">
&gt;&nbsp; &nbsp;func viewDidLoad() {<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; &nbsp;// misc setup<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; &nbsp;myControl.setAction(doSomething) // great! no problem creating a reference cycle.<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; &nbsp;myOtherControl.setAction {<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // `self.doSomethingElse()` is not required.<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // The compiler knows we cannot create a reference cycle here.<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; doSomethingElse()<br class="gmail_msg">
&gt;&nbsp; &nbsp; &nbsp; &nbsp;}<br class="gmail_msg">
&gt;&nbsp; &nbsp;}<br class="gmail_msg">
&gt;&nbsp; &nbsp;func doSomething() {}<br class="gmail_msg">
&gt;&nbsp; &nbsp;func doSomethingElse() {}<br class="gmail_msg">
&gt; }<br class="gmail_msg">
&gt; ```<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ## Detailed design<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; TBD - If anyone can think of additional details that need to be spelled out please provide feedback in this thread.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ## Source compatibility<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; No effect.&nbsp; This is a purely additive change.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ## Effect on ABI stability<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; No effect.&nbsp; This is a purely additive change.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ## Effect on API resilience<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; No effect.&nbsp; This is a purely additive change.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; ## Alternatives considered<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; I considered various ways of exposing the entire captured context or the captured `self` reference directly as properties of function types, along with access to an unbound version of the function.&nbsp; This turns out to be far more complex than necessary to solve the problem this proposal aims to solve and doesn't enable any interesting use cases I have thought of.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; _______________________________________________<br class="gmail_msg">
&gt; swift-evolution mailing list<br class="gmail_msg">
&gt; <a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg">
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
<br class="gmail_msg">
_______________________________________________<br class="gmail_msg">
swift-evolution mailing list<br class="gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
</blockquote></div>
</div></blockquote></body></html>