[swift-evolution] Proposal: Allow `[strong self]` capture in closures and remove the `self` requirement therein
Matthew Johnson
matthew at anandabits.com
Tue Dec 15 20:06:32 CST 2015
I believe it has been made clear upthread now, but only the closure is capturing self. Your evil function only stores a copy of the dictionary.
This behavior is identical whether you use [strong self] and metadata or you use self.metadata so I don’t understand why it would be an argument against the proposal. Either way the capture of self by the closure is explicitly represented in the code where it happens. [strong self] actually seems a bit more clear to me.
An example that behaves like you stated could be concocted if we modify your example to pass a bound method rather than a property value, however that seems pretty unlikely to happen unintentionally even if / when we can obtain references to bound property getters / setters.
typealias evilArg = [String:String]
var strongReference: () -> evilArg
func evil(foo: () -> evilArg ) {
strongReference = foo
}
final class Photo {
var data = [UInt8](count: 100000000, repeatedValue: 0) //a large amount of data
func metadata() -> [String: String] { return [:] }
func save() {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)) {
evil(self.metadata)
}
}
}
I understand why you’re afraid of anything that might lead to unintentionally storing a strong reference or creating a reference cycle. I don’t understand why this proposal is likely to make that happen. I would even argue it might make it less likely to happen. If developers get in the habit of using the capture list rather than explicitly using “self.” in the body they will be more likely to capture only what they need. In your example the developer may have specified [metadata = self.metadata] rather than using [strong self] if the metadata value at the time of closure capture was sufficient.
Matthew
> On Dec 15, 2015, at 7:23 PM, Drew Crawford via swift-evolution <swift-evolution at swift.org> wrote:
>
>
>> On Dec 15, 2015, at 7:15 PM, Greg Parker <gparker at apple.com <mailto:gparker at apple.com>> wrote:
>>
>> We could make it more difficult for unaware programmers to *write* the `[strong self]` version, at least. When a programmer writes just `metadata` in a closure, the compiler could continue to suggest using `self.metadata` and not suggest using `[strong self]`.
>
> That's not (especially) the danger I'm worried about.
>
> I'm worried about the case where I write `[strong self] in` and then years later I add the `evil(f)` to the bottom of the closure, because it turns out we need more code in there.
>
> I'm also worried about the case where I write nonEvil(f) but at some later time the implementation of nonEvil(f) becomes evil.
>
> I'm also worried about the case where nonEvil(f) is a call into closed-source UIKit and without any visibility to me, UIKit's implementation of nonEvil becomes evil between iOS10b3 and iOS10b4.
>
> These things are "category 5" bugs waiting to happen, and they can't be competently addressed with a UI-level fix in Xcode.
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151215/ab4b6bf7/attachment.html>
More information about the swift-evolution
mailing list