<html><head><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=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 15, 2015, at 5:02 PM, Drew Crawford <<a href="mailto:drew@sealedabstract.com" class="">drew@sealedabstract.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><br class="" style="font-family: HelveticaNeue; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class="" style="font-family: HelveticaNeue; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Can you explain what is so evil about func evil() when it is called from an asynchronously-executed closure? I don't see an obvious bug here.</div></div></blockquote><br class=""></div><div class="">Apologies for earlier brevity, perhaps it would be helpful for me to present a more complete, realistic example. Paste the following into main.swift:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">import Foundation</div><div class=""><br class=""></div><div class="">print("Hello, World!")</div><div class=""><br class=""></div><div class="">typealias evilArg = [String:String]</div><div class="">var strongReference: evilArg! = nil</div><div class="">func evil(foo:evilArg ) {</div><div class=""> strongReference = foo</div><div class="">}</div><div class=""><br class=""></div><div class="">final class Photo {</div><div class=""> var data = [UInt8](count: 100000000, repeatedValue: 0) //a large amount of data</div><div class=""> let metadata: [String: String] = [:] //a small amount of data</div><div class=""> func save() {</div><div class=""> dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)) {</div><div class=""> evil(self.metadata)</div><div class=""> }</div><div class=""> }</div><div class="">}</div><div class="">let p = Photo()</div><div class="">p.save()</div><div class="">//leaks Photo, data, and metadata</div><div class=""><br class=""></div><div class="">let sema = dispatch_semaphore_create(0)</div><div class="">dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)</div></blockquote><div class=""><br class=""></div><div class="">In this example, the memory usage at the end of the program is 100MB:</div><div class=""><br class=""></div><div class=""><span id="cid:E8D5A738-4C93-40B4-8880-82217923A57F@austin.rr.com"><Screen Shot 2015-12-15 at 6.26.52 PM.png></span></div><div class=""><br class=""></div><div class="">This is because Photo, data, and metadata are all leaked by the evil function.</div><div class=""><br class=""></div><div class="">This is the (surprising?) behavior specified in the Swift Book:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">[A capture occurs when] the closure’s body accesses a property of the instance, such as self.someProperty, or because the closure calls a method on the instance, such as self.someMethod(). In either case, these accesses cause the closure to “capture” self, creating a strong reference cycle.<br class=""></blockquote></div><div class=""><br class=""></div><div class="">Even though evil may seem (to the casual programmer who does not read language specifications for funsies) like the closure captures only the evil argument `metadata`, it *<b class="">actually</b>* captures <b class="">Photo (and therefore data)</b></div><div class=""><br class=""></div><div class="">The capture of Photo (data) is somewhat clear when we write</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">evil(self.metadata)</div><div class=""><br class=""></div></blockquote>But it is hidden when we write<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">evil(metadata)</div></blockquote><br class=""><div class="">As you propose.</div><div class=""><br class=""></div><div class="">I think that if we are going to have semantics that capture Photo (data), it had better look like it in a cursory inspection. The existing syntax is not as great as it could be, but it provides a clue.</div></div></div></blockquote><br class=""></div><div>I think I see. Your contention is that `self.metadata` is only just barely a sufficient clue to the capture behavior, and that `[strong self]` at the top of the closure would no longer be good enough.</div><div><br class=""></div><div>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]`.</div><div><br class=""></div><div><br class=""></div>-- <div class="">Greg Parker <a href="mailto:gparker@apple.com" class="">gparker@apple.com</a> Runtime Wrangler</div><div class=""><br class=""></div><div class=""><br class=""></div></body></html>